diff options
| author | sakumisu <[email protected]> | 2026-03-10 21:18:12 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2026-03-11 11:08:28 +0800 |
| commit | f9fe00d6023aaba3228ee0ad272d3e3f6d9b3b34 (patch) | |
| tree | 93d359601790cbbaa99f5db177c9508e373dbd8d | |
| parent | 904b4ca63f90ce8957157824e5be5495f8ff6aa2 (diff) | |
feat(class/hid/usbh_hid): add usbh_hid_report_convert api
Signed-off-by: sakumisu <[email protected]>
| -rw-r--r-- | class/hid/usbh_hid.c | 57 | ||||
| -rw-r--r-- | class/hid/usbh_hid.h | 1 |
2 files changed, 53 insertions, 5 deletions
diff --git a/class/hid/usbh_hid.c b/class/hid/usbh_hid.c index 92db7332..7dddf915 100644 --- a/class/hid/usbh_hid.c +++ b/class/hid/usbh_hid.c @@ -435,11 +435,58 @@ err: return -1; } +int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len) +{ + const uint8_t *src; + uint32_t bits_len = item->attribute.report_size * item->attribute.report_count; + + if(bits_len == 0) { + return -1; + } + + if (item->report_flags & HID_MAINITEM_CONSTANT) { + return -1; + } + + if (item->attribute.report_id > 0) { + if (report_buf[0] != item->attribute.report_id) { + return -2; /* report id mismatch */ + } + + src = report_buf + 1; /* skip report id */ + } else { + src = report_buf; + } + + if ((bits_len < 32) && (bits_len % 8 != 0)) { + *output1 = 0; + + for (uint32_t i = 0; i < bits_len; i++) { + *output1 |= ((src[item->report_bit_offset / 8] >> ((item->report_bit_offset % 8) + i)) & 0x01) << i; + } + + *output2 = NULL; + *output_len = (bits_len + 7) / 8; + return 0; + } else if (bits_len % 8 == 0) { + if (item->report_bit_offset % 8 != 0) { + /* currently do not support item that is not byte aligned */ + return -3; + } + + uint32_t byte_len = bits_len / 8; + *output2 = (uint8_t *)src + item->report_bit_offset / 8; + *output_len = byte_len; + return 0; + } + return -4; +} + static void usbh_hid_item_info_print(struct usbh_hid_report_item *item) { USB_LOG_RAW("Item Type: %s\r\n", (unsigned int)item->report_type == HID_REPORT_INPUT ? "Input" : (unsigned int)item->report_type == HID_REPORT_OUTPUT ? "Output" : - "Feature"); + "Feature"); USB_LOG_RAW("Usage Page: 0x%04x\r\n", (unsigned int)item->attribute.usage_page); USB_LOG_RAW("Report ID: 0x%04x\r\n", (unsigned int)item->attribute.report_id); USB_LOG_RAW("Report Size: %ubit\r\n", (unsigned int)item->attribute.report_size); @@ -452,7 +499,7 @@ static void usbh_hid_item_info_print(struct usbh_hid_report_item *item) USB_LOG_RAW("\r\n"); } -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_report_buf[2048]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_report_desc_buf[2048]; int lshid(int argc, char **argv) { @@ -471,18 +518,18 @@ int lshid(int argc, char **argv) return -1; } - if (hid_class->report_size > sizeof(g_hid_report_buf)) { + if (hid_class->report_size > sizeof(g_hid_report_desc_buf)) { USB_LOG_ERR("hid report buffer is too small\r\n"); return -1; } - ret = usbh_hid_get_report_descriptor(hid_class, g_hid_report_buf, hid_class->report_size); + ret = usbh_hid_get_report_descriptor(hid_class, g_hid_report_desc_buf, hid_class->report_size); if (ret < 0) { USB_LOG_ERR("get hid report descriptor failed, errcode: %d\r\n", ret); return -1; } - ret = usbh_hid_parse_report_descriptor(g_hid_report_buf, hid_class->report_size, &report_info); + ret = usbh_hid_parse_report_descriptor(g_hid_report_desc_buf, hid_class->report_size, &report_info); if (ret < 0) { USB_LOG_ERR("parse hid report descriptor failed\r\n"); return -1; diff --git a/class/hid/usbh_hid.h b/class/hid/usbh_hid.h index d58c8e1d..26b22555 100644 --- a/class/hid/usbh_hid.h +++ b/class/hid/usbh_hid.h @@ -70,6 +70,7 @@ int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen); int usbh_hid_parse_report_descriptor(const uint8_t *report_data, uint32_t report_size, struct usbh_hid_report_info *report_info); +int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len); void usbh_hid_run(struct usbh_hid *hid_class); void usbh_hid_stop(struct usbh_hid *hid_class); |
