From ffdcf9a0d00ad8eba544c4404e27275685ef9cab Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 13:54:39 +0700 Subject: move report_info to application update API accordingly, update hid parser for usage, and usage_page. --- src/class/hid/hid_host.c | 201 ++++++++++++++++++++++++++++------------------- src/class/hid/hid_host.h | 54 ++++++------- 2 files changed, 143 insertions(+), 112 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4c32d9b33..0ffd32617 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,16 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_protocol; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol - - tuh_hid_report_info_t report_info; - - // Parsed Report ID for convenient API - uint8_t rid_keyboard; - uint8_t rid_mouse; - uint8_t rid_gamepad; - uint8_t rid_consumer; + uint8_t boot_interface; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; @@ -107,49 +99,30 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_protocol; + return hid_itf->boot_interface; } -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->boot_mode; } -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance) -{ - return &get_instance(dev_addr, instance)->report_info; -} - -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) -{ - TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); - - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); -} - -//--------------------------------------------------------------------+ -// KEYBOARD -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO check rid_keyboard - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +//{ +// +//} -// TODO remove -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) +//{ +// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); +// +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); +// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +//} //--------------------------------------------------------------------+ // USBH API @@ -167,10 +140,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_cb) - { - tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - } + TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); + TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); @@ -197,7 +169,6 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len); static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -228,40 +199,40 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + hid_itf->boot_interface = desc_itf->bInterfaceProtocol; if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Keyboard\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->report_info.info[0].in_len = 8; - hid_itf->report_info.info[0].out_len = 1; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; +// hid_itf->report_info.info[0].in_len = 8; +// hid_itf->report_info.info[0].out_len = 1; } else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Mouse\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->report_info.info[0].in_len = 5; - hid_itf->report_info.info[0].out_len = 0; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; +// hid_itf->report_info.info[0].in_len = 5; +// hid_itf->report_info.info[0].out_len = 0; } else { @@ -344,15 +315,8 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; - if (tuh_hid_descriptor_report_cb) - { - tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); - } - - parse_report_descriptor(hid_itf, desc_report, desc_len); - // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); @@ -363,8 +327,11 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } -// Parse Report Descriptor to tuh_hid_report_info_t -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) +//--------------------------------------------------------------------+ +// Report Descriptor Parser +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED @@ -378,7 +345,20 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de }; } header; - while(desc_len) + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info; + + tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + + // current parsed report count & size from descriptor +// uint8_t ri_report_count = 0; +// uint8_t ri_report_size = 0; + + uint8_t ri_collection_depth = 0; + uint16_t ri_usage_page = 0; + uint8_t ri_usage = 0; + + while(desc_len && report_num < arr_count) { header.byte = *desc_report++; desc_len--; @@ -387,6 +367,8 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de uint8_t const type = header.type; uint8_t const size = header.size; + uint8_t const data8 = desc_report[0]; + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; iusage_page = ri_usage_page; + info->usage = ri_usage; + }else + { + TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count); + } + break; + + case RI_GLOBAL_REPORT_SIZE: +// ri_report_size = data8; + break; + + case RI_GLOBAL_REPORT_COUNT: +// ri_report_count = data8; + break; + case RI_GLOBAL_UNIT_EXPONENT : break; case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_REPORT_SIZE : break; - case RI_GLOBAL_REPORT_ID : break; - case RI_GLOBAL_REPORT_COUNT : break; case RI_GLOBAL_PUSH : break; case RI_GLOBAL_POP : break; @@ -429,7 +450,11 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de case RI_TYPE_LOCAL: switch(tag) { - case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE: + // only take in account the "usage" before starting COLLECTION + if ( ri_collection_depth == 0) ri_usage = data8; + break; + case RI_LOCAL_USAGE_MIN : break; case RI_LOCAL_USAGE_MAX : break; case RI_LOCAL_DESIGNATOR_INDEX : break; @@ -448,8 +473,22 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de } desc_report += size; - desc_len -= size; + desc_len -= size; } + + if ( report_num == 0 ) + { + report_info[0].usage_page = ri_usage_page; + report_info[0].usage = ri_usage; + } + + for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ ) + { + info = report_info+i; + TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage); + } + + return report_num; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index b000cdfcb..122f57088 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,17 +53,12 @@ typedef struct { - uint8_t count; // number of info + uint16_t usage_page; + uint8_t usage; - struct - { - uint8_t usage_page; - uint8_t usage; - - // TODO still use the endpoint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - } info[CFG_TUH_HID_REPORT_MAX]; + // TODO still use the endpoint size for now +// uint8_t in_len; // length of IN report +// uint8_t out_len; // length of OUT report } tuh_hid_report_info_t; //--------------------------------------------------------------------+ @@ -79,47 +74,44 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); -// Get boot protocol check out hid_protocol_type_t for possible value -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance); +// Get boot interface protocol check out hid_protocol_type_t for possible value +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); + +// Get current protocol mode: Boot (true) or Report (false) +// By HID spec, device will be initialized in Report mode +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance); +// Set protocol to Boot or Report mode. +// This function is only supported by Boot interface tuh_n_hid_n_boot_interface() +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode); -// Get Report information parsed from report descriptor. Data must not be modified by application -// If report information does not match the actual device descriptor, that is because the built-in parser -// has its limit. Application could use tuh_hid_descriptor_report_cb() callback to parse descriptor by itself. -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance); +// Parse report descriptor into array of report_info struct and return number of reports. +// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. +// For complicated report, application should write its own parser. +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; // Check if the interface is ready to use -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); // Set Report using control endpoint //bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); //------------- -------------// -// Check if HID instance with Keyboard is mounted -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance); - -// Check if HID instance with Mouse is mounted -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ -// Invoked when report descriptor is received -// Note: enumeration is still not complete yet at this time -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - // Invoked when device with hid interface is mounted -TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint -TU_ATTR_WEAK void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either regular or control endpoint TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); -- cgit v1.3.1