Thanks TIC.
We made bit more progress and here is the description of our problem now. I have included the descriptor file, and also python code we use as a host in case you need.
When we don’t define report ID in our report descriptor, it takes the default ID that is ‘0’. In that case, we didn’t have to set report ID in the input or feature report we are sending. It looked like ROM stack was adding the report ID. For example, the input buffer looked like this
[20,21,22,23,24,25,26,27]
The host receives this
[0, 20,21,22,23,24,25,26,27]
However, when we specify a report ID say 1 for the input report, as per your suggestion we added the report ID as the first byte and now the host receives
For example, report ID with ‘1’ our input buffer at the device side looks like this
[1,20,21,22,23,24,25,26,27]
And the
The host receives this
[1, 20,21,22,23,24,25,26,27]
Now regarding Report Descriptor with multiple report IDs
Here are our descriptor and the code too.
Our understanding is, we can define different report ID so that we can utilize the bus efficiently. For example, if a feature Report with ID as 2 can have 2 bytes and another feature report with ID as 3 can have 64 bytes and report ID 2 results in 2 bytes transfer and report ID 3 results in 64 bytes transfer. Is that true? In our case, reports are sent padding. For example, if the HID_FEATURE_REPORT_BYTES is defined 64, then all feature reports are sent as 64 bytes.
For example, feature report with ID ‘2’ looks like this at the device side
[2,10,11]
Then the host receives this
[2,10,11,0,0------0] – Total 65 bytes – because as I mentioned HID_FEATURE_REPORT_BYTES is defined 64.
What is that we need to do if we want to send different length reports without padding?
Our descriptor
define HID_INPUT_REPORT_BYTES 8 /* size of report in Bytes */
#define HID_OUTPUT_REPORT_BYTES 64 /* size of report in Bytes */
#define HID_FEATURE_REPORT_BYTES 64 /* size of report in Bytes */
const uint8_t HID_ReportDescriptor[] = {
HID_UsagePageVendor(0x45),
HID_Usage(0x00), //name of hhe usage for the entire application
HID_Collection(HID_Application),
HID_Usage(0xA010), //name of the usage for the entire input report
HID_ReportID(0x01),
HID_Collection(HID_Logical),
HID_Usage(0xA011),
HID_Usage(0xA012),
HID_Usage(0xA013),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(3),
HID_Input(HID_Variable),
HID_Usage(0xA014),
HID_Usage(0xA015),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xF),
HID_ReportSize(4),
HID_ReportCount(2),
HID_Input(HID_Variable),
HID_Usage(0xA016),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(4),
HID_Input(HID_Variable),
HID_EndCollection, //end of input collection
HID_ReportID(0x02),
HID_ReportSize(8),
HID_ReportCount(HID_OUTPUT_REPORT_BYTES),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_Usage(0xA020),
HID_Output(HID_Variable),
HID_Usage(0xA0001), //name of the usage for the entire feature report
HID_ReportID(0x03),
HID_Collection(HID_Logical),
HID_Usage(0xA0002),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(1),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0xA0003),
HID_Usage(0xA0004),
HID_LogicalMin(0), // value range: 0 - 0xF
HID_LogicalMaxS(0xF),
HID_ReportSize(4),
HID_ReportCount(2),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0xA0005),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(1),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0xA0006),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(61),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_EndCollection, //end of feature
//testing another feature report with ID 4 format is the same
HID_Usage(0x30), //name of the usage for the entire feature report
HID_ReportID(0x04),
HID_Collection(HID_Logical),
HID_Usage(0x32),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(1),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0x33),
HID_Usage(0x34),
HID_LogicalMin(0), // value range: 0 - 0xF
HID_LogicalMaxS(0xF),
HID_ReportSize(4),
HID_ReportCount(2),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0x35),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(1),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_Usage(0x36),
HID_LogicalMin(0), // value range: 0 - 0xFF
HID_LogicalMaxS(0xFF),
HID_ReportSize(8),
HID_ReportCount(5),
HID_Feature(HID_Variable| HID_Volatile), //device might change
HID_EndCollection, //end of feature
HID_EndCollection,
};
The initialization routine
/* HID init routine */
ErrorCode_t usb_hid_init(USBD_HANDLE_T hUsb,
USB_INTERFACE_DESCRIPTOR *pIntfDesc,
uint32_t *mem_base,
uint32_t *mem_size)
{
USBD_HID_INIT_PARAM_T hid_param;
USB_HID_REPORT_T reports_data[1];
ErrorCode_t ret = LPC_OK;
uint16_t count = 0;
memset((void *) &hid_param, 0, sizeof(USBD_HID_INIT_PARAM_T));
/* HID paramas */
hid_param.max_reports = 1;
/* Init reports_data */
reports_data[0].len = HID_ReportDescSize;
reports_data[0].idle_time = 0;
reports_data[0].desc = (uint8_t *) &HID_ReportDescriptor[0];
if ((pIntfDesc == 0) || (pIntfDesc->bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE)) {
return ERR_FAILED;
}
hid_param.mem_base = *mem_base;
hid_param.mem_size = *mem_size;
hid_param.intf_desc = (uint8_t *) pIntfDesc;
/* user defined functions */
hid_param.HID_GetReport = HID_GetReport;
hid_param.HID_SetReport = HID_SetReport;
hid_param.HID_EpIn_Hdlr = HID_Ep_Hdlr;
hid_param.HID_EpOut_Hdlr = HID_Ep_Hdlr;
hid_param.report_data = reports_data;
ret = USBD_API->hid->init(hUsb, &hid_param);
/* allocate USB accessable memory space for report data */
//loopback_report = (uint8_t *) hid_param.mem_base;
output_report = (uint8_t *) hid_param.mem_base;
//bns 3/8 - since we are using 64 bytes make it 64 - originally it was 4
hid_param.mem_base += 65;
hid_param.mem_size += 65;
//bns adding onout and out put
input_report = (uint8_t *) hid_param.mem_base;
memset((uint8_t*) input_report, 0, 65);
//bns 3/8 - since we are using 64 bytes make it 64 - originally it was 4
hid_param.mem_base += 65;
hid_param.mem_size += 65;
//bns adding feature
feature_report = (uint8_t *) hid_param.mem_base;
memset((uint8_t*) feature_report, 0, 65);
//bns 3/8 - since we are using 64 bytes make it 64 -
hid_param.mem_base += 65;
hid_param.mem_size += 65;
/* update memory variables */
/* update memory variables */
*mem_base = hid_param.mem_base;
*mem_size = hid_param.mem_size;
//bns 3/8 initlaize bit of inout so that we know what we are sending for test
for (int i = 0;i<10;i++)
input_report[i] =i+20;
//bns 3/14 initialize bit of feature so that we know what we are sending for test
for (int i = 0;i<10;i++)
feature_report[i] =i+10;
return LPC_OK;
}
And now the get report code
static ErrorCode_t HID_GetReport(USBD_HANDLE_T hHid, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t *plength)
{
uint8_t ReportID = pSetup->wValue.WB.L;
switch (pSetup->wValue.WB.H) {
case HID_REPORT_INPUT:
//now think if different report ID
switch (ReportID)
{
case 0: //when we don't define
//Can't assign explicitly 0 as report ID, but it is assigned default , in that case
// USB stack adds report ID as the first byte so not required to assign explicitly
//In general, we are using first byte as the report ID in the input buffer and second byte onwards data
//and due to what we mentioned earlier, just give data that is input_report second byte onwards
*pBuffer = input_report+1;
*plength = 8;
break;
case 1: //when we defined report ID as 1
//as we are testing different report ID etc add report ID here, much easier and no confusion
//after concluding about report ID can initialize as part of initialization routine
input_report[0] = 1;
input_report[1] = 11;
*pBuffer = input_report;
*plength = 8;
break;
case 4: //when we defined report ID as 1
//as we are testing different report ID etc add report ID here, much easier and no confusion
//after concluding about report ID can initialize as part of initialization routine
input_report[0] = 4;
//change data to test
input_report[1] = 44;
*pBuffer = input_report;
*plength = 8;
break;
}
break;
case HID_REPORT_OUTPUT:
//bns 3/19 shoudl never be here !
return ERR_USBD_STALL; // Not Supported
break;
case HID_REPORT_FEATURE:
switch (ReportID)
{
case 0: //when we don't define
//add report ID here no confusion
// feature_report[0] = 0;
*pBuffer = feature_report+1;
*plength = 64;
break;
case 1:
//as we are testing different report ID etc add report ID here, much easier and no confusion
//after concluding about report ID can initialize as part of initialization routine
feature_report[0] = 1;
*pBuffer = feature_report;
*plength = 64;
break;
case 3: // when we define report ID as 3
//as we are testing different report ID etc add report ID here, much easier and no confusion
//after concluding about report ID can initialize as part of initialization routine
feature_report[0] = 3;
//just to test different data
feature_report[1]=33;
*pBuffer = feature_report;
*plength = 64;
break;
case 4: // when we define report ID as 3
//as we are testing different report ID etc add report ID here, much easier and no confusion
//after concluding about report ID can initialize as part of initialization routine
feature_report[0] = 4;
//just to test different data
feature_report[1]=44;
*pBuffer = feature_report;
*plength = 8;
break;
}
break;
}
return LPC_OK;
}
Thanks