From ffdcf9a0d00ad8eba544c4404e27275685ef9cab Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 13:54:39 +0700 Subject: [PATCH] move report_info to application update API accordingly, update hid parser for usage, and usage_page. --- examples/host/cdc_msc_hid/src/hid_app.c | 209 ++++++++++++++++++++++++ examples/host/cdc_msc_hid/src/main.c | 124 +------------- src/class/hid/hid_host.c | 201 ++++++++++++++--------- src/class/hid/hid_host.h | 54 +++--- 4 files changed, 356 insertions(+), 232 deletions(-) create mode 100644 examples/host/cdc_msc_hid/src/hid_app.c diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c new file mode 100644 index 000000000..4f8556274 --- /dev/null +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -0,0 +1,209 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define MAX_REPORT 4 + +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +static uint8_t _report_count[CFG_TUH_HID]; +static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT]; + +static void process_kbd_report(hid_keyboard_report_t const *report); +static void process_mouse_report(hid_mouse_report_t const * report); + +void hid_app_task(void) +{ +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len); + + if (_report_count[instance]) + { + printf("Composite with %u reports", _report_count[instance]); + }else + { + printf("Single report"); + } + + // Interface protocol + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t + uint8_t const interface_protocol = tuh_n_hid_n_interface_protocol(dev_addr, instance); + printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); +} + +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +{ + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +} + +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + uint8_t const rpt_count = _report_count[instance]; + tuh_hid_report_info_t* rpt_info; + + if (rpt_count) + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + // Note: report index = report ID - 1 + uint8_t idx = report[0] - 1; + rpt_info = &_report_info[instance][idx]; + + report++; + }else + { + rpt_info = &_report_info[instance][0]; + } + + if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP ) + { + switch (rpt_info->usage) + { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) +{ + for(uint8_t i=0; i<6; i++) + { + if (report->keycode[i] == keycode) return true; + } + + return false; +} + +static void process_kbd_report(hid_keyboard_report_t const *report) +{ + static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for(uint8_t i=0; i<6; i++) + { + if ( report->keycode[i] ) + { + if ( find_key_in_report(&prev_report, report->keycode[i]) ) + { + // exist in previous report means the current key is holding + }else + { + // not existed in previous report means the current key is pressed + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if ( ch == '\r' ) putchar('\n'); // added new line for enter key + + fflush(stdout); // flush right away, else nanolib will wait for newline + } + } + // TODO example skips key released + } + + prev_report = *report; +} + +//--------------------------------------------------------------------+ +// Mouse +//--------------------------------------------------------------------+ + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + // Move X using ansi escape + if ( x < 0) + { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) + { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + } + + // Move Y using ansi escape + if ( y < 0) + { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) + { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + } + + // Scroll using ansi escape + if (wheel < 0) + { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) + { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + } +} + +static void process_mouse_report(hid_mouse_report_t const * report) +{ + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; + if ( button_changed_mask & report->buttons) + { + printf(" %c%c%c ", + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(report->x, report->y, report->wheel); +} diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 40642561b..7ae814e38 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -37,7 +37,7 @@ void print_greeting(void); void led_blinking_task(void); extern void cdc_task(void); -extern void hid_task(void); +extern void hid_app_task(void); /*------------- MAIN -------------*/ int main(void) @@ -58,7 +58,7 @@ int main(void) #endif #if CFG_TUH_HID - hid_task(); + hid_app_task(); #endif } @@ -106,127 +106,11 @@ void cdc_task(void) #endif //--------------------------------------------------------------------+ -// USB HID -//--------------------------------------------------------------------+ -uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; - -// look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) -{ - for(uint8_t i=0; i<6; i++) - { - if (p_report->keycode[i] == keycode) return true; - } - - return false; -} - -static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) -{ - static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released - - //------------- example code ignore control (non-printable) key affects -------------// - for(uint8_t i=0; i<6; i++) - { - if ( p_new_report->keycode[i] ) - { - if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) ) - { - // exist in previous report means the current key is holding - }else - { - // not existed in previous report means the current key is pressed - bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); - uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0]; - putchar(ch); - if ( ch == '\r' ) putchar('\n'); // added new line for enter key - - fflush(stdout); // flush right away, else nanolib will wait for newline - } - } - // TODO example skips key released - } - - prev_report = *p_new_report; -} - -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -void cursor_movement(int8_t x, int8_t y, int8_t wheel) -{ - //------------- X -------------// - if ( x < 0) - { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) - { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - }else { } - - //------------- Y -------------// - if ( y < 0) - { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) - { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - }else { } - - //------------- wheel -------------// - if (wheel < 0) - { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) - { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - }else { } -} - -static inline void process_mouse_report(hid_mouse_report_t const * p_report) -{ - static hid_mouse_report_t prev_report = { 0 }; - - //------------- button state -------------// - uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; - if ( button_changed_mask & p_report->buttons) - { - printf(" %c%c%c ", - p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); - } - - //------------- cursor movement -------------// - cursor_movement(p_report->x, p_report->y, p_report->wheel); -} - -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - process_kbd_report( (hid_keyboard_report_t*) report ); -} - -void hid_task(void) -{ -} - -//--------------------------------------------------------------------+ -// tinyusb callbacks +// TinyUSB Callbacks //--------------------------------------------------------------------+ //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ void led_blinking_task(void) { 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_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +//{ +// +//} -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); -} - -// 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); -// Check if current mode is Boot (true) or Report (false) -bool tuh_n_hid_n_boot_mode(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); -// 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); +// 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); + +// 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);