summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-03-18 14:06:37 +0700
committerGitHub <[email protected]>2026-03-18 14:06:37 +0700
commit8f7f286ae347ec1adbfd0888d65fb1aeb263b7d2 (patch)
tree1cabd047e3ebe4756367abed214ea5a84212799e
parent151a5ad1984a9706aedbe9d26411c33202760007 (diff)
parenta46c863cc0adae61b28f00ad82a4ca6f53052a81 (diff)
Merge pull request #3558 from hathach/hid-host-set-protocol-skipable
Add `CFG_TUH_HID_SET_PROTOCOL_ON_ENUM` configuration option
-rw-r--r--src/class/hid/hid_host.c31
-rw-r--r--src/class/hid/hid_host.h11
2 files changed, 24 insertions, 18 deletions
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index 98f9bf80b..7935b84d3 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -240,7 +240,7 @@ void tuh_hid_set_default_protocol(uint8_t protocol) {
_hidh_default_protocol = protocol;
}
-static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol,
+static bool hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol);
@@ -272,7 +272,7 @@ bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid && p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE);
- return _hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0);
+ return hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0);
}
static void get_report_complete(tuh_xfer_t* xfer) {
@@ -359,7 +359,7 @@ bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r
return tuh_control_xfer(&xfer);
}
-static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate,
+static bool hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// SET IDLE request, device can stall if not support this request
TU_LOG_DRV("HID Set Idle \r\n");
@@ -566,8 +566,8 @@ uint16_t hidh_open(uint8_t rhport, uint8_t daddr, const tusb_desc_interface_t *d
// Use offsetof to avoid pointer to the odd/misaligned address
p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*)desc_hid + offsetof(tusb_hid_descriptor_hid_t, wReportLength));
- // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config
- p_hid->protocol_mode = _hidh_default_protocol;
+ // Per HID Specs: default is Report protocol
+ p_hid->protocol_mode = HID_PROTOCOL_REPORT;
if (HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass) {
p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
}
@@ -623,25 +623,30 @@ static void process_set_config(tuh_xfer_t* xfer) {
switch (state) {
case CONFG_SET_IDLE: {
- // Idle rate = 0 mean only report when there is changes
+ // Idle rate = 0 mean only report when there are changes
const uint16_t idle_rate = 0;
const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE)
? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC;
- _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state);
+ hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state);
break;
}
case CONFIG_SET_PROTOCOL:
- _hidh_set_protocol(daddr, p_hid->itf_num, _hidh_default_protocol, process_set_config, CONFIG_GET_REPORT_DESC);
+ #if CFG_TUH_HID_SET_PROTOCOL_ON_ENUM
+ hidh_set_protocol(daddr, p_hid->itf_num, _hidh_default_protocol, process_set_config, CONFIG_GET_REPORT_DESC);
break;
+ #else
+ TU_ATTR_FALLTHROUGH;
+ #endif
case CONFIG_GET_REPORT_DESC:
+ if (xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL && xfer->result == XFER_RESULT_SUCCESS) {
+ p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue);
+ }
// Get Report Descriptor if possible
- // using usbh enumeration buffer since report descriptor can be very long
+ // using usbh enumeration buffer since the report descriptor can be very long
if (p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE) {
TU_LOG_DRV("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len);
-
- // Driver is mounted without report descriptor
config_driver_mount_complete(daddr, idx, NULL, 0);
} else {
tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0,
@@ -651,8 +656,8 @@ static void process_set_config(tuh_xfer_t* xfer) {
break;
case CONFIG_COMPLETE: {
- uint8_t const* desc_report = usbh_get_enum_buf();
- uint16_t const desc_len = tu_le16toh(xfer->setup->wLength);
+ const uint8_t *desc_report = usbh_get_enum_buf();
+ const uint16_t desc_len = tu_le16toh(xfer->setup->wLength);
config_driver_mount_complete(daddr, idx, desc_report, desc_len);
break;
diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h
index d7a415485..922848fc2 100644
--- a/src/class/hid/hid_host.h
+++ b/src/class/hid/hid_host.h
@@ -36,7 +36,6 @@ extern "C" {
//--------------------------------------------------------------------+
// Class Driver Configuration
//--------------------------------------------------------------------+
-
// TODO Highspeed interrupt can be up to 512 bytes
#ifndef CFG_TUH_HID_EPIN_BUFSIZE
#define CFG_TUH_HID_EPIN_BUFSIZE 64
@@ -46,7 +45,13 @@ extern "C" {
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
#endif
+#ifndef CFG_TUH_HID_SET_PROTOCOL_ON_ENUM
+ #define CFG_TUH_HID_SET_PROTOCOL_ON_ENUM 1
+#endif
+//--------------------------------------------------------------------+
+// Interface API
+//--------------------------------------------------------------------+
typedef struct {
uint8_t report_id;
uint8_t usage;
@@ -57,10 +62,6 @@ typedef struct {
// uint8_t out_len; // length of OUT report
} tuh_hid_report_info_t;
-//--------------------------------------------------------------------+
-// Interface API
-//--------------------------------------------------------------------+
-
// Get the total number of mounted HID interfaces of a device
uint8_t tuh_hid_itf_get_count(uint8_t dev_addr);