diff options
| author | Ha Thach <[email protected]> | 2021-05-22 22:56:17 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-05-22 22:56:17 +0700 |
| commit | 56577d9fcab58680b22d86be6ecac0a16f96f659 (patch) | |
| tree | 445278bc5e2aba1e9fbdc8cd064c5e4f09ee8ac2 /examples | |
| parent | cdb063f007f16f5cfad7b4c05fc117da5f251b26 (diff) | |
| parent | f13a3c04f790a865472a7ed0b57182f401189977 (diff) | |
Merge pull request #834 from hathach/host-hid
Rework Host hid
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/host/cdc_msc_hid/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/hid_app.c | 237 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/keyboard_helper.h | 59 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/main.c | 205 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/msc_app.c | 2 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/tusb_config.h | 11 |
6 files changed, 257 insertions, 258 deletions
diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index a9a4f08ad..ac57bf6dd 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -19,6 +19,7 @@ if(FAMILY STREQUAL "rp2040") # Example source target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_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..23ab12404 --- /dev/null +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -0,0 +1,237 @@ +/* + * 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 +//--------------------------------------------------------------------+ + +// If your host terminal support ansi escape code, it can be use to simulate mouse cursor +#define USE_ANSI_ESCAPE 0 + +#define MAX_REPORT 4 + +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +// Each HID instance can has multiple reports +static uint8_t _report_count[CFG_TUH_HID]; +static tuh_hid_report_info_t _report_info_arr[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) +{ + // nothing to do +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +void tuh_hid_mount_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); + + // Interface protocol + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t + uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len); + printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); +} + +// Invoked when device with hid interface is un-mounted +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) +{ + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +} + +// Invoked when received report from device via interrupt endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + (void) dev_addr; + + uint8_t const rpt_count = _report_count[instance]; + tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; + tuh_hid_report_info_t* rpt_info = NULL; + + if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) + { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + }else + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; i<rpt_count; i++) + { + if (rpt_id == rpt_info_arr[i].report_id ) + { + rpt_info = &rpt_info_arr[i]; + break; + } + } + + report++; + len--; + } + + if (!rpt_info) + { + printf("Couldn't find the report info for this report !\r\n"); + return; + } + + 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) +{ +#if USE_ANSI_ESCAPE + // 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 + } + + printf("\r\n"); +#else + printf("(%d %d %d)\r\n", x, y, wheel); +#endif +} + +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/keyboard_helper.h b/examples/host/cdc_msc_hid/src/keyboard_helper.h deleted file mode 100644 index 1fde2768c..000000000 --- a/examples/host/cdc_msc_hid/src/keyboard_helper.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef KEYBOARD_HELPER_H -#define KEYBAORD_HELPER_H - -#include <stdbool.h> -#include <stdint.h> - -#include "tusb.h" - -// look up new key in previous keys -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; -} - -inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) -{ - return keycode > 128 ? 0 : - hid_keycode_to_ascii_tbl [keycode][modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0]; -} - -void print_kbd_report(hid_keyboard_report_t *prev_report, hid_keyboard_report_t const *new_report) -{ - - printf("Report: "); - uint8_t c; - - // I assume it's possible to have up to 6 keypress events per report? - for (uint8_t i = 0; i < 6; i++) - { - // Check for key presses - if (new_report->keycode[i]) - { - // If not in prev report then it is newly pressed - if ( !find_key_in_report(prev_report, new_report->keycode[i]) ) - c = keycode_to_ascii(new_report->modifier, new_report->keycode[i]); - printf("press %c ", c); - } - - // Check for key depresses (i.e. was present in prev report but not here) - if (prev_report->keycode[i]) - { - // If not present in the current report then depressed - if (!find_key_in_report(new_report, prev_report->keycode[i])) - { - c = keycode_to_ascii(prev_report->modifier, prev_report->keycode[i]); - printf("depress %c ", c); - } - } - } - - printf("\n"); -} - -#endif
\ No newline at end of file diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c6ab54682..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) @@ -51,15 +51,14 @@ int main(void) { // tinyusb host task tuh_task(); - led_blinking_task(); #if CFG_TUH_CDC cdc_task(); #endif -#if CFG_TUH_HID_KEYBOARD || CFG_TUH_HID_MOUSE - hid_task(); +#if CFG_TUH_HID + hid_app_task(); #endif } @@ -107,184 +106,11 @@ void cdc_task(void) #endif //--------------------------------------------------------------------+ -// USB HID +// TinyUSB Callbacks //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD - -CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; -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_keyboard_mounted_cb(uint8_t dev_addr) -{ - // application set-up - printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); - - tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); -} - -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) -{ - // application tear-down - printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); -} - -// invoked ISR context -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} - -#endif - -#if CFG_TUH_HID_MOUSE - -CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; - -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_mouse_mounted_cb(uint8_t dev_addr) -{ - // application set-up - printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) -{ - // application tear-down - printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -// invoked ISR context -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} -#endif - - - -void hid_task(void) -{ - uint8_t const addr = 1; - -#if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_is_mounted(addr) ) - { - if ( !tuh_hid_keyboard_is_busy(addr) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); - } - } -#endif - -#if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_is_mounted(addr) ) - { - if ( !tuh_hid_mouse_is_busy(addr) ) - { - process_mouse_report(&usb_mouse_report); - tuh_hid_mouse_get_report(addr, &usb_mouse_report); - } - } -#endif -} - -//--------------------------------------------------------------------+ -// tinyusb callbacks //--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ void led_blinking_task(void) { @@ -316,23 +142,12 @@ void print_greeting(void) [OPT_OS_RTTHREAD] = "RT-Thread" }; - printf("--------------------------------------------------------------------\r\n"); - printf("- Host example\r\n"); - printf("- if you find any bugs or get any questions, feel free to file an\r\n"); - printf("- issue at https://github.com/hathach/tinyusb\r\n"); - printf("--------------------------------------------------------------------\r\n\r\n"); + printf("----------------------------------------------------\r\n"); + printf("TinyUSB Host Example\r\n"); + printf("If you find any bugs or problems, feel free to open\r\n"); + printf("an issue at https://github.com/hathach/tinyusb\r\n"); + printf("----------------------------------------------------\r\n\r\n"); printf("This Host demo is configured to support:\r\n"); printf(" - RTOS = %s\r\n", rtos_name[CFG_TUSB_OS]); - -#if CFG_TUH_CDC - printf(" - Communication Device Class\r\n"); -#endif - -#if CFG_TUH_MSC - printf(" - Mass Storage\r\n"); -#endif - -// if (CFG_TUH_HID_KEYBOARD ) puts(" - HID Keyboard"); -// if (CFG_TUH_HID_MOUSE ) puts(" - HID Mouse"); } diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 3a8ef3a07..3657a3d35 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -80,7 +80,7 @@ void tuh_msc_mount_cb(uint8_t dev_addr) // } } -void tuh_msc_unmount_cb(uint8_t dev_addr) +void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fabc7765c..8253964c0 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -71,16 +71,21 @@ // CONFIGURATION //-------------------------------------------------------------------- +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSZIE 256 + #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 -#define CFG_TUH_HID_KEYBOARD 1 -#define CFG_TUH_HID_MOUSE 1 -#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) +#define CFG_TUH_HID 2 #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports +//------------- HID -------------// + +#define CFG_TUH_HID_EP_BUFSIZE 64 + #ifdef __cplusplus } #endif |
