2025-06-14 10:05 AM - last edited on 2025-07-02 2:43 AM by Andrew Neil
Hi,
I would like to consult the USB HID GetReport feature.
The issue is that the printout data from MCU log is different from bus hound displayed result.
Bus hound is trial version, the data length indeed is 16.
This is the log I set to printout from USBD_HID_Keyboard_SetReport
#define UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH 32
static uint8_t g_last_input_report[17]; // adjust size to match your report
static UINT g_last_input_report_len = 0;
/**
* @brief USBD_HID_Keyboard_GetReport
* This function is invoked when host is requesting event through
* control GET_REPORT request.
* hid_instance: Pointer to the hid class instance.
* hid_event: Pointer to structure of the hid event.
* @retval status
*/
UINT USBD_HID_Keyboard_GetReport(UX_SLAVE_CLASS_HID *hid_instance,
UX_SLAVE_CLASS_HID_EVENT *hid_event) {
printf(">>> USBD_HID_Keyboard_GetReport invoked\r\n");
static uint32_t get_report_counter = 0;
printf("=== GET_REPORT #%lu at %lu ms ===\r\n", ++get_report_counter, HAL_GetTick());
if (hid_event == UX_NULL || g_last_input_report_len == 0)
return UX_ERROR;
//Type1:Input ;; Type3:Feature
printf(">>> GetReport Request: type=%lu, id=0x%02lX\r\n, Buffer len: %lu\r\n",
hid_event->ux_device_class_hid_event_report_type,
hid_event->ux_device_class_hid_event_report_id,
g_last_input_report_len);
if (hid_event->ux_device_class_hid_event_report_id== 0x01&&
hid_event->ux_device_class_hid_event_report_type == UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT)
{
if (g_last_input_report_len <= UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH) {
memcpy(hid_event->ux_device_class_hid_event_buffer,
g_last_input_report, g_last_input_report_len);
hid_event->ux_device_class_hid_event_length =
g_last_input_report_len;
printf("GetReport:");
for (UINT i = 0; i < g_last_input_report_len; i++) {
printf("%02X,", g_last_input_report[i]);
}
printf("\r\n");
return UX_SUCCESS;
}
}
printf("ERROR: Conditions not met, returning UX_ERROR\r\n");
return UX_ERROR;
}
Also add the log in _ux_device_class_hid_report_get
However, in here is still show the different data from bus hound capture though it is still aligned the data in GetReport Callback.
The HID descriptor is set as below
__ALIGN_BEGIN uint8_t USBD_HID_KEYBOARD_ReportDesc[]
__ALIGN_END =
{
/* USER CODE BEGIN USBD_HID_KEYBOARD_ReportDesc */
//Wedy Change for customized report
0x06, 0x00, 0xFF, // USAGE PAGE (Vendor Defined)
0x09, 0xFF, // USAGE (Vendor Usage)
0xA1, 0x01, // COLLECTION (Application)
// Feature Report - Report ID 1
0x85, 0x01, // REPORT_ID (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x10, // REPORT_COUNT (16)
0x09, 0x01, // USAGE (Vendor Specific)
0x81, 0x02, // INPUT (Data,Var,Abs)
// Feature Report - Report ID 1 (16 bytes)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x10, // REPORT_COUNT (16)
0x09, 0x02, // USAGE (Vendor Specific)
0xB1, 0x02, // FEATURE (Data,Var,Abs)
// Output Report - Report ID 2
0x85, 0x02, // REPORT_ID (2)
0x95, 0x11, // REPORT_COUNT (17)
0x09, 0x01, // USAGE (Vendor Specific)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
/* USER CODE END USBD_HID_KEYBOARD_ReportDesc */
0xc0 /* End Collection */
};
2025-07-02 9:07 PM
Hi @FBL ,
I found that if I don't proceed _ux_device_class_hid_event_set() inside Keyboard_SendReport as below makred, then I could get the matched data from GetReport.
UINT USBD_HID_Keyboard_GetReport(UX_SLAVE_CLASS_HID *hid_instance,
UX_SLAVE_CLASS_HID_EVENT *hid_event) {
/* USER CODE BEGIN USBD_HID_Keyboard_GetReport */
printf("\r\n=== [GET_REPORT] ===\r\n");
if (hid_event == UX_NULL || g_last_input_report_len == 0) {
if (hid_event != UX_NULL) {
memset(hid_event->ux_device_class_hid_event_buffer, 0, HID_REPORT_TOTAL_SIZE);
hid_event->ux_device_class_hid_event_length = HID_REPORT_TOTAL_SIZE;
}
printf("GetReport ERROR: No data available\r\n");
return UX_SUCCESS;
}
if (hid_event->ux_device_class_hid_event_report_id == 0x01 &&
hid_event->ux_device_class_hid_event_report_type == UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT) {
memcpy(hid_event->ux_device_class_hid_event_buffer,
g_last_input_report, HID_REPORT_TOTAL_SIZE);
hid_event->ux_device_class_hid_event_length = g_last_input_report_len;
printf("Final length set = %lu\r\n", hid_event->ux_device_class_hid_event_length);
printf("USBX sending to host: ");
for (UINT i = 0; i < hid_event->ux_device_class_hid_event_length; i++) {
printf("%02X ", hid_event->ux_device_class_hid_event_buffer[i]);
}
printf("\r\n");
return UX_SUCCESS;
}
printf("ERROR: Report type/id mismatch or unsupported\r\n");
return UX_ERROR;
/* USER CODE END USBD_HID_Keyboard_GetReport */
}
/* USER CODE BEGIN 1 */
///////////////////HID_INPUT_to_HOST//////////////////////
UINT USBD_HID_Keyboard_SendReport(UX_SLAVE_CLASS_HID *hid_instance, uint8_t *report, UINT length)
{
if (hid_instance == UX_NULL || report == UX_NULL || length == 0)
return UX_ERROR;
if (length > HID_REPORT_TOTAL_SIZE) {
printf("Error: Output report too large\r\n");
return UX_ERROR;
}
full_report[0] = 0x01; // Report ID
memcpy(&full_report[1], report, length);
// Store for GetReport
memcpy(g_last_input_report, full_report, HID_REPORT_TOTAL_SIZE);
g_last_input_report_len = HID_REPORT_TOTAL_SIZE;
printf("GetReport prepared (Report ID 0x01): ");
for (UINT i = 0; i < g_last_input_report_len; i++) {
printf("%02X ", g_last_input_report[i]);
}
printf("\r\n");
// Do NOT call _ux_device_class_hid_event_set() here if need to support GetReport instead of OutputReport
/*UX_SLAVE_CLASS_HID_EVENT hid_event;
hid_event.ux_device_class_hid_event_report_id = 0x01;
hid_event.ux_device_class_hid_event_report_type =
UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT;
hid_event.ux_device_class_hid_event_length = sizeof(full_report)-1;
memcpy(hid_event.ux_device_class_hid_event_buffer, full_report,
sizeof(full_report)-1);
printf("Input report to host: ");
for (UINT i = 0; i < sizeof(full_report)-1; i++) {
printf("%02X ", full_report[i]);
}
printf("\r\n");
ux_device_class_hid_event_set(hid_instance, &hid_event);*/
return UX_SUCCESS;
}
Does it sounds reasonable? Is that expected to not have input report while system would like to proceed GetReport?