Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions src/class/hid/hid_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -623,25 +623,27 @@ 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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sync protocol_mode when skipping SET_PROTOCOL on enum

With CFG_TUH_HID_SET_PROTOCOL_ON_ENUM set to 0, this branch falls through to CONFIG_GET_REPORT_DESC without sending SET_PROTOCOL, but the interface state still keeps the preloaded _hidh_default_protocol value (default Boot). For Boot-subclass devices this causes tuh_hid_get_protocol() to report Boot while the device is actually still in Report protocol, so applications that rely on the reported mode can take the wrong path.

Useful? React with 👍 / 👎.


case CONFIG_GET_REPORT_DESC:
// 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,
Expand All @@ -651,8 +653,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;
Expand Down
11 changes: 6 additions & 5 deletions src/class/hid/hid_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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);

Expand Down
Loading