summaryrefslogtreecommitdiff
path: root/examples/host/hid_controller
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2024-05-09 15:51:53 +0200
committerHiFiPhile <[email protected]>2024-05-09 15:51:53 +0200
commit36ce6fad8ca997804a569fe575584b45a1b5fc79 (patch)
treef79aa084a42438667b5e26b588a6f794c9ad1608 /examples/host/hid_controller
parentf607a99127cc9e8dfc3f716f977e6c1bfb6f7c2d (diff)
parent74e57499baac36c4cccf76549259905162031e41 (diff)
Merge branch 'master' into vendor_class_zero_length_transfer
Diffstat (limited to 'examples/host/hid_controller')
-rw-r--r--examples/host/hid_controller/CMakeLists.txt33
-rw-r--r--examples/host/hid_controller/Makefile14
-rw-r--r--examples/host/hid_controller/only.txt14
-rw-r--r--examples/host/hid_controller/src/hid_app.c324
-rw-r--r--examples/host/hid_controller/src/main.c97
-rw-r--r--examples/host/hid_controller/src/tusb_config.h121
6 files changed, 603 insertions, 0 deletions
diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt
new file mode 100644
index 000000000..c1b500dd8
--- /dev/null
+++ b/examples/host/hid_controller/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT} C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile
new file mode 100644
index 000000000..1377f1f90
--- /dev/null
+++ b/examples/host/hid_controller/Makefile
@@ -0,0 +1,14 @@
+include ../../build_system/make/make.mk
+
+INC += \
+ src \
+ $(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += \
+ src/hid_app.c \
+ src/main.c
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+include ../../build_system/make/rules.mk
diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt
new file mode 100644
index 000000000..fee10f9e2
--- /dev/null
+++ b/examples/host/hid_controller/only.txt
@@ -0,0 +1,14 @@
+mcu:KINETIS_KL
+mcu:LPC175X_6X
+mcu:LPC177X_8X
+mcu:LPC18XX
+mcu:LPC40XX
+mcu:LPC43XX
+mcu:MIMXRT1XXX
+mcu:MIMXRT10XX
+mcu:MIMXRT11XX
+mcu:RP2040
+mcu:MSP432E4
+mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c
new file mode 100644
index 000000000..bff830ca2
--- /dev/null
+++ b/examples/host/hid_controller/src/hid_app.c
@@ -0,0 +1,324 @@
+/*
+ * 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_api.h"
+#include "tusb.h"
+
+/* From https://www.kernel.org/doc/html/latest/input/gamepad.html
+ ____________________________ __
+ / [__ZL__] [__ZR__] \ |
+ / [__ TL __] [__ TR __] \ | Front Triggers
+ __/________________________________\__ __|
+ / _ \ |
+ / /\ __ (N) \ |
+ / || __ |MO| __ _ _ \ | Main Pad
+ | <===DP===> |SE| |ST| (W) -|- (E) | |
+ \ || ___ ___ _ / |
+ /\ \/ / \ / \ (S) /\ __|
+ / \________ | LS | ____ | RS | ________/ \ |
+| / \ \___/ / \ \___/ / \ | | Control Sticks
+| / \_____/ \_____/ \ | __|
+| / \ |
+ \_____/ \_____/
+
+ |________|______| |______|___________|
+ D-Pad Left Right Action Pad
+ Stick Stick
+
+ |_____________|
+ Menu Pad
+
+ Most gamepads have the following features:
+ - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST.
+ - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right.
+ - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START.
+ - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also
+ provide a digital button if you press them.
+ - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons
+ are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right.
+ - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors.
+ */
+
+// Sony DS4 report layout detail https://www.psdevwiki.com/ps4/DS4-USB
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t x, y, z, rz; // joystick
+
+ struct {
+ uint8_t dpad : 4; // (hat format, 0x08 is released, 0=N, 1=NE, 2=E, 3=SE, 4=S, 5=SW, 6=W, 7=NW)
+ uint8_t square : 1; // west
+ uint8_t cross : 1; // south
+ uint8_t circle : 1; // east
+ uint8_t triangle : 1; // north
+ };
+
+ struct {
+ uint8_t l1 : 1;
+ uint8_t r1 : 1;
+ uint8_t l2 : 1;
+ uint8_t r2 : 1;
+ uint8_t share : 1;
+ uint8_t option : 1;
+ uint8_t l3 : 1;
+ uint8_t r3 : 1;
+ };
+
+ struct {
+ uint8_t ps : 1; // playstation button
+ uint8_t tpad : 1; // track pad click
+ uint8_t counter : 6; // +1 each report
+ };
+
+ uint8_t l2_trigger; // 0 released, 0xff fully pressed
+ uint8_t r2_trigger; // as above
+
+ // uint16_t timestamp;
+ // uint8_t battery;
+ //
+ // int16_t gyro[3]; // x, y, z;
+ // int16_t accel[3]; // x, y, z
+
+ // there is still lots more info
+
+} sony_ds4_report_t;
+
+typedef struct TU_ATTR_PACKED {
+ // First 16 bits set what data is pertinent in this structure (1 = set; 0 = not set)
+ uint8_t set_rumble : 1;
+ uint8_t set_led : 1;
+ uint8_t set_led_blink : 1;
+ uint8_t set_ext_write : 1;
+ uint8_t set_left_volume : 1;
+ uint8_t set_right_volume : 1;
+ uint8_t set_mic_volume : 1;
+ uint8_t set_speaker_volume : 1;
+ uint8_t set_flags2;
+
+ uint8_t reserved;
+
+ uint8_t motor_right;
+ uint8_t motor_left;
+
+ uint8_t lightbar_red;
+ uint8_t lightbar_green;
+ uint8_t lightbar_blue;
+ uint8_t lightbar_blink_on;
+ uint8_t lightbar_blink_off;
+
+ uint8_t ext_data[8];
+
+ uint8_t volume_left;
+ uint8_t volume_right;
+ uint8_t volume_mic;
+ uint8_t volume_speaker;
+
+ uint8_t other[9];
+} sony_ds4_output_report_t;
+
+static bool ds4_mounted = false;
+static uint8_t ds4_dev_addr = 0;
+static uint8_t ds4_instance = 0;
+static uint8_t motor_left = 0;
+static uint8_t motor_right = 0;
+
+// check if device is Sony DualShock 4
+static inline bool is_sony_ds4(uint8_t dev_addr)
+{
+ uint16_t vid, pid;
+ tuh_vid_pid_get(dev_addr, &vid, &pid);
+
+ return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
+ || (vid == 0x0f0d && pid == 0x005e) // Hori FC4
+ || (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
+ || (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller
+ );
+}
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+void hid_app_task(void)
+{
+ if (ds4_mounted)
+ {
+ const uint32_t interval_ms = 200;
+ static uint32_t start_ms = 0;
+
+ uint32_t current_time_ms = board_millis();
+ if ( current_time_ms - start_ms >= interval_ms)
+ {
+ start_ms = current_time_ms;
+
+ sony_ds4_output_report_t output_report = {0};
+ output_report.set_rumble = 1;
+ output_report.motor_left = motor_left;
+ output_report.motor_right = motor_right;
+ tuh_hid_send_report(ds4_dev_addr, ds4_instance, 5, &output_report, sizeof(output_report));
+ }
+ }
+}
+
+//--------------------------------------------------------------------+
+// 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.
+// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
+// therefore report_desc = NULL, desc_len = 0
+void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
+{
+ (void)desc_report;
+ (void)desc_len;
+ uint16_t vid, pid;
+ tuh_vid_pid_get(dev_addr, &vid, &pid);
+
+ printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
+ printf("VID = %04x, PID = %04x\r\n", vid, pid);
+
+ // Sony DualShock 4 [CUH-ZCT2x]
+ if ( is_sony_ds4(dev_addr) )
+ {
+ if (!ds4_mounted)
+ {
+ ds4_dev_addr = dev_addr;
+ ds4_instance = instance;
+ motor_left = 0;
+ motor_right = 0;
+ ds4_mounted = true;
+ }
+ // request to receive report
+ // tuh_hid_report_received_cb() will be invoked when report is available
+ if ( !tuh_hid_receive_report(dev_addr, instance) )
+ {
+ printf("Error: cannot request to receive report\r\n");
+ }
+ }
+}
+
+// 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);
+ if (ds4_mounted && ds4_dev_addr == dev_addr && ds4_instance == instance)
+ {
+ ds4_mounted = false;
+ }
+}
+
+// check if different than 2
+bool diff_than_2(uint8_t x, uint8_t y)
+{
+ return (x - y > 2) || (y - x > 2);
+}
+
+// check if 2 reports are different enough
+bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
+{
+ bool result;
+
+ // x, y, z, rz must different than 2 to be counted
+ result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
+ diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);
+
+ // check the rest with mem compare
+ result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-6);
+
+ return result;
+}
+
+void process_sony_ds4(uint8_t const* report, uint16_t len)
+{
+ const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
+
+ // previous report used to compare for changes
+ static sony_ds4_report_t prev_report = { 0 };
+
+ uint8_t const report_id = report[0];
+ report++;
+ len--;
+
+ // all buttons state is stored in ID 1
+ if (report_id == 1)
+ {
+ sony_ds4_report_t ds4_report;
+ memcpy(&ds4_report, report, sizeof(ds4_report));
+
+ // counter is +1, assign to make it easier to compare 2 report
+ prev_report.counter = ds4_report.counter;
+
+ // only print if changes since it is polled ~ 5ms
+ // Since count+1 after each report and x, y, z, rz fluctuate within 1 or 2
+ // We need more than memcmp to check if report is different enough
+ if ( diff_report(&prev_report, &ds4_report) )
+ {
+ printf("(x, y, z, rz) = (%u, %u, %u, %u)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz);
+ printf("DPad = %s ", dpad_str[ds4_report.dpad]);
+
+ if (ds4_report.square ) printf("Square ");
+ if (ds4_report.cross ) printf("Cross ");
+ if (ds4_report.circle ) printf("Circle ");
+ if (ds4_report.triangle ) printf("Triangle ");
+
+ if (ds4_report.l1 ) printf("L1 ");
+ if (ds4_report.r1 ) printf("R1 ");
+ if (ds4_report.l2 ) printf("L2 ");
+ if (ds4_report.r2 ) printf("R2 ");
+
+ if (ds4_report.share ) printf("Share ");
+ if (ds4_report.option ) printf("Option ");
+ if (ds4_report.l3 ) printf("L3 ");
+ if (ds4_report.r3 ) printf("R3 ");
+
+ if (ds4_report.ps ) printf("PS ");
+ if (ds4_report.tpad ) printf("TPad ");
+
+ printf("\r\n");
+ }
+
+ // The left and right triggers control the intensity of the left and right rumble motors
+ motor_left = ds4_report.l2_trigger;
+ motor_right = ds4_report.r2_trigger;
+
+ prev_report = ds4_report;
+ }
+}
+
+// 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)
+{
+ if ( is_sony_ds4(dev_addr) )
+ {
+ process_sony_ds4(report, len);
+ }
+
+ // continue to request to receive report
+ if ( !tuh_hid_receive_report(dev_addr, instance) )
+ {
+ printf("Error: cannot request to receive report\r\n");
+ }
+}
diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c
new file mode 100644
index 000000000..05a5ae176
--- /dev/null
+++ b/examples/host/hid_controller/src/main.c
@@ -0,0 +1,97 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 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.
+ *
+ */
+
+/* This example current worked and tested with following controller
+ * - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+void led_blinking_task(void);
+
+extern void cdc_task(void);
+extern void hid_app_task(void);
+
+/*------------- MAIN -------------*/
+int main(void)
+{
+ board_init();
+
+ printf("TinyUSB Host HID Controller Example\r\n");
+ printf("Note: Events only displayed for explicit supported controllers\r\n");
+
+ // init host stack on configured roothub port
+ tuh_init(BOARD_TUH_RHPORT);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ while (1)
+ {
+ // tinyusb host task
+ tuh_task();
+ led_blinking_task();
+
+#if CFG_TUH_CDC
+ cdc_task();
+#endif
+
+#if CFG_TUH_HID
+ hid_app_task();
+#endif
+ }
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+void led_blinking_task(void)
+{
+ const uint32_t interval_ms = 1000;
+ static uint32_t start_ms = 0;
+
+ static bool led_state = false;
+
+ // Blink every interval ms
+ if ( board_millis() - start_ms < interval_ms) return; // not enough time
+ start_ms += interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state; // toggle
+}
diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h
new file mode 100644
index 000000000..3ac591d8f
--- /dev/null
+++ b/examples/host/hid_controller/src/tusb_config.h
@@ -0,0 +1,121 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 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.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// Common Configuration
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_NONE
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#define CFG_TUH_HUB 0
+#define CFG_TUH_CDC 0
+#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
+#define CFG_TUH_MSC 0
+#define CFG_TUH_VENDOR 0
+
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
+
+//------------- HID -------------//
+
+#define CFG_TUH_HID_EP_BUFSIZE 64
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */