From 5316c4e84adbe68571970f988b4e03e94dd3fac8 Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Fri, 7 May 2021 16:35:22 -0400 Subject: [PATCH 01/56] Update main.c Added new RTOS names to the name string array in print_greeting() in the host example program. The program seemed to hang when a new RTOS was indexed in CFG_TUSB_OS. --- examples/host/cdc_msc_hid/src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index bbaac8644..d941c56f3 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -310,6 +310,10 @@ void print_greeting(void) { [OPT_OS_NONE] = "None", [OPT_OS_FREERTOS] = "FreeRTOS", + [OPT_OS_MYNEWT] = "Mynewt OS", + [OPT_OS_CUSTOM] = "Custom OS implemnted by application", + [OPT_OS_PICO] = "Raspberry Pi Pico SDK", + [OPT_OS_RTTHREAD] = "RT-Thread" }; printf("--------------------------------------------------------------------\r\n"); From 13b510ad8e6c76e36cf63ec2931d6cf3f6840114 Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Fri, 7 May 2021 16:49:48 -0400 Subject: [PATCH 02/56] Update hcd_rp2040.c Remove reference to the deprecated "num" and "in" members of struct hw_endpoint which still exist in an assert statement and break DEBUG builds. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 224f6ef21..40d208679 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -487,7 +487,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // EP0 out _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); assert(ep->configured); - assert(ep->num == 0 && !ep->in); ep->total_len = 8; ep->transfer_size = 8; ep->active = true; From 0621df8d26a860ec31a2c66e8ba55f3366df7071 Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Sun, 9 May 2021 19:11:29 -0400 Subject: [PATCH 03/56] Update main.c Fix code where HID keyboard was being stuffed into the HID mouse buffer. --- examples/host/cdc_msc_hid/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index d941c56f3..c6ab54682 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -262,7 +262,7 @@ void hid_task(void) if ( !tuh_hid_keyboard_is_busy(addr) ) { process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_mouse_report); + tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); } } #endif From 13de8f5d98eceae8771af78e6acb126f8da19854 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 10 May 2021 19:15:46 +0700 Subject: [PATCH 04/56] minor clean up --- src/common/tusb_types.h | 2 ++ src/portable/espressif/esp32sx/dcd_esp32sx.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ba3fe2c41..922d3daff 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -309,6 +309,8 @@ typedef struct TU_ATTR_PACKED uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); + /// USB Interface Descriptor typedef struct TU_ATTR_PACKED { diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index 74842a291..502273a9b 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -27,7 +27,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) @@ -41,6 +40,7 @@ #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 62fab8d17..9b6a1f9a5 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -25,11 +25,11 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_SAMG #include "sam.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" // TODO should support (SAM3S || SAM4S || SAM4E || SAMG55) diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 5dc3bca21..7aeb49f2a 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC100Series.h" diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index d50e82846..e76d7118c 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NuMicro.h" diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index b7bbb020b..46081d4d0 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC505Series.h" diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dd0d76c1f..0b7605a73 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -102,7 +102,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if defined(STM32F102x6) || defined(STM32F102xB) || \ defined(STM32F103x6) || defined(STM32F103xB) || \ @@ -121,6 +120,7 @@ // Some definitions are copied to our private include file. #undef USE_HAL_DRIVER +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0fe7c2a3c..76f5c6050 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,7 +28,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on @@ -98,6 +97,7 @@ #endif +#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index d8c8753d3..92a9f3144 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -25,10 +25,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_NONE +#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 48e9dd592..e13ee697e 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -26,11 +26,11 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) #include "msp430.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ From 74ca1894de12429e1a16d75242889dcd520eea68 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 10 May 2021 15:58:04 +0200 Subject: [PATCH 05/56] audio_device: Fix build error ep_in_as_intf_num was incorrectly used to access out interface which is defined for 'in' interface. Code related to 'out' endpoint should use ep_out_as_intf_num instead. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 76ebc8aba..72533013c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -496,7 +496,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) { idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); } // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) From 72f52020864bb8980fa6c5adc7bf31d1c233d133 Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Mon, 10 May 2021 10:09:09 -0400 Subject: [PATCH 06/56] Update trace statements that referenced deprecated structure elements. --- .gitignore | 1 + src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f7adff4c9..f180d4079 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ cov-int # cppcheck build directories *-build-dir /_bin/ +examples/host/cdc_msc_hid/setup.bat diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 40d208679..5201d1d4c 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -306,8 +306,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; - pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->transfer_type); - pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->hw_data_buf); + pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->transfer_type); + pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->hw_data_buf); uint dpram_offset = hw_data_offset(ep->hw_data_buf); // Bits 0-5 should be 0 assert(!(dpram_offset & 0b111111)); From 23e564249ce9fda8034a2ced91a98d8e17cb2f7b Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Mon, 10 May 2021 10:15:36 -0400 Subject: [PATCH 07/56] Update .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index f180d4079..f7adff4c9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,3 @@ cov-int # cppcheck build directories *-build-dir /_bin/ -examples/host/cdc_msc_hid/setup.bat From e2f795067acede0b93de8f7f27edb6aaa76eda57 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 11 May 2021 08:53:33 +0200 Subject: [PATCH 08/56] Allow build for NRF5340 MCU Errata code referred to NRF_USBD_BASE. This definition is not present in NRF5340 but both NRF52 and NRF53 do have NRF_USBD which maps to NRF_USBD_BASE for NRF52 and to NRF_USBD_S_BASE for NRF5340. This just make build possible for NRF5340. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 6b8095a00..3bb9bd37a 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -924,8 +924,8 @@ void tusb_hal_nrf_power_event (uint32_t event) if ( nrfx_usbd_errata_166() ) { - *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; - *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; + *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x800)) = 0x7E3; + *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x804)) = 0x40; __ISB(); __DSB(); } From 9233269a2c97c9ca980276a288b1b225cb4d3825 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 18:38:23 +0700 Subject: [PATCH 09/56] only apply errata walkaround for nrf52 --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 3bb9bd37a..977ec6cdb 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -833,9 +833,8 @@ void tusb_hal_nrf_power_event (uint32_t event) NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync - /* Enable the peripheral */ +#ifdef NRF52_SERIES // ERRATA 171, 187, 166 - if ( nrfx_usbd_errata_187() ) { // CRITICAL_REGION_ENTER(); @@ -867,7 +866,9 @@ void tusb_hal_nrf_power_event (uint32_t event) } // CRITICAL_REGION_EXIT(); } +#endif + /* Enable the peripheral */ NRF_USBD->ENABLE = 1; __ISB(); __DSB(); // for sync @@ -889,6 +890,7 @@ void tusb_hal_nrf_power_event (uint32_t event) NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync +#ifdef NRF52_SERIES if ( nrfx_usbd_errata_171() ) { // CRITICAL_REGION_ENTER(); @@ -924,11 +926,12 @@ void tusb_hal_nrf_power_event (uint32_t event) if ( nrfx_usbd_errata_166() ) { - *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x800)) = 0x7E3; - *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x804)) = 0x40; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; __ISB(); __DSB(); } +#endif // ISO buffer Lower half for IN, upper half for OUT NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; From e163f85ee024ff366253478cfd20e3fc35e96819 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:32:20 +0700 Subject: [PATCH 10/56] clean up, rename some HID device symbol/API - add tud_hid_n_interface_protocol() - rename tud_hid_n_boot_mode() to tud_hid_n_get_protocol() - rename tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() - add HID_PROTOCOL_BOOT/REPORT to avoid magic number 0,1 - rename HID_PROTOCOL_NONE/KEYBOARD/MOUSE to HID_ITF_PROTOCOL_ to avoid confusion --- .../hid_composite/src/usb_descriptors.c | 2 +- .../src/usb_descriptors.c | 2 +- .../hid_generic_inout/src/usb_descriptors.c | 2 +- .../src/usb_descriptors.c | 4 +- src/class/hid/hid.h | 29 ++++++---- src/class/hid/hid_device.c | 58 ++++++++++--------- src/class/hid/hid_device.h | 55 +++++++++++------- src/class/hid/hid_host.c | 4 +- 8 files changed, 92 insertions(+), 64 deletions(-) diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index db4ddd76e..5a2f5ffdc 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -104,7 +104,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index a28e57a2b..9eef21504 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -119,8 +119,8 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), - TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), + TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..6014e54a6 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -62,15 +62,15 @@ typedef enum { HID_SUBCLASS_NONE = 0, ///< No Subclass HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_type_t; +}hid_subclass_enum_t; -/// HID Protocol +/// HID Interface Protocol typedef enum { - HID_PROTOCOL_NONE = 0, ///< None - HID_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_protocol_type_t; + HID_ITF_PROTOCOL_NONE = 0, ///< None + HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard + HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse +}hid_interface_protocol_enum_t; /// HID Descriptor Type typedef enum @@ -78,7 +78,7 @@ typedef enum HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_type_t; +}hid_descriptor_enum_t; /// HID Request Report Type typedef enum @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; +}hid_report_enum_t; /// HID Class Specific Control Request typedef enum @@ -98,9 +98,9 @@ typedef enum HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_type_t; +}hid_request_enum_t; -/// HID Country Code +/// HID Local Code typedef enum { HID_LOCAL_NotSupported = 0 , ///< NotSupported @@ -139,7 +139,14 @@ typedef enum HID_LOCAL_US , ///< US HID_LOCAL_Yugoslavia , ///< Yugoslavia HID_LOCAL_Turkish_F ///< Turkish-F -} hid_country_code_t; +} hid_local_enum_t; + +// HID protocol value used by GetProtocol / SetProtocol +enum +{ + HID_PROTOCOL_BOOT = 0, + HID_PROTOCOL_REPORT = 1 +}; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..62d63e30a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -43,7 +43,8 @@ typedef struct uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; // optional Out endpoint - uint8_t boot_protocol; // Boot mouse or keyboard + uint8_t itf_protocol; // Boot mouse or keyboard + bool boot_mode; // default = false (Report) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -51,6 +52,8 @@ typedef struct CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; + // TODO save hid descriptor since host can specifically request this after enumeration + // Note: HID descriptor may be not available from application after enumeration tusb_hid_descriptor_hid_t const * hid_descriptor; } hidd_interface_t; @@ -70,16 +73,16 @@ static inline uint8_t get_index_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t itf) +bool tud_hid_n_ready(uint8_t instance) { - uint8_t const ep_in = _hidd_itf[itf].ep_in; + uint8_t const ep_in = _hidd_itf[instance].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[itf]; + hidd_interface_t * p_hid = &_hidd_itf[instance]; // claim endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); @@ -102,12 +105,17 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); } -bool tud_hid_n_boot_mode(uint8_t itf) +uint8_t tud_hid_n_interface_protocol(uint8_t instance) { - return _hidd_itf[itf].boot_mode; + return _hidd_itf[instance].itf_protocol; } -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +bool tud_hid_n_get_protocol(uint8_t instance) +{ + return _hidd_itf[instance].boot_mode; +} + +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -121,10 +129,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, tu_memclr(report.keycode, 6); } - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = @@ -136,10 +144,10 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, .pan = horizontal }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { hid_gamepad_report_t report = @@ -154,7 +162,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, .buttons = buttons, }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ @@ -203,7 +211,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol; + if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; @@ -318,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); tud_control_xfer(rhport, request, &protocol, 1); } break; @@ -327,15 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - p_hid->boot_mode = 1 - request->wValue; + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_hid_boot_mode_cb) + if (tud_hid_set_protocol_cb) { - tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); } } break; @@ -354,29 +360,29 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { (void) result; - uint8_t itf = 0; + uint8_t instance = 0; hidd_interface_t * p_hid = _hidd_itf; // Identify which interface to use - for (itf = 0; itf < CFG_TUD_HID; itf++) + for (instance = 0; instance < CFG_TUD_HID; instance++) { - p_hid = &_hidd_itf[itf]; + p_hid = &_hidd_itf[instance]; if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; } - TU_ASSERT(itf < CFG_TUD_HID); + TU_ASSERT(instance < CFG_TUD_HID); // Sent report successfully if (ep_addr == p_hid->ep_in) { if (tud_hid_report_complete_cb) { - tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); + tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); } } // Received report else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..cc34f19ac 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -55,34 +55,39 @@ //--------------------------------------------------------------------+ // Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t itf); +bool tud_hid_n_ready(uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tud_hid_n_boot_mode(uint8_t itf); +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +uint8_t tud_hid_n_interface_protocol(uint8_t instance); + +// Check if active protocol is Boot (true) or Report (false) +bool tud_hid_n_get_protocol(uint8_t instance); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); // Gamepad: convenient helper to send mouse report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_ready(void); +static inline uint8_t tud_hid_interface_protocol(void); +static inline bool tud_hid_get_protocol(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -90,29 +95,29 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); +uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); //--------------------------------------------------------------------+ @@ -123,9 +128,14 @@ static inline bool tud_hid_ready(void) return tud_hid_n_ready(0); } -static inline bool tud_hid_boot_mode(void) +static inline uint8_t tud_hid_interface_protocol(void) { - return tud_hid_n_boot_mode(0); + return tud_hid_n_interface_protocol(0); +} + +static inline bool tud_hid_get_protocol(void) +{ + return tud_hid_n_get_protocol(0); } static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) @@ -143,6 +153,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +{ + return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); +} + /* --------------------------------------------------------------------+ * HID Report Descriptor Template * diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..28440b1b4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -178,7 +178,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); @@ -186,7 +186,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); From 7e9e682e09c2629a9575343e4efaf43d328bde33 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:38:11 +0700 Subject: [PATCH 11/56] update to use HID spec protocol value for get/set_protocol() --- src/class/hid/hid.h | 4 ++-- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 11 ++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 6014e54a6..5c30f7585 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -142,11 +142,11 @@ typedef enum } hid_local_enum_t; // HID protocol value used by GetProtocol / SetProtocol -enum +typedef enum { HID_PROTOCOL_BOOT = 0, HID_PROTOCOL_REPORT = 1 -}; +} hid_protocol_mode_enum_t; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 62d63e30a..4d33c85d3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) bool tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode; + return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -334,14 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); } } break; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index cc34f19ac..2cc4a9546 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -60,8 +60,8 @@ bool tud_hid_n_ready(uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value uint8_t tud_hid_n_interface_protocol(uint8_t instance); -// Check if active protocol is Boot (true) or Report (false) -bool tud_hid_n_get_protocol(uint8_t instance); +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +uint8_t tud_hid_n_get_protocol(uint8_t instance); // Send report to host bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); @@ -83,7 +83,7 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline uint8_t tud_hid_interface_protocol(void); -static inline bool tud_hid_get_protocol(void); +static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); @@ -106,8 +106,9 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -// Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); +// Invoked when received SET_PROTOCOL request +// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication From a26752a93e56b2fb2d683e5a9f9934b432531d9b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:45:59 +0700 Subject: [PATCH 12/56] fix build error --- src/class/hid/hid.h | 2 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5c30f7585..c63b6f00b 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_enum_t; +}hid_report_type_t; /// HID Class Specific Control Request typedef enum diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4d33c85d3..ab9ef3ad8 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -110,7 +110,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) return _hidd_itf[instance].itf_protocol; } -bool tud_hid_n_get_protocol(uint8_t instance) +uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 2cc4a9546..b3701c7e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -134,7 +134,7 @@ static inline uint8_t tud_hid_interface_protocol(void) return tud_hid_n_interface_protocol(0); } -static inline bool tud_hid_get_protocol(void) +static inline uint8_t tud_hid_get_protocol(void) { return tud_hid_n_get_protocol(0); } @@ -156,7 +156,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { - return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); + return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } /* --------------------------------------------------------------------+ From 1dd2cd43dda857de3f4272074c595e663ef09b22 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:10:47 +0700 Subject: [PATCH 13/56] add hcd_ehci.h as interface for ehci port --- src/host/usbh.c | 2 +- src/portable/ehci/ehci.c | 5 +- src/portable/ehci/hcd_ehci.h | 53 +++++++++++++++++++ .../nxp/transdimension/hcd_transdimension.c | 4 +- 4 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/portable/ehci/hcd_ehci.h diff --git a/src/host/usbh.c b/src/host/usbh.c index a4ee4cb5c..3761f279c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -656,7 +656,7 @@ static bool enum_new_device(hcd_event_t* event) //------------- connected/disconnected directly with roothub -------------// if (dev0->hub_addr == 0) { - // wait until device is stable + // wait until device is stable TODO non blocking osal_task_delay(RESET_DELAY); // device unplugged while delaying diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index e2327fdc0..484e49600 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -37,6 +37,7 @@ #include "host/hcd.h" #include "host/usbh_hcd.h" +#include "hcd_ehci.h" #include "ehci.h" //--------------------------------------------------------------------+ @@ -49,10 +50,6 @@ // Periodic frame list must be 4K alignment CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; -// EHCI portable -uint32_t hcd_ehci_register_addr(uint8_t rhport); -bool hcd_ehci_init (uint8_t rhport); // TODO move later - //--------------------------------------------------------------------+ // PROTOTYPE //--------------------------------------------------------------------+ diff --git a/src/portable/ehci/hcd_ehci.h b/src/portable/ehci/hcd_ehci.h new file mode 100644 index 000000000..480d11eda --- /dev/null +++ b/src/portable/ehci/hcd_ehci.h @@ -0,0 +1,53 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_HCD_EHCI_H_ +#define _TUSB_HCD_EHCI_H_ + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// API Implemented by HCD +//--------------------------------------------------------------------+ + +// Get operational address i.e EHCI Command register +uint32_t hcd_ehci_register_addr(uint8_t rhport); + +//--------------------------------------------------------------------+ +// API Implemented by EHCI +//--------------------------------------------------------------------+ + +// Initialize EHCI driver +extern bool hcd_ehci_init (uint8_t rhport); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index e6b7afe8f..db447ef23 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -43,6 +43,7 @@ #include "common/tusb_common.h" #include "common_transdimension.h" +#include "portable/ehci/hcd_ehci.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -75,9 +76,6 @@ typedef struct }; #endif -// TODO better prototype later -extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ From 98f5082191e2135ca783a24a39f95ee82639b9fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:19:32 +0700 Subject: [PATCH 14/56] rename var to be consistent --- src/class/hid/hid_host.c | 36 +++++++++++++++++++----------------- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 12 +++++------- src/class/msc/msc_host.h | 2 +- src/host/usbh.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..9e41f9f45 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -47,12 +47,12 @@ typedef struct { //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_t *p_hid) +static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) { - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, p_endpoint_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - p_hid->ep_in = p_endpoint_desc->bEndpointAddress; - p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor + p_hid->ep_in = desc_ep->bEndpointAddress; + p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->itf_num = interface_number; p_hid->valid = true; @@ -161,34 +161,36 @@ void hidh_init(void) CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; #endif -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); - if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); } else #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); } else #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 5c77398f8..174601594 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -196,7 +196,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); // Internal Class Driver API //--------------------------------------------------------------------+ void hidh_init(void); -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 34dbec2e3..3e8573df0 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -357,15 +357,13 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); msch_interface_t* p_msc = get_itf(dev_addr); - - //------------- Open Data Pipe -------------// - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { @@ -383,7 +381,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } - p_msc->itf_num = itf_desc->bInterfaceNumber; + p_msc->itf_num = desc_itf->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 8116e729f..d99f1204a 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -116,7 +116,7 @@ void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 3761f279c..86da97bb8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -79,7 +79,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, .init = hidh_init, - .open = hidh_open_subtask, + .open = hidh_open, .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, .close = hidh_close From f1148ca5ac8f56774af4b58175d0d61442f86544 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:54:18 +0700 Subject: [PATCH 15/56] reworking hid host --- src/class/hid/hid_host.c | 43 ++++++++++++++++++++++++++++++++-------- src/class/hid/hid_host.h | 8 ++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 9e41f9f45..7ae50e4d7 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,13 +35,40 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF + */ typedef struct { - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - bool valid; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; - uint16_t report_size; + bool valid; + uint16_t report_size; // TODO remove later + + uint8_t boot_protocol; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol + uint8_t report_count; // Number of reports + + struct { + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report + uint8_t usage_page; + uint8_t usage; + }reports[CFG_TUH_HID_MAX_REPORT]; + + // Parsed Report ID for convenient API + uint8_t report_id_keyboard; + uint8_t reprot_id_mouse; + uint8_t report_id_gamepad; + uint8_t report_id_consumer; + uint8_t report_id_vendor; }hidh_interface_t; //--------------------------------------------------------------------+ @@ -51,9 +78,9 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t { TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + p_hid->itf_num = interface_number; p_hid->ep_in = desc_ep->bEndpointAddress; p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->itf_num = interface_number; p_hid->valid = true; return true; @@ -170,12 +197,12 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 174601594..d43158186 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -38,6 +38,14 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_HID_MAX_REPORT +#define CFG_TUH_HID_MAX_REPORT 8 +#endif + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ From 68fa17e17ca900ec2800c55c9345a2a0fed3fca9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 14:07:33 +0700 Subject: [PATCH 16/56] more API rename --- examples/host/cdc_msc_hid/src/main.c | 4 ++-- src/class/hid/hid_device.h | 4 ++-- src/class/hid/hid_host.c | 8 ++++---- src/class/hid/hid_host.h | 14 ++++++++++++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c6ab54682..84e88e509 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -257,7 +257,7 @@ 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_mounted(addr) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { @@ -268,7 +268,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_is_mounted(addr) ) + if ( tuh_hid_mouse_mounted(addr) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..7520d3453 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -50,7 +50,7 @@ #endif //--------------------------------------------------------------------+ -// Application API (Multiple Ports) +// Application API (Multiple Instances) // CFG_TUD_HID > 1 //--------------------------------------------------------------------+ @@ -76,7 +76,7 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ -// Application API (Single Port) +// Application API (Single Instance) //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7ae50e4d7..aa6188a24 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -113,7 +113,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); } @@ -125,7 +125,7 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); } #endif @@ -138,14 +138,14 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr) +bool tuh_hid_mouse_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index d43158186..f777fe45d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,6 +46,16 @@ #define CFG_TUH_HID_MAX_REPORT 8 #endif +//--------------------------------------------------------------------+ +// Application API (Multiple Instances) +// CFG_TUH_HID > 1 +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// Application API (Single Instance) +//--------------------------------------------------------------------+ + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -63,7 +73,7 @@ extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if * \retval true if device supports Keyboard interface * \retval false if device does not support Keyboard interface or is not mounted */ -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr); +bool tuh_hid_keyboard_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address @@ -128,7 +138,7 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * \retval true if device supports Mouse interface * \retval false if device does not support Mouse interface or is not mounted */ -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr); +bool tuh_hid_mouse_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address From 2666e1efec20d78f8f74c23cdbb7977737b8d956 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 01:46:22 +0700 Subject: [PATCH 17/56] add tuh_inited() and tud_inited() --- src/device/usbd.c | 19 ++++++++++++++++--- src/device/usbd.h | 3 +++ src/host/usbh.c | 14 ++++++++++++++ src/host/usbh.h | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 2853b619b..fe18b21b3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,10 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + typedef struct { struct TU_ATTR_PACKED @@ -76,9 +80,6 @@ typedef struct static usbd_device_t _usbd_dev; -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; - //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ @@ -241,6 +242,8 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ +static bool _initialized = false; + // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); @@ -368,8 +371,16 @@ bool tud_connect(void) //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ +bool tud_inited(void) +{ + return _initialized; +} + bool tud_init (void) { + // skip if already initialized + if (_initialized) return _initialized; + TU_LOG2("USBD init\r\n"); tu_varclr(&_usbd_dev); @@ -402,6 +413,8 @@ bool tud_init (void) dcd_init(TUD_OPT_RHPORT); dcd_int_enable(TUD_OPT_RHPORT); + _initialized = true; + return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 7c50a6db0..10fbe0bf1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -43,6 +43,9 @@ extern "C" { // Init device stack bool tud_init (void); +// Check if device stack is already initialized +bool tud_inited(void); + // Task function should be called in main/rtos loop void tud_task (void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 86da97bb8..411945fdb 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,6 +121,8 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool _initialized = false; + // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -170,8 +172,19 @@ void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ + +bool tuh_inited(void) +{ + return _initialized; +} + bool tuh_init(void) { + // skip if already initialized + if (_initialized) return _initialized; + + TU_LOG2("USBH init\r\n"); + tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); //------------- Enumeration & Reporter Task init -------------// @@ -202,6 +215,7 @@ bool tuh_init(void) TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); hcd_int_enable(TUH_OPT_RHPORT); + _initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index a05010b36..732a4b66e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -78,6 +78,9 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request // Init host stack bool tuh_init(void); +// Check if host stack is already initialized +bool tuh_inited(void); + // Task function should be called in main/rtos loop void tuh_task(void); From 3a7f8b3ac3988eeb653ada6e3efdd7acb68fbe0f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 17:32:52 +0700 Subject: [PATCH 18/56] separte tusb_init/inited() to tud/tuh init/inited add rhport to tud_init() --- src/device/usbd.c | 14 +++++++------- src/device/usbd.h | 2 +- src/host/usbh.c | 14 +++++++------- src/host/usbh.h | 2 +- src/tusb.c | 27 +++++++++++++++------------ 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index fe18b21b3..280235911 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -242,7 +242,7 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbd_initialized = false; // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) @@ -373,13 +373,13 @@ bool tud_connect(void) //--------------------------------------------------------------------+ bool tud_inited(void) { - return _initialized; + return _usbd_initialized; } -bool tud_init (void) +bool tud_init (uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbd_initialized) return _usbd_initialized; TU_LOG2("USBD init\r\n"); @@ -410,10 +410,10 @@ bool tud_init (void) } // Init device controller driver - dcd_init(TUD_OPT_RHPORT); - dcd_int_enable(TUD_OPT_RHPORT); + dcd_init(rhport); + dcd_int_enable(rhport); - _initialized = true; + _usbd_initialized = true; return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 10fbe0bf1..c0bec9566 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,7 +41,7 @@ extern "C" { //--------------------------------------------------------------------+ // Init device stack -bool tud_init (void); +bool tud_init (uint8_t rhport); // Check if device stack is already initialized bool tud_inited(void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 411945fdb..5132d7e93 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,7 +121,7 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbh_initialized = false; // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -175,13 +175,13 @@ void osal_task_delay(uint32_t msec) bool tuh_inited(void) { - return _initialized; + return _usbh_initialized; } -bool tuh_init(void) +bool tuh_init(uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbh_initialized) return _usbh_initialized; TU_LOG2("USBH init\r\n"); @@ -212,10 +212,10 @@ bool tuh_init(void) usbh_class_drivers[drv_id].init(); } - TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); - hcd_int_enable(TUH_OPT_RHPORT); + TU_ASSERT(hcd_init(rhport)); + hcd_int_enable(rhport); - _initialized = true; + _usbh_initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 732a4b66e..809ffd40b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -76,7 +76,7 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request //--------------------------------------------------------------------+ // Init host stack -bool tuh_init(void); +bool tuh_init(uint8_t rhport); // Check if host stack is already initialized bool tuh_inited(void); diff --git a/src/tusb.c b/src/tusb.c index 31452e897..0350fa1de 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -30,8 +30,6 @@ #include "tusb.h" -static bool _initialized = false; - // TODO clean up #if TUSB_OPT_DEVICE_ENABLED #include "device/usbd_pvt.h" @@ -39,25 +37,30 @@ static bool _initialized = false; bool tusb_init(void) { - // skip if already initialized - if (_initialized) return true; +#if TUSB_OPT_DEVICE_ENABLED + TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack +#endif #if TUSB_OPT_HOST_ENABLED - TU_ASSERT( tuh_init() ); // init host stack + TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack #endif -#if TUSB_OPT_DEVICE_ENABLED - TU_ASSERT ( tud_init() ); // init device stack -#endif - - _initialized = true; - return true; } bool tusb_inited(void) { - return _initialized; + bool ret = false; + +#if TUSB_OPT_DEVICE_ENABLED + ret = ret || tud_inited(); +#endif + +#if TUSB_OPT_HOST_ENABLED + ret = ret || tuh_inited(); +#endif + + return ret; } /*------------------------------------------------------------------*/ From 13613eafb70acd028572305b3e0b9064f905b835 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 18:11:46 +0700 Subject: [PATCH 19/56] correct ehci control endpoint address report on xfer complete improve host log --- src/host/usbh.c | 9 ++++++--- src/host/usbh_control.c | 1 + src/portable/ehci/ehci.c | 15 ++++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 5132d7e93..88e5c02a7 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -626,10 +626,11 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request static bool enum_request_set_addr(void) { // Set Address - TU_LOG2("Set Address \r\n"); uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + TU_LOG2("Set Address = %d\r\n", new_addr); + usbh_device_t* dev0 = &_usbh_devices[0]; usbh_device_t* new_dev = &_usbh_devices[new_addr]; @@ -783,6 +784,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor + TU_LOG2("Get Device Descriptor\r\n"); tusb_control_request_t const new_request = { .bmRequestType_bit = @@ -849,7 +851,8 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); - //Get full configuration descriptor + // Get full configuration descriptor + TU_LOG2("Get Configuration Descriptor\r\n"); tusb_control_request_t const new_request = { .bmRequestType_bit = @@ -879,7 +882,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request // Driver open aren't allowed to make any usb transfer yet parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - TU_LOG2("Set Configuration Descriptor\r\n"); + TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); tusb_control_request_t const new_request = { .bmRequestType_bit = diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index de55bd5e1..2b9f47793 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -80,6 +80,7 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { + TU_LOG2("\r\n"); if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 484e49600..eab1f8928 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -513,18 +513,19 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) // free all TDs from the head td to the first active TD while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) { - // TD need to be freed and removed from qhd, before invoking callback - bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0); - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; + bool const is_ioc = (qtd->int_on_complete != 0); + uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); - p_qhd->p_qtd_list_head->used = 0; // free QTD + p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes; + + // TD need to be freed and removed from qhd, before invoking callback + qtd->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); if (is_ioc) { - // end of request - // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); p_qhd->total_xferred_bytes = 0; } } From 4023d05e9306c68a3760fd696220868eab69a0d4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 18:19:42 +0700 Subject: [PATCH 20/56] minor clean up --- examples/host/cdc_msc_hid/src/main.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 84e88e509..652a372e9 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -316,23 +316,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"); } From e83bdcdfdc521fef2dd182a5f83cd1c1be673865 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 15:29:17 +0700 Subject: [PATCH 21/56] reworking hid host --- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 4 + src/class/hid/hid_host.c | 159 +++++++++++--------- src/class/hid/hid_host.h | 14 +- src/host/usbh.c | 1 + 5 files changed, 108 insertions(+), 72 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 652a372e9..b3fd1f2af 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fabc7765c..82155f1ca 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -73,9 +73,13 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 + +#define CFG_TUH_HID 2 + #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_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index aa6188a24..dae20b305 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -44,11 +44,14 @@ "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ -typedef struct { +typedef struct +{ uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; + uint16_t report_desc_len; + bool valid; uint16_t report_size; // TODO remove later @@ -61,16 +64,38 @@ typedef struct { uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; - }reports[CFG_TUH_HID_MAX_REPORT]; + }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API - uint8_t report_id_keyboard; - uint8_t reprot_id_mouse; - uint8_t report_id_gamepad; - uint8_t report_id_consumer; - uint8_t report_id_vendor; + uint8_t rid_keyboard; + uint8_t rid_mouse; + uint8_t rid_gamepad; + uint8_t rid_consumer; }hidh_interface_t; +typedef struct +{ + uint8_t inst_count; + hidh_interface_t instance[CFG_TUH_HID]; +} hidh_device_t; + +static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; + +#if 0 +CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; +#endif + +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +{ + return &_hidh_dev[dev_addr-1].instance[inst]; +} + + //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ @@ -108,27 +133,32 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD -static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + // TODO check rid_keyboard + return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); } -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) +tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - return hidh_interface_get_report(dev_addr, p_report, &keyboardh_data[dev_addr-1]); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -#endif //--------------------------------------------------------------------+ // MOUSE @@ -158,36 +188,20 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ // GENERIC //--------------------------------------------------------------------+ -#if CFG_TUSB_HOST_HID_GENERIC -//STATIC_ struct { -// hidh_interface_info_t -//} generic_data[CFG_TUSB_HOST_DEVICE_MAX]; - -#endif //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ void hidh_init(void) { -#if CFG_TUH_HID_KEYBOARD - tu_memclr(&keyboardh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); -#endif + tu_memclr(_hidh_dev, sizeof(_hidh_dev)); #if CFG_TUH_HID_MOUSE tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_init(); -#endif } -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif - bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -199,6 +213,18 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + // not enough interface, try to increase CFG_TUH_HID + // TODO multiple devices + hidh_device_t* hid_dev = get_dev(dev_addr); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + + 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->boot_mode = false; // default is report mode + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; @@ -206,11 +232,20 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { + hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); - TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); + TU_LOG2_HEX(hid_itf->ep_in); + + hid_itf->report_count = 1; + + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; } else #endif @@ -226,13 +261,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // Not supported protocol return false; } - }else - { - // Not supported subclass - return false; } - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); + *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); return true; } @@ -276,12 +307,13 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) usbh_driver_set_config_complete(dev_addr, itf_num); -#if CFG_TUH_HID_KEYBOARD - if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid) - { - tuh_hid_keyboard_mounted_cb(dev_addr); +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + + + if (itf_num == 0 ) { + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); } -#endif #if CFG_TUH_HID_MOUSE if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) @@ -297,12 +329,15 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { (void) xferred_bytes; // TODO may need to use this para later +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + #if CFG_TUH_HID_KEYBOARD - if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) - { - tuh_hid_keyboard_isr(dev_addr, event); - return true; - } +// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_keyboard_isr(dev_addr, event); +// return true; +// } #endif #if CFG_TUH_HID_MOUSE @@ -311,10 +346,6 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 tuh_hid_mouse_isr(dev_addr, event); return true; } -#endif - -#if CFG_TUSB_HOST_HID_GENERIC - #endif return true; @@ -322,13 +353,11 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { -#if CFG_TUH_HID_KEYBOARD - if ( keyboardh_data[dev_addr-1].ep_in != 0 ) - { - hidh_interface_close(&keyboardh_data[dev_addr-1]); - tuh_hid_keyboard_unmounted_cb(dev_addr); - } -#endif + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); + hidh_interface_close(hid_itf); #if CFG_TUH_HID_MOUSE if( mouseh_data[dev_addr-1].ep_in != 0 ) @@ -337,12 +366,6 @@ void hidh_close(uint8_t dev_addr) tuh_hid_mouse_unmounted_cb( dev_addr ); } #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_close(dev_addr); -#endif } - - #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f777fe45d..10ecc457f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,8 +42,8 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_MAX_REPORT -#define CFG_TUH_HID_MAX_REPORT 8 +#ifndef CFG_TUH_HID_REPORT_MAX +#define CFG_TUH_HID_REPORT_MAX 4 #endif //--------------------------------------------------------------------+ @@ -56,6 +56,12 @@ // Application API (Single Instance) //--------------------------------------------------------------------+ +// tuh_hid_instance_count() +//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); + +TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -66,7 +72,9 @@ * The interface API includes status checking function, data transferring function and callback functions * @{ */ -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled +// TODO used weak attr if build failed without KEYBOARD enabled +// TODO remove +extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address diff --git a/src/host/usbh.c b/src/host/usbh.c index 88e5c02a7..f7cad4640 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -915,6 +915,7 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co // Start the Set Configuration process for interfaces (itf = 0xff) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + // TODO use separated API instead of usig 0xff usbh_driver_set_config_complete(dev_addr, 0xff); return true; From e0dbb489aed9d9e7f081c379400dcb74600ede6a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:27:05 +0700 Subject: [PATCH 22/56] rename CFG_TUSB_HOST_ENUM_BUFFER_SIZE to CFG_TUH_ENUMERATION_BUFSZIE add usbh_get_enum_buf --- examples/host/cdc_msc_hid/src/tusb_config.h | 13 +++++++++++++ src/host/usbh.c | 9 +++++++-- src/host/usbh.h | 2 ++ src/host/usbh_control.c | 2 +- src/tusb_option.h | 4 ++-- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 82155f1ca..e1e02e31e 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -71,6 +71,9 @@ // 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 @@ -85,6 +88,16 @@ #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports +//------------- HID -------------// + +// Max number of reports per interface +// E.g composite HID with keyboard + mouse + gamepad will have 3 reports +#define CFG_TUH_HID_REPORT_MAX 4 + +// Max buffer +#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 + + #ifdef __cplusplus } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f7cad4640..fe0b2b987 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -131,7 +131,7 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); @@ -144,6 +144,11 @@ uint8_t usbh_get_rhport(uint8_t dev_addr) return _usbh_devices[dev_addr].rhport; } +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -849,7 +854,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE); // Get full configuration descriptor TU_LOG2("Get Configuration Descriptor\r\n"); diff --git a/src/host/usbh.h b/src/host/usbh.h index 809ffd40b..5e7abe868 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -124,6 +124,8 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); uint8_t usbh_get_rhport(uint8_t dev_addr); +uint8_t* usbh_get_enum_buf(void); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 2b9f47793..974d10662 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -50,7 +50,7 @@ typedef struct static usbh_control_xfer_t _ctrl_xfer; //CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; +//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/src/tusb_option.h b/src/tusb_option.h index b59c7cb22..53d3d9d20 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -269,8 +269,8 @@ //------------- HID CLASS -------------// #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) - #ifndef CFG_TUSB_HOST_ENUM_BUFFER_SIZE - #define CFG_TUSB_HOST_ENUM_BUFFER_SIZE 256 + #ifndef CFG_TUH_ENUMERATION_BUFSZIE + #define CFG_TUH_ENUMERATION_BUFSZIE 256 #endif //------------- CLASS -------------// From 510beef9f8f78689424ee8f62d3883b89fe794fa Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:27:34 +0700 Subject: [PATCH 23/56] make tuh_msc_mount_cb() tuh_msc_unmount_cb() as weak callback --- src/class/msc/msc_host.c | 9 ++++++--- src/class/msc/msc_host.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 3e8573df0..4869c8c03 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -287,7 +287,7 @@ bool tuh_msc_reset(uint8_t dev_addr) #endif //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// CLASS-USBH API //--------------------------------------------------------------------+ void msch_init(void) { @@ -298,7 +298,9 @@ void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); tu_memclr(p_msc, sizeof(msch_interface_t)); - tuh_msc_unmount_cb(dev_addr); // invoke Application Callback + + // invoke Application Callback + if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -471,8 +473,9 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Mark enumeration is complete p_msc->mounted = true; - tuh_msc_mount_cb(dev_addr); + if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index d99f1204a..7ebc9b5a8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,10 +106,10 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -void tuh_msc_mount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API From be165a67134d08f7c32386de041f1a2665e696be Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:36:52 +0700 Subject: [PATCH 24/56] reworking host hid API --- examples/host/cdc_msc_hid/src/main.c | 17 +- src/class/hid/hid_host.c | 358 +++++++++++++++------------ src/class/hid/hid_host.h | 62 ++--- 3 files changed, 234 insertions(+), 203 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index b3fd1f2af..5543e9efb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -162,19 +162,12 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) +void tuh_hid_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 @@ -242,12 +235,6 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) 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 @@ -257,7 +244,7 @@ void hid_task(void) uint8_t const addr = 1; #if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_mounted(addr) ) + if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dae20b305..a5aa33c2c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -50,6 +50,7 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t report_desc_type; uint16_t report_desc_len; bool valid; @@ -75,41 +76,50 @@ typedef struct typedef struct { - uint8_t inst_count; - hidh_interface_t instance[CFG_TUH_HID]; + uint8_t itf_count; + hidh_interface_t interface[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; +// Get Device by address TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) { return &_hidh_dev[dev_addr-1]; } -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].instance[inst]; + return &_hidh_dev[dev_addr-1].interface[instance]; } +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ +uint8_t tuh_n_hid_instance_count(uint8_t daddr) +{ + return get_dev(daddr)->itf_count; +} //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) -{ - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - - p_hid->itf_num = interface_number; - p_hid->ep_in = desc_ep->bEndpointAddress; - p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->valid = true; - - return true; -} static inline void hidh_interface_close(hidh_interface_t *p_hid) { @@ -123,7 +133,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // TODO change to use is configured function TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; @@ -134,10 +144,9 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); @@ -153,13 +162,12 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t instance = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } - //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ @@ -191,138 +199,11 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// USBH API //--------------------------------------------------------------------+ void hidh_init(void) { tu_memclr(_hidh_dev, sizeof(_hidh_dev)); - -#if CFG_TUH_HID_MOUSE - tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); -#endif -} - -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) -{ - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - //------------- HID descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); - - // not enough interface, try to increase CFG_TUH_HID - // TODO multiple devices - hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); - - 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->boot_mode = false; // default is report mode - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { - hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; - - #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) - { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); - TU_LOG2_HEX(hid_itf->ep_in); - - hid_itf->report_count = 1; - - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[0].out_len = 1; - } else - #endif - - #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) - { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); - TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); - } else - #endif - - { - // Not supported protocol - return false; - } - } - - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - return true; -} - -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) -{ -#if 0 - //------------- Get Report Descriptor TODO HID parser -------------// - if ( p_desc_hid->bNumDescriptors ) - { - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), - TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, - p_desc_hid->wReportLength, report_descriptor ), - error - ); - (void) error; // if error in getting report descriptor --> treating like there is none - } -#endif - -#if 0 - // SET IDLE = 0 request - // Device can stall if not support this request - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, - .wLength = 0 - }; - - // stall is a valid response for SET_IDLE, therefore we could ignore result of this request - tuh_control_xfer(dev_addr, &request, NULL, NULL); -#endif - - usbh_driver_set_config_complete(dev_addr, itf_num); - -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - - - if (itf_num == 0 ) { - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); - } - -#if CFG_TUH_HID_MOUSE - if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) - { - tuh_hid_mouse_mounted_cb(dev_addr); - } -#endif - - return true; } bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -341,11 +222,11 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 #endif #if CFG_TUH_HID_MOUSE - if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) - { - tuh_hid_mouse_isr(dev_addr, event); - return true; - } +// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_mouse_isr(dev_addr, event); +// return true; +// } #endif return true; @@ -368,4 +249,163 @@ void hidh_close(uint8_t dev_addr) #endif } +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ + +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); + +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +{ + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; + + //------------- HID descriptor -------------// + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + + // not enough interface, try to increase CFG_TUH_HID + // TODO multiple devices + hidh_device_t* hid_dev = get_dev(dev_addr); + TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); + + //------------- Endpoint Descriptor -------------// + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + + // TODO also open endpoint OUT + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); + hid_dev->itf_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor + hid_itf->valid = true; + + TU_LOG2_HEX(hid_itf->ep_in); + + // Assume bNumDescriptors = 1 + hid_itf->report_desc_type = desc_hid->bReportType; + 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; + + if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) + { + // TODO boot protocol may still have more report in report mode + hid_itf->report_count = 1; + + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; + } + else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) + { + // TODO boot protocol may still have more report in report mode + hid_itf->report_count = 1; + + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; + } + else + { + // Unknown protocol + TU_ASSERT(false); + } + } + + *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + + return true; +} + +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + // Idle rate = 0 mean only report when there is changes + uint16_t const idle_rate = 0; + + // SET IDLE request, device can stall if not support this request + TU_LOG2("Set Idle \r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = idle_rate, + .wIndex = itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); + + return true; +} + +bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // Stall is a valid response for SET_IDLE, therefore we could ignore its result + (void) result; + + uint8_t const itf_num = (uint8_t) request->wIndex; + + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + + // Get Report Descriptor + // using usbh enumeration buffer since report descriptor can be very long + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + return true; +} + +bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + uint8_t const itf_num = (uint8_t) request->wIndex; + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + + if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); + + // TODO Report descriptor parser + + // enumeration is complete + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, itf_num); + + return true; +} + #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 10ecc457f..98c652338 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,22 +46,51 @@ #define CFG_TUH_HID_REPORT_MAX 4 #endif +#ifndef CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE +#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 +#endif + //--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUH_HID > 1 +// Application API (Multiple devices) +// Note: +// - tud_n : is multiple devices API +// - class_n : is multiple instances API //--------------------------------------------------------------------+ +// Get the number of HID instances +uint8_t tuh_n_hid_instance_count(uint8_t daddr); + +// Check if HID instance support keyboard +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); + + //--------------------------------------------------------------------+ -// Application API (Single Instance) +// Application API (Single device) //--------------------------------------------------------------------+ -// tuh_hid_instance_count() +// Get the number of HID instances +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_hid_instance_count(void) +{ + return tuh_n_hid_instance_count(1); +} + //bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when report descriptor is received +// Note: enumeration is still not complete yet +TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); + TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -193,31 +222,6 @@ void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); */ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); -/** @} */ // Mouse_Host -/** @} */ // ClassDriver_HID_Mouse - -//--------------------------------------------------------------------+ -// GENERIC Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Generic Generic (not supported yet) - * @{ */ - -/** \defgroup Generic_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -bool tuh_hid_generic_is_mounted(uint8_t dev_addr); -tusb_error_t tuh_hid_generic_get_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_error_t tuh_hid_generic_set_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_interface_status_t tuh_hid_generic_get_status(uint8_t dev_addr); -tusb_interface_status_t tuh_hid_generic_set_status(uint8_t dev_addr); - -//------------- Application Callback -------------// -void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); - -/** @} */ // Generic_Host -/** @} */ // ClassDriver_HID_Generic - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ From a5cd81a2266541c14dfeb2617b2a826296aab688 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:04:19 +0700 Subject: [PATCH 25/56] correct hid host mount/unmount callback rename HOST_CLASS_HID to CFG_TUH_HID --- examples/host/cdc_msc_hid/src/main.c | 4 +- src/class/hid/hid_host.c | 64 +++++++++++++++------------- src/class/hid/hid_host.h | 6 +-- src/host/usbh.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 3 -- 6 files changed, 42 insertions(+), 39 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 5543e9efb..ccc50bbf2 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); @@ -162,7 +162,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_unmounted_cb(uint8_t dev_addr) +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { // application tear-down printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a5aa33c2c..6e8ec47c8 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_HOST_ENABLED && HOST_CLASS_HID) +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "common/tusb_common.h" #include "hid_host.h" @@ -76,8 +76,8 @@ typedef struct typedef struct { - uint8_t itf_count; - hidh_interface_t interface[CFG_TUH_HID]; + uint8_t inst_count; + hidh_interface_t instances[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; @@ -93,15 +93,28 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) // Get Interface by instance number TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].interface[instance]; + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; } // Get Interface by interface number static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) { - for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; } @@ -114,18 +127,13 @@ static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) //--------------------------------------------------------------------+ uint8_t tuh_n_hid_instance_count(uint8_t daddr) { - return get_dev(daddr)->itf_count; + return get_dev(daddr)->inst_count; } //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline void hidh_interface_close(hidh_interface_t *p_hid) -{ - tu_memclr(p_hid, sizeof(hidh_interface_t)); -} - // called from public API need to validate parameters tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) { @@ -234,19 +242,13 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); - - if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); - hidh_interface_close(hid_itf); - -#if CFG_TUH_HID_MOUSE - if( mouseh_data[dev_addr-1].ep_in != 0 ) + hidh_device_t* hid_dev = get_dev(dev_addr); + if (tuh_hid_unmounted_cb) { - hidh_interface_close(&mouseh_data[dev_addr-1]); - tuh_hid_mouse_unmounted_cb( dev_addr ); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); } -#endif + + tu_memclr(hid_dev, sizeof(hidh_device_t)); } //--------------------------------------------------------------------+ @@ -270,7 +272,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -280,8 +282,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // TODO also open endpoint OUT TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); - hid_dev->itf_count++; + 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; @@ -393,14 +395,18 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + uint8_t const inst = get_instance_id(dev_addr, itf_num); + //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); + if (tuh_hid_descriptor_report_cb) + { + tuh_hid_descriptor_report_cb(dev_addr, inst, usbh_get_enum_buf(), request->wLength); + } // TODO Report descriptor parser // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 98c652338..c45ca9bd4 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,7 +60,7 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance support keyboard +// Check if HID instance has keyboard bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); @@ -86,8 +86,8 @@ uint8_t tuh_hid_instance_count(void) // Note: enumeration is still not complete yet TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); -TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); diff --git a/src/host/usbh.c b/src/host/usbh.c index fe0b2b987..3008c9b4e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -74,7 +74,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = }, #endif - #if HOST_CLASS_HID + #if CFG_TUH_HID { DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..1678ef5d8 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -42,7 +42,7 @@ #if TUSB_OPT_HOST_ENABLED #include "host/usbh.h" - #if HOST_CLASS_HID + #if CFG_TUH_HID #include "class/hid/hid_host.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 53d3d9d20..97e12806b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -266,9 +266,6 @@ #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif - //------------- HID CLASS -------------// - #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) - #ifndef CFG_TUH_ENUMERATION_BUFSZIE #define CFG_TUH_ENUMERATION_BUFSZIE 256 #endif From 69defb5edc34979c9476533ba3bb49e070879ceb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:19:00 +0700 Subject: [PATCH 26/56] rename and moving --- src/class/hid/hid_host.c | 87 +++++++++++++++++++++------------------- src/host/usbh.c | 16 ++++---- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6e8ec47c8..80680894f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,45 +82,10 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; - -// Get Device by address -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) -{ - return &_hidh_dev[dev_addr-1]; -} - -// Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) -{ - return &_hidh_dev[dev_addr-1].instances[instance]; -} - -// Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; - } - - return 0xff; -} - -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; - } - - return NULL; -} +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); //--------------------------------------------------------------------+ // Application API @@ -290,8 +255,6 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor hid_itf->valid = true; - TU_LOG2_HEX(hid_itf->ep_in); - // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); @@ -414,4 +377,46 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +//--------------------------------------------------------------------+ +// Instance helper +//--------------------------------------------------------------------+ + +// Get Device by address +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) +{ + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; +} + +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} + #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 3008c9b4e..7a021c11c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -282,7 +282,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } -bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { tusb_desc_endpoint_t ep0_desc = { @@ -297,9 +297,11 @@ bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); } -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { - bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); if (ret) { @@ -315,7 +317,7 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - uint8_t const ep_addr = ep_desc->bEndpointAddress; + uint8_t const ep_addr = desc_ep->bEndpointAddress; dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; } @@ -526,7 +528,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) if (drv_id != 0xff) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config itf = %u\r\n", driver->name, itf_num); + TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; } @@ -702,7 +704,7 @@ static bool enum_new_device(hcd_event_t* event) static bool enum_request_addr0_device_desc(void) { // TODO probably doesn't need to open/close each enumeration - TU_ASSERT( usbh_pipe_control_open(0, 8) ); + TU_ASSERT( usbh_edpt_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); @@ -786,7 +788,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); From b7a8b278c83b9b8e03a328e17f4b833f925226a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 21:40:17 +0700 Subject: [PATCH 27/56] rename tuh_device_is_configured() to tuh_device_configured() - remove tuh_device_get_state() - more hid mouse clean up --- .../host/cdc_msc_hid/src/keyboard_helper.h | 59 ------------------- examples/host/cdc_msc_hid/src/main.c | 12 ++-- src/class/hid/hid_host.c | 38 ++++++++---- src/class/hid/hid_host.h | 19 ++---- src/host/usbh.c | 5 +- src/host/usbh.h | 6 +- 6 files changed, 42 insertions(+), 97 deletions(-) delete mode 100644 examples/host/cdc_msc_hid/src/keyboard_helper.h 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 -#include - -#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 ccc50bbf2..6b2d0affb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -156,16 +156,18 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { - // application set-up - printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + 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); + if (instance == 0) { tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { - // application tear-down - printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); + 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); } #endif @@ -255,7 +257,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_mounted(addr) ) + if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 80680894f..72cecb8d1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -104,7 +104,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int { //------------- parameters validation -------------// // TODO change to use is configured function - TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); + TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); @@ -113,32 +113,45 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int return TUSB_ERROR_NONE; } +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +//{ +// +//} + //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + hidh_interface_t* hid_itf = get_instance(daddr, instance); // TODO check rid_keyboard - return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); +} + +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(daddr, instance); + + // TODO check rid_keyboard + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); } tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t instance = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } //--------------------------------------------------------------------+ @@ -149,14 +162,15 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { - return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index c45ca9bd4..0052a2b0c 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,10 +60,14 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance has keyboard +// Check if HID instance is mounted +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); + +// Check if HID instance with Keyboard is mounted bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, 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); //--------------------------------------------------------------------+ // Application API (Single device) @@ -101,10 +105,6 @@ TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -// TODO used weak attr if build failed without KEYBOARD enabled -// TODO remove -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; - /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address * \retval true if device supports Keyboard interface @@ -170,13 +170,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if device supports Mouse interface or not - * \param[in] dev_addr device address - * \retval true if device supports Mouse interface - * \retval false if device does not support Mouse interface or is not mounted - */ -bool tuh_hid_mouse_mounted(uint8_t dev_addr); - /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a021c11c..f1c386a4d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -152,10 +152,9 @@ uint8_t* usbh_get_enum_buf(void) //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ -tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) +bool tuh_device_configured(uint8_t dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); - return (tusb_device_state_t) _usbh_devices[dev_addr].state; + return _usbh_devices[dev_addr].configured; } tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) diff --git a/src/host/usbh.h b/src/host/usbh.h index 5e7abe868..e503ef8fb 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -88,13 +88,9 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); -static inline bool tuh_device_is_configured(uint8_t dev_addr) -{ - return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; -} +bool tuh_device_configured(uint8_t dev_addr); bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ From 791efecfdfd650e7287388e3f3210b18f7262934 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 00:11:20 +0700 Subject: [PATCH 28/56] add tuh_device_ready() --- src/device/usbd.h | 1 + src/host/usbh.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/device/usbd.h b/src/device/usbd.h index c0bec9566..c707cecfc 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -70,6 +70,7 @@ bool tud_mounted(void); bool tud_suspended(void); // Check if device is ready to transfer +TU_ATTR_ALWAYS_INLINE static inline bool tud_ready(void) { return tud_mounted() && !tud_suspended(); diff --git a/src/host/usbh.h b/src/host/usbh.h index e503ef8fb..590c8a359 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -90,7 +90,17 @@ extern void hcd_int_handler(uint8_t rhport); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); +// Check if device is configured bool tuh_device_configured(uint8_t dev_addr); + +// Check if device is ready to communicate with +TU_ATTR_ALWAYS_INLINE +static inline bool tuh_device_ready(uint8_t dev_addr) +{ + return tuh_device_configured(dev_addr); +} + +// Carry out control transfer bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ From db8ea7ea1c48a04fff6446df294123690dcb7012 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:21:12 +0700 Subject: [PATCH 29/56] clean up --- src/device/usbd.c | 3 +- src/host/usbh.c | 201 ++++++++++++++++++++++++---------------------- 2 files changed, 107 insertions(+), 97 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 280235911..9fddbc299 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1090,7 +1090,7 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ } //--------------------------------------------------------------------+ -// Helper +// USBD API For Class Driver //--------------------------------------------------------------------+ // Parse consecutive endpoint descriptors (IN & OUT) @@ -1184,7 +1184,6 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) #if CFG_TUSB_OS != OPT_OS_NONE // pre-check to help reducing mutex lock TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f1c386a4d..ac0b654ef 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -135,20 +135,11 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - return _usbh_devices[dev_addr].rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -223,6 +214,109 @@ bool tuh_init(uint8_t rhport) return true; } +/* USB Host Driver task + * This top level thread manages all host controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tuh_task(); // tinyusb host task + } + } + @endcode + */ +void tuh_task(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return; + + // Loop until there is no more events in the queue + while (1) + { + hcd_event_t event; + if ( !osal_queue_receive(_usbh_q, &event) ) return; + + switch (event.event_id) + { + case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. + TU_LOG2("USBH DEVICE ATTACH\r\n"); + enum_new_device(&event); + break; + + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + + case HCD_EVENT_XFER_COMPLETE: + { + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// USBH API For Class Driver +//--------------------------------------------------------------------+ + +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + return _usbh_devices[dev_addr].rhport; +} + +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + +//------------- Endpoint API -------------// + bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -278,6 +372,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } @@ -387,7 +482,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) // a device unplugged on hostid, hub_addr, hub_port // return true if found and unmounted device, false if cannot find -static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) @@ -420,90 +515,6 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ } } -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; - - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating - // one device before enumerating another one. - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_new_device(&event); - break; - - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; - - case HCD_EVENT_XFER_COMPLETE: - { - usbh_device_t* dev = &_usbh_devices[event.dev_addr]; - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - //--------------------------------------------------------------------+ // INTERNAL HELPER //--------------------------------------------------------------------+ From 7305fec4db13e846aa945b26d18418ec1e5e4ce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:27:09 +0700 Subject: [PATCH 30/56] change hid device report len from uint8 to uint16 --- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..ccd47a290 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -76,7 +76,7 @@ bool tud_hid_n_ready(uint8_t itf) return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len) { uint8_t const rhport = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; @@ -87,7 +87,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ // prepare data if (report_id) { - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE-1); p_hid->epin_buf[0] = report_id; memcpy(p_hid->epin_buf+1, report, len); @@ -95,7 +95,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ }else { // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE); memcpy(p_hid->epin_buf, report, len); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 7520d3453..a36f7e623 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -61,7 +61,7 @@ bool tud_hid_n_ready(uint8_t itf); bool tud_hid_n_boot_mode(uint8_t itf); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t @@ -128,7 +128,7 @@ static inline bool tud_hid_boot_mode(void) return tud_hid_n_boot_mode(0); } -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) { return tud_hid_n_report(0, report_id, report, len); } From 9324fd8f2e549434fd2a399500ae1dc766530046 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 13:42:52 +0700 Subject: [PATCH 31/56] more hid host API rework --- examples/host/cdc_msc_hid/src/main.c | 28 ++++---- src/class/hid/hid_host.c | 100 +++++++++------------------ src/class/hid/hid_host.h | 42 ++--------- 3 files changed, 56 insertions(+), 114 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 6b2d0affb..c37cad15d 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -160,7 +160,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); if (instance == 0) { - tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } @@ -243,28 +243,30 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) void hid_task(void) { - uint8_t const addr = 1; + uint8_t const daddr = 1; + uint8_t const instance = 0; #if CFG_TUH_HID_KEYBOARD - if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) + if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { - if ( !tuh_hid_keyboard_is_busy(addr) ) + if ( tuh_n_hid_n_ready(daddr, instance) ) { process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } #endif #if CFG_TUH_HID_MOUSE - if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) - { - if ( !tuh_hid_mouse_is_busy(addr) ) - { - process_mouse_report(&usb_mouse_report); - tuh_hid_mouse_get_report(addr, &usb_mouse_report); - } - } + (void) usb_mouse_report; +// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) +// { +// if ( tuh_n_hid_n_ready(daddr, instance) ) +// { +// process_mouse_report(&usb_mouse_report); +// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); +// } +// } #endif } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 72cecb8d1..83e65dc52 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -52,19 +52,19 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - - bool valid; - uint16_t report_size; // TODO remove later + uint16_t ep_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports + uint8_t report_count; // Number of reports struct { - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; + + // TODO just use the endpint size for now + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API @@ -99,59 +99,43 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr) // HID Interface common functions //--------------------------------------------------------------------+ -// called from public API need to validate parameters -tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) { - //------------- parameters validation -------------// - // TODO change to use is configured function - TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; - - return TUSB_ERROR_NONE; + hidh_interface_t* hid_itf = get_instance(daddr, instance); + return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) -//{ -// -//} +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); +} + +bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) +{ + TU_VERIFY( tuh_device_ready(daddr) && report && len); + hidh_interface_t* hid_itf = get_instance(daddr, instance); + + // TODO change to claim endpoint + TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); + + len = tu_min16(len, hid_itf->ep_size); + + return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); +} //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(daddr, instance); - - // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); -} - bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(daddr, instance); // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); -} - -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) -{ - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - - return hidh_interface_get_report(dev_addr, buffer, hid_itf); -} - -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) -{ - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - - return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -165,26 +149,11 @@ static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have 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_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); -} - -bool tuh_hid_mouse_is_busy(uint8_t dev_addr) -{ - return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); -} - -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) -{ - return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]); + return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } #endif -//--------------------------------------------------------------------+ -// GENERIC -//--------------------------------------------------------------------+ - - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -264,10 +233,9 @@ 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->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - hid_itf->valid = true; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->ep_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 0052a2b0c..23b23e657 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -61,7 +61,12 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr); // Check if HID instance is mounted -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); + +// 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_get_report(uint8_t daddr, 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 daddr, uint8_t instance); @@ -69,6 +74,7 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, 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); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ @@ -119,19 +125,6 @@ bool tuh_hid_keyboard_mounted(uint8_t dev_addr); * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. * Alternatively, asynchronous event API can be used */ -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Keyboard interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report); //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred @@ -170,27 +163,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_mouse_get_report. - * Alternatively, asynchronous event API can be used - */ -bool tuh_hid_mouse_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Mouse interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report); - //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device From cc1b83412a0263f0f3d5db492f5680f4a9bb179b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 14:09:33 +0700 Subject: [PATCH 32/56] continue with hid host rework --- src/class/hid/hid_host.c | 112 +++++++++++++++++---------------- src/class/hid/hid_host.h | 132 +++++++++------------------------------ 2 files changed, 85 insertions(+), 159 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83e65dc52..dc29f7322 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,26 +82,25 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; +//------------- Internal prototypes -------------// TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t daddr) + +uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) { - return get_dev(daddr)->inst_count; + return get_dev(dev_addr)->inst_count; } -//--------------------------------------------------------------------+ -// HID Interface common functions -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } @@ -113,29 +112,29 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) +bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) { - TU_VERIFY( tuh_device_ready(daddr) && report && len); - hidh_interface_t* hid_itf = get_instance(daddr, instance); + TU_VERIFY( tuh_device_ready(dev_addr) && report && len); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); + TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); len = tu_min16(len, hid_itf->ep_size); - return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); } //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard - return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -164,26 +163,16 @@ void hidh_init(void) bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { - (void) xferred_bytes; // TODO may need to use this para later + uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - -#if CFG_TUH_HID_KEYBOARD -// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_keyboard_isr(dev_addr, event); -// return true; -// } -#endif - -#if CFG_TUH_HID_MOUSE -// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_mouse_isr(dev_addr, event); -// return true; -// } -#endif + if ( dir == TUSB_DIR_IN ) + { + if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + }else + { + if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + } return true; } @@ -311,7 +300,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -340,7 +329,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id(dev_addr, itf_num); + uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); if (tuh_hid_descriptor_report_cb) @@ -375,30 +364,43 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } -// Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +// Get instance by interface number +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) { for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) { hidh_interface_t *hid = get_instance(dev_addr, inst); - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; - } - - return 0xff; -} - -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; } return NULL; } +// Get instance ID by interface number +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; + } + + return 0xff; +} + +// Get instance ID by endpoint address +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; + } + + return 0xff; +} + #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 23b23e657..45f03a192 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -58,22 +58,46 @@ //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t daddr); +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 daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); // 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_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len); +// Get Report from device +bool tuh_n_hid_n_get_report(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 daddr, uint8_t instance); +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); + +// 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 +TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); + +// Invoked when Sent Report to device +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); //--------------------------------------------------------------------+ // Application API (Single device) @@ -86,106 +110,6 @@ uint8_t tuh_hid_instance_count(void) return tuh_n_hid_instance_count(1); } -//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when report descriptor is received -// Note: enumeration is still not complete yet -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - -TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); - - - -//--------------------------------------------------------------------+ -// KEYBOARD Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/** \defgroup Keyboard_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -/** \brief Check if device supports Keyboard interface or not - * \param[in] dev_addr device address - * \retval true if device supports Keyboard interface - * \retval false if device does not support Keyboard interface or is not mounted - */ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr); - -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. - * Alternatively, asynchronous event API can be used - */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback - */ -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); - -/** @} */ // Keyboard_Host -/** @} */ // ClassDriver_HID_Keyboard - -//--------------------------------------------------------------------+ -// MOUSE Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ - -/** \defgroup Mouse_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback - */ -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Mouse interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); - -/** \brief Callback function that will be invoked when a device with Mouse interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API From 641f55f1f18234dbcf3f2b5d46d2231a5e9abae3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 15:44:00 +0700 Subject: [PATCH 33/56] remove CFG_TUH_HID_KEYBOARD and CFG_TUH_HID_MOUSE --- examples/host/cdc_msc_hid/src/main.c | 30 +++------------------ examples/host/cdc_msc_hid/src/tusb_config.h | 6 ----- src/class/hid/hid_host.c | 4 +-- src/host/hcd.h | 5 ++-- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c37cad15d..17f649aa4 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -51,14 +51,13 @@ 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 +#if CFG_TUH_HID hid_task(); #endif } @@ -109,8 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -#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 }; @@ -158,6 +155,7 @@ 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); if (instance == 0) { tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); @@ -168,11 +166,9 @@ 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); } -#endif - -#if CFG_TUH_HID_MOUSE CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; @@ -225,28 +221,12 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) } -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); -} - -#endif - - void hid_task(void) { uint8_t const daddr = 1; uint8_t const instance = 0; -#if CFG_TUH_HID_KEYBOARD if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { if ( tuh_n_hid_n_ready(daddr, instance) ) @@ -255,9 +235,8 @@ void hid_task(void) tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } -#endif -#if CFG_TUH_HID_MOUSE +// #if CFG_TUH_HID_MOUSE (void) usb_mouse_report; // if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) // { @@ -267,7 +246,6 @@ void hid_task(void) // tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); // } // } -#endif } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e1e02e31e..01296cd26 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -76,13 +76,7 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 - #define CFG_TUH_HID 2 - -#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_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dc29f7322..60ee667d0 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -140,8 +140,8 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ -#if CFG_TUH_HID_MOUSE +// TODO remove static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// @@ -151,8 +151,6 @@ bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } -#endif - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ diff --git a/src/host/hcd.h b/src/host/hcd.h index 4810ef8da..a470a45e8 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -85,9 +85,8 @@ typedef struct #if TUSB_OPT_HOST_ENABLED // Max number of endpoints per device enum { - HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC + - CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - + // TODO better computation + HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, }; From 9ddc3bfd6dc1450d30c16c0a1d07240ea74a13bf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 01:02:47 +0700 Subject: [PATCH 34/56] more host hid API adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- src/class/hid/hid.h | 60 +++++++- src/class/hid/hid_host.c | 148 +++++++++++++++----- src/class/hid/hid_host.h | 35 ++++- 4 files changed, 196 insertions(+), 53 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 01296cd26..fd0432799 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,11 +86,7 @@ // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - -// Max buffer -#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 - +#define CFG_TUH_HID_REPORT_MAX 4 #ifdef __cplusplus } diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..f0ad03603 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -479,6 +479,7 @@ typedef enum //--------------------------------------------------------------------+ // REPORT DESCRIPTOR //--------------------------------------------------------------------+ + //------------- ITEM & TAG -------------// #define HID_REPORT_DATA_0(data) #define HID_REPORT_DATA_1(data) , data @@ -488,18 +489,31 @@ typedef enum #define HID_REPORT_ITEM(data, tag, type, size) \ (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) -#define RI_TYPE_MAIN 0 -#define RI_TYPE_GLOBAL 1 -#define RI_TYPE_LOCAL 2 +// Report Item Types +enum { + RI_TYPE_MAIN = 0, + RI_TYPE_GLOBAL = 1, + RI_TYPE_LOCAL = 2 +}; + +//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// + +// Report Item Main group +enum { + RI_MAIN_INPUT = 8, + RI_MAIN_OUTPUT = 9, + RI_MAIN_COLLECTION = 10, + RI_MAIN_FEATURE = 11, + RI_MAIN_COLLECTION_END = 12 +}; -//------------- MAIN ITEMS 6.2.2.4 -------------// #define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) #define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) #define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) #define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) #define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) -//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------// +//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) #define HID_CONSTANT (1<<0) @@ -527,7 +541,7 @@ typedef enum #define HID_BITFIELD (0<<8) #define HID_BUFFERED_BYTES (1<<8) -//------------- COLLECTION ITEM 6.2.2.6 -------------// +//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// enum { HID_COLLECTION_PHYSICAL = 0, HID_COLLECTION_APPLICATION, @@ -538,7 +552,24 @@ enum { HID_COLLECTION_USAGE_MODIFIER }; -//------------- GLOBAL ITEMS 6.2.2.7 -------------// +//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// + +// Report Item Global group +enum { + RI_GLOBAL_USAGE_PAGE = 0, + RI_GLOBAL_LOGICAL_MIN = 1, + RI_GLOBAL_LOGICAL_MAX = 2, + RI_GLOBAL_PHYSICAL_MIN = 3, + RI_GLOBAL_PHYSICAL_MAX = 4, + RI_GLOBAL_UNIT_EXPONENT = 5, + RI_GLOBAL_UNIT = 6, + RI_GLOBAL_REPORT_SIZE = 7, + RI_GLOBAL_REPORT_ID = 8, + RI_GLOBAL_REPORT_COUNT = 9, + RI_GLOBAL_PUSH = 10, + RI_GLOBAL_POP = 11 +}; + #define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) #define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) @@ -573,6 +604,21 @@ enum { #define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// + +enum { + RI_LOCAL_USAGE = 0, + RI_LOCAL_USAGE_MIN = 1, + RI_LOCAL_USAGE_MAX = 2, + RI_LOCAL_DESIGNATOR_INDEX = 3, + RI_LOCAL_DESIGNATOR_MIN = 4, + RI_LOCAL_DESIGNATOR_MAX = 5, + // 6 is reserved + RI_LOCAL_STRING_INDEX = 7, + RI_LOCAL_STRING_MIN = 8, + RI_LOCAL_STRING_MAX = 9, + RI_LOCAL_DELIMITER = 10, +}; + #define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) #define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 60ee667d0..862026b5b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,14 +35,15 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF +/* + "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ typedef struct { @@ -57,22 +58,14 @@ typedef struct uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports - struct { - uint8_t usage_page; - uint8_t usage; - - // TODO just use the endpint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - }reports[CFG_TUH_HID_REPORT_MAX]; + 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; -}hidh_interface_t; +} hidh_interface_t; typedef struct { @@ -104,6 +97,23 @@ 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) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->boot_protocol; +} + +bool tuh_n_hid_n_boot_mode(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)); @@ -190,6 +200,7 @@ 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); @@ -235,23 +246,25 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de 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_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[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_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[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_MOUSE; + hid_itf->report_info.info[0].in_len = 5; + hid_itf->report_info.info[0].out_len = 0; } else { @@ -326,19 +339,23 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); - //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + 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, inst, usbh_get_enum_buf(), request->wLength); + tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); } - // TODO Report descriptor parser + parse_report_descriptor(hid_itf, desc_report, desc_len); // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -346,8 +363,69 @@ 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) +{ + enum + { + USAGE_PAGE = 0x05, + USAGE = 0x09, + USAGE_MIN = 0x19, + USAGE_MAX = 0x29, + LOGICAL_MIN = 0x15, + LOGICAL_MAX = 0x25, + REPORT_SIZE = 0x75, + REPORT_COUNT = 0x95 + }; + + // Short Item 6.2.2.2 USB HID 1.11 + union TU_ATTR_PACKED + { + uint8_t byte; + struct TU_ATTR_PACKED + { + uint8_t size : 2; + uint8_t type : 2; + uint8_t tag : 4; + }; + } header; + + while(desc_len) + { + header.byte = *desc_report++; + + uint8_t const tag = header.tag; + uint8_t const type = header.type; + uint8_t const size = header.size; + + desc_len--; + + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); + for(uint32_t i=0; i Date: Fri, 14 May 2021 12:23:09 +0700 Subject: [PATCH 35/56] adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 + src/class/hid/hid_host.c | 55 ++++++++++++++++----- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fd0432799..7c13cbd2f 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,6 +84,8 @@ //------------- HID -------------// +//#define CFG_TUH_HID_EP_BUFSIZE 64 + // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports #define CFG_TUH_HID_REPORT_MAX 4 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 862026b5b..ba9707a69 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -366,19 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // 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) { - enum - { - USAGE_PAGE = 0x05, - USAGE = 0x09, - USAGE_MIN = 0x19, - USAGE_MAX = 0x29, - LOGICAL_MIN = 0x15, - LOGICAL_MAX = 0x25, - REPORT_SIZE = 0x75, - REPORT_COUNT = 0x95 - }; - - // Short Item 6.2.2.2 USB HID 1.11 + // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED { uint8_t byte; @@ -407,12 +395,53 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de switch(type) { case RI_TYPE_MAIN: + switch (tag) + { + case RI_MAIN_INPUT: break; + case RI_MAIN_OUTPUT: break; + case RI_MAIN_FEATURE: break; + case RI_MAIN_COLLECTION: break; + case RI_MAIN_COLLECTION_END: break; + + default: break; + } break; case RI_TYPE_GLOBAL: + switch(tag) + { + case RI_GLOBAL_USAGE_PAGE : break; + case RI_GLOBAL_LOGICAL_MIN : break; + case RI_GLOBAL_LOGICAL_MAX : break; + case RI_GLOBAL_PHYSICAL_MIN : break; + case RI_GLOBAL_PHYSICAL_MAX : 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; + + default: break; + } break; case RI_TYPE_LOCAL: + switch(tag) + { + case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE_MIN : break; + case RI_LOCAL_USAGE_MAX : break; + case RI_LOCAL_DESIGNATOR_INDEX : break; + case RI_LOCAL_DESIGNATOR_MIN : break; + case RI_LOCAL_DESIGNATOR_MAX : break; + case RI_LOCAL_STRING_INDEX : break; + case RI_LOCAL_STRING_MIN : break; + case RI_LOCAL_STRING_MAX : break; + case RI_LOCAL_DELIMITER : break; + default: break; + } break; // error From 93661042d96d08ad9f0de66fa44d22bdc4faeb08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 17:47:02 +0700 Subject: [PATCH 36/56] more API update - remove tuh_n_hid_n_get_report() - usbh auto queue get report and invoke callback when received data --- examples/host/cdc_msc_hid/src/main.c | 35 ++----------- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/hid/hid_host.c | 55 ++++++++++----------- src/class/hid/hid_host.h | 10 ++-- 4 files changed, 38 insertions(+), 64 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 17f649aa4..40642561b 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -108,7 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -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 @@ -156,10 +155,6 @@ 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); - - if (instance == 0) { - tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -169,9 +164,6 @@ void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } - -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 -------------// @@ -220,32 +212,13 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) 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) { - uint8_t const daddr = 1; - uint8_t const instance = 0; - - if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) - { - if ( tuh_n_hid_n_ready(daddr, instance) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } - } - -// #if CFG_TUH_HID_MOUSE - (void) usb_mouse_report; -// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) -// { -// if ( tuh_n_hid_n_ready(daddr, instance) ) -// { -// process_mouse_report(&usb_mouse_report); -// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); -// } -// } } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 7c13cbd2f..8c82c0fef 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,7 +84,7 @@ //------------- HID -------------// -//#define CFG_TUH_HID_EP_BUFSIZE 64 +#define CFG_TUH_HID_EP_BUFSIZE 64 // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ba9707a69..4c32d9b33 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -53,7 +53,9 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - uint16_t ep_size; + + uint16_t epin_size; + uint16_t epout_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol @@ -65,6 +67,9 @@ typedef struct uint8_t rid_mouse; uint8_t rid_gamepad; uint8_t rid_consumer; + + uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; + uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; } hidh_interface_t; typedef struct @@ -82,6 +87,11 @@ static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); +TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) +{ + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); +} + //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ @@ -122,19 +132,6 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) -{ - TU_VERIFY( tuh_device_ready(dev_addr) && report && len); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); - - len = tu_min16(len, hid_itf->ep_size); - - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); -} - //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ @@ -147,18 +144,11 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ - // TODO remove -static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- Public API -------------// 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) && (mouseh_data[dev_addr-1].ep_in != 0); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -173,10 +163,17 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_get_report_cb) + { + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + } + + // queue next report + hidh_get_report(dev_addr, hid_itf); }else { if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); @@ -233,7 +230,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->ep_size = desc_ep->wMaxPacketSize.size; + hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; @@ -357,6 +354,9 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // enumeration is complete if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + // queue transfer for IN endpoint + hidh_get_report(dev_addr, hid_itf); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -381,13 +381,12 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de while(desc_len) { header.byte = *desc_report++; + desc_len--; - uint8_t const tag = header.tag; + uint8_t const tag = header.tag; uint8_t const type = header.type; uint8_t const size = header.size; - desc_len--; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; i Date: Fri, 14 May 2021 18:07:58 +0700 Subject: [PATCH 37/56] fix compile --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a36f7e623..6b876ae74 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -80,7 +80,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); From da6a7fb2bbb5ee07914e684a5162a9534c10bbb1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 08:18:25 +0700 Subject: [PATCH 38/56] update hid report descriptor macro --- src/class/hid/hid.h | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index f0ad03603..42e16b288 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -507,11 +507,11 @@ enum { RI_MAIN_COLLECTION_END = 12 }; -#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) +#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) +#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) +#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) +#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) +#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) //------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) @@ -570,38 +570,38 @@ enum { RI_GLOBAL_POP = 11 }; -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) +#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) +#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n) +#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) -#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n) +#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) +#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) +#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) -#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) +#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) +#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// @@ -619,14 +619,14 @@ enum { RI_LOCAL_DELIMITER = 10, }; -#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) +#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) +#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n) +#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n) +#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) //--------------------------------------------------------------------+ // Usage Table From ffdcf9a0d00ad8eba544c4404e27275685ef9cab Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 13:54:39 +0700 Subject: [PATCH 39/56] 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); From 2df5a5367f6b8a6649d39d3ba7ebc0af56db9ad2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 13:12:33 +0700 Subject: [PATCH 40/56] update hid host get/set protocol to match device --- src/class/hid/hid_device.h | 2 +- src/class/hid/hid_host.c | 12 ++++++------ src/class/hid/hid_host.h | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index bccfb8d4d..bfaa35f7d 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -57,7 +57,7 @@ // Check if the interface is ready to use bool tud_hid_n_ready(uint8_t instance); -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tud_hid_n_interface_protocol(uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8d60ceb71..62e6c4b76 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,8 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_interface; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol + uint8_t itf_protocol; // 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]; @@ -102,16 +102,16 @@ bool tuh_n_hid_n_mounted(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_interface; + return hid_itf->itf_protocol; } 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; + return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } -//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) //{ // //} @@ -212,7 +212,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_interface = desc_itf->bInterfaceProtocol; + hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; if ( HID_ITF_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 87b86c90b..677c8c9de 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -74,16 +74,16 @@ 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 interface protocol check out hid_protocol_type_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values 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 +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: as HID spec, device will be initialized in Report mode bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Set protocol to Boot or Report mode. +// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // 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); +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // 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. From 7d0fb6f87a3b7d200fcf572c8d99ef87ef0e5982 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 May 2021 11:05:44 +0700 Subject: [PATCH 41/56] enable ci for esp32s3 boards --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 187b7d4a6..01b280fc4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -199,7 +199,7 @@ jobs: - 'espressif_kaluga_1' - 'espressif_saola_1' # ESP32-S3 - # - 'espressif_addax_1' # temporarily remove the board from test while espressif MR is not merged + - 'espressif_addax_1' steps: - name: Setup Python From 327336e921cb75359878a4cf5c77af323dd8da14 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 May 2021 11:16:26 +0700 Subject: [PATCH 42/56] fix build for rp2040 --- examples/host/cdc_msc_hid/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) 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 ) From 0b1257266bd301d7eaf7f11634f5fb193c2811a8 Mon Sep 17 00:00:00 2001 From: noodlefighter Date: Thu, 20 May 2021 17:41:07 +0800 Subject: [PATCH 43/56] fix uac2_headset example: type of bRequest should be uint8_t, not enumerate --- examples/device/uac2_headset/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index d29deb588..57abafe6c 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -149,7 +149,7 @@ typedef struct TU_ATTR_PACKED uint8_t bmRequestType; }; - audio_cs_req_t bRequest; + uint8_t bRequest; ///< Request type audio_cs_req_t uint8_t bChannelNumber; uint8_t bControlSelector; union From 99add05aa78a0fd5d462ab822d0c4656c41c59d7 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:27:28 +0700 Subject: [PATCH 44/56] simplify hid api add hid set_protocol() and set_protocol_complete_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 113 +++++++++++------------- src/class/hid/hid_host.h | 13 +-- 3 files changed, 61 insertions(+), 67 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index de92ab841..72e7c30db 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -64,7 +64,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // 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); + uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 62e6c4b76..e35e4e4da 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -51,15 +51,15 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t itf_protocol; // None, Keyboard, Mouse + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + uint8_t report_desc_type; uint16_t report_desc_len; uint16_t epin_size; uint16_t epout_size; - uint8_t itf_protocol; // 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]; } hidh_interface_t; @@ -76,7 +76,6 @@ static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) @@ -93,28 +92,64 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return hid_itf->protocol_mode; } -// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -//{ -// -//} +static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; + + if (tuh_hid_set_protocol_complete_cb) + { + tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); + } + + return true; +} + +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); + + TU_LOG2("Set Protocol = %d\r\n", protocol); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = hid_itf->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); + return true; +} //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ @@ -209,39 +244,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_desc_type = desc_hid->bReportType; 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->itf_protocol = desc_itf->bInterfaceProtocol; - - if ( HID_ITF_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.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_ITF_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.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 - { - // Unknown protocol - TU_ASSERT(false); - } - } + hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -279,9 +283,9 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; - uint8_t const itf_num = (uint8_t) request->wIndex; - - hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -509,19 +513,6 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } -// Get instance by interface number -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; - } - - return NULL; -} - // Get instance ID by interface number static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 677c8c9de..dc0d8c935 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -72,18 +72,18 @@ typedef struct 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); +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// 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, uint8_t protocol); +// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // 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. @@ -116,6 +116,9 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re // 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); +// Invoked when Set Protocol request is complete +TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ From 89dad1ad414e36aa3f0d69b35d06ec82c3e0f168 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:48:07 +0700 Subject: [PATCH 45/56] update app --- examples/host/cdc_msc_hid/src/hid_app.c | 10 ++++++++++ src/class/hid/hid_host.h | 4 +--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 72e7c30db..628ab3e7d 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -29,6 +29,10 @@ //--------------------------------------------------------------------+ // 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 }; @@ -165,6 +169,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) void cursor_movement(int8_t x, int8_t y, int8_t wheel) { +#if USE_ANSI_ESCAPE // Move X using ansi escape if ( x < 0) { @@ -191,6 +196,11 @@ void cursor_movement(int8_t x, int8_t y, int8_t wheel) { 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) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index dc0d8c935..1537216bb 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -63,9 +63,7 @@ typedef struct //--------------------------------------------------------------------+ // Application API (Multiple devices) -// Note: -// - tud_n : is multiple devices API -// - class_n : is multiple instances API +// - tud_n : is multiple devices API //--------------------------------------------------------------------+ // Get the number of HID instances From 350dfb2ea37cebc59ef9fd6b63d2aae1b8cb48da Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 18:17:32 +0700 Subject: [PATCH 46/56] more hid api rename --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 10 ++++----- src/class/hid/hid_host.h | 27 ++++++------------------- 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 628ab3e7d..eab555fc1 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -68,7 +68,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); + uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e35e4e4da..90a848fc1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -87,24 +87,24 @@ TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) +uint8_t tuh_hid_instance_count(uint8_t dev_addr) { return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -126,7 +126,7 @@ static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const return true; } -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1537216bb..3cf8dc70f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -62,26 +62,25 @@ typedef struct } tuh_hid_report_info_t; //--------------------------------------------------------------------+ -// Application API (Multiple devices) -// - tud_n : is multiple devices API +// Application API //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); +uint8_t tuh_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // 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. @@ -94,8 +93,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint // 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); -//------------- -------------// - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -117,18 +114,6 @@ TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t insta // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); -//--------------------------------------------------------------------+ -// Application API (Single device) -//--------------------------------------------------------------------+ - -// Get the number of HID instances -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_hid_instance_count(void) -{ - return tuh_n_hid_instance_count(1); -} - - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ From ad845db6a50c1d90e4f7cc45ca16a8861ee2da4d Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:54:59 +0700 Subject: [PATCH 47/56] improve hid parser --- examples/host/cdc_msc_hid/src/hid_app.c | 50 +++++++++++++--------- src/class/hid/hid_host.c | 56 ++++++++----------------- src/class/hid/hid_host.h | 6 +-- 3 files changed, 50 insertions(+), 62 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index eab555fc1..71904245a 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -37,14 +37,16 @@ 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[CFG_TUH_HID][MAX_REPORT]; +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 } //--------------------------------------------------------------------+ @@ -55,21 +57,13 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ { 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_hid_interface_protocol(dev_addr, instance); - printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); + + // 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]); } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -82,20 +76,36 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re (void) dev_addr; uint8_t const rpt_count = _report_count[instance]; - tuh_hid_report_info_t* rpt_info; + tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; + tuh_hid_report_info_t* rpt_info = NULL; - if (rpt_count) + 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 - // Note: report index = report ID - 1 - uint8_t idx = report[0] - 1; - rpt_info = &_report_info[instance][idx]; + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 90a848fc1..15533cf3a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -337,7 +337,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // 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) +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, 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 @@ -351,18 +351,16 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint }; } header; - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info; + tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info_arr; // 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) { @@ -394,6 +392,11 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_MAIN_COLLECTION_END: ri_collection_depth--; + if (ri_collection_depth == 0) + { + info++; + report_num++; + } break; default: break; @@ -404,11 +407,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_GLOBAL_USAGE_PAGE: - // only take in account the "usage page" before starting COLLECTION - if ( ri_collection_depth == 0) - { - memcpy(&ri_usage_page, desc_report, size); - } + // only take in account the "usage page" before REPORT ID + if ( ri_collection_depth == 0 ) memcpy(&info->usage_page, desc_report, size); break; case RI_GLOBAL_LOGICAL_MIN : break; @@ -417,23 +417,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_GLOBAL_PHYSICAL_MAX : break; case RI_GLOBAL_REPORT_ID: - report_num++; - if (data8 <= arr_count) - { - uint8_t const idx = data8 - 1; - if ( info != &report_info[idx] ) - { - // copy info so far to its correct report ID, and update info pointer - report_info[idx] = *info; - info = &report_info[idx]; - } - - info->usage_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); - } + info->report_id = data8; break; case RI_GLOBAL_REPORT_SIZE: @@ -457,8 +441,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_LOCAL_USAGE: - // only take in account the "usage" before starting COLLECTION - if ( ri_collection_depth == 0) ri_usage = data8; + // only take in account the "usage" before starting REPORT ID + if ( ri_collection_depth == 0 ) info->usage = data8; break; case RI_LOCAL_USAGE_MIN : break; @@ -482,16 +466,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint desc_len -= size; } - if ( report_num == 0 ) + for ( uint8_t i = 0; i < report_num; i++ ) { - 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); + info = report_info_arr+i; + TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, 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 3cf8dc70f..1b8acda05 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,8 +53,9 @@ typedef struct { + uint8_t report_id; + uint8_t usage; uint16_t usage_page; - uint8_t usage; // TODO still use the endpoint size for now // uint8_t in_len; // length of IN report @@ -83,9 +84,8 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // 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; +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, 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); From 63c57ed1a4285671ba38d87b8b77fd68c55880e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:55:42 +0700 Subject: [PATCH 48/56] clean p --- examples/host/cdc_msc_hid/src/tusb_config.h | 4 ---- src/class/hid/hid_host.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8c82c0fef..8253964c0 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,10 +86,6 @@ #define CFG_TUH_HID_EP_BUFSIZE 64 -// Max number of reports per interface -// E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1b8acda05..3ac1f7c69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,10 +42,6 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_REPORT_MAX -#define CFG_TUH_HID_REPORT_MAX 4 -#endif - // TODO Highspeed interrupt can be up to 512 bytes #ifndef CFG_TUH_HID_EP_BUFSIZE #define CFG_TUH_HID_EP_BUFSIZE 64 From df65c35b31581881b2bf49d9e16608d46f98fe4b Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:48:42 +0700 Subject: [PATCH 49/56] implement hid host set report with control transfer rename mount, umount callback --- examples/host/cdc_msc_hid/src/hid_app.c | 4 +- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/class/hid/hid_host.c | 54 ++++++++++++++++++++++--- src/class/hid/hid_host.h | 16 ++++---- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 71904245a..79f10251f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,7 +53,7 @@ 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) +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); @@ -66,7 +66,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +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); } 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/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 15533cf3a..f15f0b72a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -73,6 +73,8 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; //------------- Internal prototypes -------------// + +// Get HID device & interface TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); @@ -131,7 +133,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); - TU_LOG2("Set Protocol = %d\r\n", protocol); + TU_LOG2("HID Set Protocol = %d\r\n", protocol); tusb_control_request_t const request = { @@ -151,6 +153,48 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return true; } +static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2("HID Set Report complete\r\n"); + + if (tuh_hid_set_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); + } + + return true; +} + + +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + return true; +} + //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -185,7 +229,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { - if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); +// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); } return true; @@ -194,9 +238,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 void hidh_close(uint8_t dev_addr) { hidh_device_t* hid_dev = get_dev(dev_addr); - if (tuh_hid_unmounted_cb) + if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); @@ -322,7 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint16_t const desc_len = request->wLength; // enumeration is complete - tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); + tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3ac1f7c69..f962f5b0a 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -79,6 +79,10 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +// Set Report using control endpoint +// report_type is either Intput, Output or Feature, (value from hid_report_type_t) +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + // Parse report descriptor into array of report_info struct and return number of reports. // For complicated report, application should write its own parser. uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; @@ -86,9 +90,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //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); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -96,16 +97,17 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // 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_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +void tuh_hid_mount_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); +TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint 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); +// Invoked when Sent Report to device via either control endpoint +// len = 0 indicate there is error in the transfer e.g stalled response +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 4869c8c03..08b4db9e1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -300,7 +300,7 @@ void msch_close(uint8_t dev_addr) tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); + if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 7ebc9b5a8..b5ffcd401 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -109,7 +109,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API From b8e019da321512758959f6fb3b2f0192bda698dc Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:51:30 +0700 Subject: [PATCH 50/56] rename tuh_hid_get_report_cb to tuh_hid_report_received_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 7 ++++++- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 79f10251f..67be8d50f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,6 +53,9 @@ void hid_app_task(void) // 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); @@ -66,12 +69,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re 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); } -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index f15f0b72a..63983ca5f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -223,7 +223,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 { 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); + tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f962f5b0a..3f9979f52 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -102,8 +102,8 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular or control endpoint -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response From a2c4a48dd627828f5899e5ab70412594b60f37c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:03:21 +0700 Subject: [PATCH 51/56] add tuh_hid_report_sent_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 5 +++-- src/class/hid/hid_host.h | 10 +++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 67be8d50f..23ab12404 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -75,7 +75,7 @@ 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 either regular endpoint +// 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; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 63983ca5f..778a897be 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -171,7 +171,6 @@ static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * return true; } - bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -203,6 +202,8 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); //} +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -229,7 +230,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { -// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); } return true; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3f9979f52..ea693df69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -90,6 +90,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +// Send report using interrupt endpoint +// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -102,9 +106,13 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular endpoint +// Invoked when received report from device via interrupt endpoint +// Note: if there is report ID (composite), it is 1st byte of report void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when sent report to device successfully via interrupt endpoint +TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); From f13a3c04f790a865472a7ed0b57182f401189977 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:43:55 +0700 Subject: [PATCH 52/56] fix missing report in tuh_hid_set_report() --- src/class/hid/hid_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 778a897be..6c0c97095 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -190,7 +190,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .wLength = len }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); return true; } From a1dab1611bad43cfc3c2dcce58c1dce442287eb9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 23:30:41 +0700 Subject: [PATCH 53/56] get protocol when enum with hid boot interface --- src/class/hid/hid_host.c | 46 ++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6c0c97095..e3ae5a155 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -251,8 +251,9 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -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); +static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc (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); bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { @@ -299,11 +300,14 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // Idle rate = 0 mean only report when there is changes uint16_t const idle_rate = 0; // SET IDLE request, device can stall if not support this request - TU_LOG2("Set Idle \r\n"); + TU_LOG2("HID Set Idle \r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -318,14 +322,42 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); return true; } -bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE, therefore we could ignore its result + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + (void) result; + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + TU_LOG2("HID Get Protocol\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, + .wValue = 0, + .wIndex = hid_itf->itf_num, + .wLength = 1 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); + return false; +} + +static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; @@ -355,7 +387,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r return true; } -bool config_get_report_desc_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) { TU_ASSERT(XFER_RESULT_SUCCESS == result); From 8cffe4897eb114d65ff60685e111ff3e03d0fd74 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 13:56:32 +0700 Subject: [PATCH 54/56] change hid device internal boot_mode to protocol_mode --- src/class/hid/hid_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ab9ef3ad8..0d9cdb22b 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,7 @@ typedef struct uint8_t ep_out; // optional Out endpoint uint8_t itf_protocol; // Boot mouse or keyboard - bool boot_mode; // default = false (Report) + uint8_t protocol_mode; // Boot (0) or Report protocol (1) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) uint8_t tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return _hidd_itf[instance].protocol_mode; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -213,7 +213,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - p_hid->boot_mode = false; // default mode is REPORT + p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode p_hid->itf_num = desc_itf->bInterfaceNumber; // Use offsetof to avoid pointer to the odd/misaligned address @@ -326,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); - tud_control_xfer(rhport, request, &protocol, 1); + tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); } break; @@ -338,10 +337,10 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); + p_hid->protocol_mode = (uint8_t) request->wValue; if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); + tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); } } break; From 3654d96e07f63e041f750aafd125c2c8bca27aa5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 14:11:12 +0700 Subject: [PATCH 55/56] only invoke tuh_msc_umount_cb() if needed --- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e3ae5a155..1bc86e4ad 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -241,7 +241,7 @@ void hidh_close(uint8_t dev_addr) hidh_device_t* hid_dev = get_dev(dev_addr); if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 08b4db9e1..ca360ca2a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -297,10 +297,11 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + + tu_memclr(p_msc, sizeof(msch_interface_t)); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) From 4f033321189eb572c870d08281dd06e044c7597e Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 20:14:01 +0700 Subject: [PATCH 56/56] clean up --- src/device/dcd.h | 6 ------ src/host/hcd.h | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/device/dcd.h b/src/device/dcd.h index 1e5b3ff1e..71e88054c 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -24,10 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbd - * \defgroup group_dcd Device Controller Driver (DCD) - * @{ */ - #ifndef _TUSB_DCD_H_ #define _TUSB_DCD_H_ @@ -168,5 +164,3 @@ extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t x #endif #endif /* _TUSB_DCD_H_ */ - -/// @} diff --git a/src/host/hcd.h b/src/host/hcd.h index a470a45e8..ba6a9c5ca 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -24,14 +24,10 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbh - * \defgroup Group_HCD Host Controller Driver (HCD) - * @{ */ - #ifndef _TUSB_HCD_H_ #define _TUSB_HCD_H_ -#include +#include "common/tusb_common.h" #ifdef __cplusplus extern "C" { @@ -95,27 +91,46 @@ enum { #endif //--------------------------------------------------------------------+ -// Controller & Port API +// Controller API //--------------------------------------------------------------------+ + +// Initialize controller to host mode bool hcd_init(uint8_t rhport); + +// Interrupt Handler void hcd_int_handler(uint8_t rhport); + +// Enable USB interrupt void hcd_int_enable (uint8_t rhport); + +// Disable USB interrupt void hcd_int_disable(uint8_t rhport); // Get micro frame number (125 us) uint32_t hcd_uframe_number(uint8_t rhport); // Get frame number (1ms) -static inline uint32_t hcd_frame_number(uint8_t rhport) +TU_ATTR_ALWAYS_INLINE static inline +uint32_t hcd_frame_number(uint8_t rhport) { return hcd_uframe_number(rhport) >> 3; } -/// return the current connect status of roothub port -bool hcd_port_connect_status(uint8_t hostid); -void hcd_port_reset(uint8_t hostid); +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport); + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport); + +// TODO implement later void hcd_port_reset_end(uint8_t rhport); -tusb_speed_t hcd_port_speed_get(uint8_t hostid); + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); @@ -123,6 +138,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ + bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -134,14 +150,12 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); //--------------------------------------------------------------------+ -// PIPE API +// PIPE API - TODO remove later //--------------------------------------------------------------------+ // TODO control xfer should be used via usbh layer bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -// tusb_error_t hcd_pipe_cancel(); - //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ @@ -163,5 +177,3 @@ extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t #endif #endif /* _TUSB_HCD_H_ */ - -/// @}