summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2021-05-22 22:56:17 +0700
committerGitHub <[email protected]>2021-05-22 22:56:17 +0700
commit56577d9fcab58680b22d86be6ecac0a16f96f659 (patch)
tree445278bc5e2aba1e9fbdc8cd064c5e4f09ee8ac2 /examples
parentcdb063f007f16f5cfad7b4c05fc117da5f251b26 (diff)
parentf13a3c04f790a865472a7ed0b57182f401189977 (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.txt1
-rw-r--r--examples/host/cdc_msc_hid/src/hid_app.c237
-rw-r--r--examples/host/cdc_msc_hid/src/keyboard_helper.h59
-rw-r--r--examples/host/cdc_msc_hid/src/main.c205
-rw-r--r--examples/host/cdc_msc_hid/src/msc_app.c2
-rw-r--r--examples/host/cdc_msc_hid/src/tusb_config.h11
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