Просмотр исходного кода

Merge remote-tracking branch 'hathach/master'

tfx2001 4 лет назад
Родитель
Сommit
bd78dde047
100 измененных файлов с 2696 добавлено и 664 удалено
  1. 5 4
      .github/ISSUE_TEMPLATE/bug_report.yml
  2. 1 1
      docs/reference/supported.rst
  3. 0 4
      examples/device/audio_4_channel_mic/src/tusb_config.h
  4. 0 4
      examples/device/audio_test/src/tusb_config.h
  5. 2 7
      examples/device/cdc_dual_ports/src/tusb_config.h
  6. 2 8
      examples/device/cdc_msc/src/tusb_config.h
  7. 2 7
      examples/device/dfu/src/tusb_config.h
  8. 2 7
      examples/device/dfu_runtime/src/tusb_config.h
  9. 2 7
      examples/device/dynamic_configuration/src/tusb_config.h
  10. 2 8
      examples/device/hid_boot_interface/src/tusb_config.h
  11. 2 8
      examples/device/hid_composite/src/tusb_config.h
  12. 1 1
      examples/device/hid_composite_freertos/src/CMakeLists.txt
  13. 2 7
      examples/device/hid_composite_freertos/src/tusb_config.h
  14. 2 7
      examples/device/hid_generic_inout/src/tusb_config.h
  15. 2 8
      examples/device/hid_multiple_interface/src/tusb_config.h
  16. 2 8
      examples/device/midi_test/src/tusb_config.h
  17. 2 7
      examples/device/msc_dual_lun/src/tusb_config.h
  18. 2 7
      examples/device/net_lwip_webserver/src/tusb_config.h
  19. 0 4
      examples/device/uac2_headset/src/tusb_config.h
  20. 1 1
      examples/device/uac2_headset/src/usb_descriptors.h
  21. 2 7
      examples/device/usbtmc/src/tusb_config.h
  22. 2 7
      examples/device/video_capture/src/tusb_config.h
  23. 2 7
      examples/device/webusb_serial/src/tusb_config.h
  24. 27 0
      examples/host/bare_api/CMakeLists.txt
  25. 27 0
      examples/host/bare_api/Makefile
  26. 9 0
      examples/host/bare_api/only.txt
  27. 221 0
      examples/host/bare_api/src/main.c
  28. 94 0
      examples/host/bare_api/src/tusb_config.h
  29. 0 1
      examples/host/cdc_msc_hid/Makefile
  30. 0 1
      examples/host/hid_controller/Makefile
  31. 28 0
      examples/host/hid_to_cdc/CMakeLists.txt
  32. 19 0
      examples/host/hid_to_cdc/Makefile
  33. 2 0
      examples/host/hid_to_cdc/only.txt
  34. 315 0
      examples/host/hid_to_cdc/src/main.c
  35. 163 0
      examples/host/hid_to_cdc/src/tusb_config.h
  36. 266 0
      examples/host/hid_to_cdc/src/usb_descriptors.c
  37. 1 1
      hw/bsp/board.h
  38. 3 3
      hw/bsp/brtmm90x/family.c
  39. 1 1
      hw/bsp/d5035_01/d5035_01.c
  40. 1 1
      hw/bsp/da14695_dk_usb/da14695_dk_usb.c
  41. 2 2
      hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
  42. 2 2
      hw/bsp/frdm_kl25z/frdm_kl25z.c
  43. 3 0
      hw/bsp/imxrt/boards/mimxrt1060_evk/board.mk
  44. 3 0
      hw/bsp/imxrt/boards/mimxrt1064_evk/board.mk
  45. 22 5
      hw/bsp/imxrt/family.c
  46. 7 0
      hw/bsp/imxrt/family.mk
  47. 2 2
      hw/bsp/lpcxpresso1769/lpcxpresso1769.c
  48. 2 2
      hw/bsp/mbed1768/mbed1768.c
  49. 5 5
      hw/bsp/msp432e4/family.c
  50. 1 1
      hw/bsp/nrf/family.c
  51. 2 2
      hw/bsp/rp2040/family.c
  52. 0 1
      hw/bsp/rp2040/family.cmake
  53. 2 2
      hw/bsp/rx/boards/rx65n_target/rx65n_target.c
  54. 1 1
      hw/bsp/same54xplainedpro/same54xplainedpro.c
  55. 122 0
      hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h
  56. 9 0
      hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk
  57. 171 0
      hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld
  58. 190 0
      hw/bsp/stm32wb/family.c
  59. 44 0
      hw/bsp/stm32wb/family.mk
  60. 349 0
      hw/bsp/stm32wb/stm32wbxx_hal_conf.h
  61. 2 2
      hw/bsp/tm4c123/family.c
  62. 1 0
      hw/mcu/st/cmsis_device_wb
  63. 1 0
      hw/mcu/st/stm32wbxx_hal_driver
  64. 3 1
      repository.yml
  65. 2 2
      src/class/audio/audio_device.c
  66. 1 1
      src/class/bth/bth_device.c
  67. 1 1
      src/class/cdc/cdc_device.c
  68. 3 3
      src/class/cdc/cdc_host.c
  69. 11 1
      src/class/cdc/cdc_rndis_host.c
  70. 1 1
      src/class/cdc/cdc_rndis_host.h
  71. 1 1
      src/class/dfu/dfu_device.c
  72. 1 1
      src/class/dfu/dfu_rt_device.c
  73. 4 1
      src/class/hid/hid.h
  74. 1 1
      src/class/hid/hid_device.c
  75. 20 28
      src/class/hid/hid_host.c
  76. 1 1
      src/class/midi/midi_device.c
  77. 2 1
      src/class/msc/msc_device.c
  78. 1 1
      src/class/msc/msc_host.c
  79. 1 1
      src/class/net/ecm_rndis_device.c
  80. 1 1
      src/class/net/ncm_device.c
  81. 1 1
      src/class/usbtmc/usbtmc_device.c
  82. 15 4
      src/class/vendor/vendor_device.c
  83. 9 0
      src/class/vendor/vendor_device.h
  84. 1 1
      src/class/vendor/vendor_host.c
  85. 6 6
      src/class/vendor/vendor_host.h
  86. 1 1
      src/class/video/video_device.c
  87. 2 146
      src/common/tusb_common.h
  88. 8 4
      src/common/tusb_compiler.h
  89. 174 0
      src/common/tusb_debug.h
  90. 0 75
      src/common/tusb_error.h
  91. 130 72
      src/common/tusb_mcu.h
  92. 65 0
      src/common/tusb_private.h
  93. 1 8
      src/common/tusb_types.h
  94. 0 28
      src/common/tusb_verify.h
  95. 1 2
      src/device/dcd.h
  96. 44 77
      src/device/usbd.c
  97. 4 4
      src/device/usbd.h
  98. 1 1
      src/device/usbd_control.c
  99. 3 1
      src/device/usbd_pvt.h
  100. 15 15
      src/host/hcd.h

+ 5 - 4
.github/ISSUE_TEMPLATE/bug_report.yml

@@ -60,11 +60,12 @@ body:
 
   - type: textarea
     attributes:
-      label: Debug Log
+      label: Debug Log as txt file
       placeholder: |
-        TinyUSB debug log where the issue occurred as attached txt file, best with comments to explain the actual events.
-
-        Note: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h. 
+        Attach your debug log txt file here, where the issue occurred, best with comments to explain the actual events.
+        
+        Note1: Please DO NOT paste your lengthy log contents here since it hurts the readibility.
+        Note2: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h. 
         More information can be found at [example's readme](https://github.com/hathach/tinyusb/blob/master/docs/getting_started.md)
     validations:
       required: false

+ 1 - 1
docs/reference/supported.rst

@@ -42,7 +42,7 @@ Supported MCUs
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
 | NXP          | iMXRT   | RT10xx      | ✔      | ✔    | ✔         | ci_hs             |              |
 |              +---------+-------------+--------+------+-----------+-------------------+--------------+
-|              | Kinetis | KL25        | ✔      | ⚠     | ✖         |                   |              |
+|              | Kinetis | KL25        | ✔      | ⚠    | ✖         |                   |              |
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
 |              |         | K32L2       | ✔      |      | ✖         |                   |              |
 |              +---------+-------------+--------+------+-----------+-------------------+--------------+

+ 0 - 4
examples/device/audio_4_channel_mic/src/tusb_config.h

@@ -39,11 +39,7 @@ extern "C" {
 #error CFG_TUSB_MCU must be defined
 #endif
 
-#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
-#define CFG_TUSB_RHPORT0_MODE       (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
-#else
 #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_DEVICE
-#endif
 
 #ifndef CFG_TUSB_OS
 #define CFG_TUSB_OS                 OPT_OS_NONE

+ 0 - 4
examples/device/audio_test/src/tusb_config.h

@@ -39,11 +39,7 @@ extern "C" {
 #error CFG_TUSB_MCU must be defined
 #endif
 
-#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
-#define CFG_TUSB_RHPORT0_MODE       (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
-#else
 #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_DEVICE
-#endif
 
 #ifndef CFG_TUSB_OS
 #define CFG_TUSB_OS                 OPT_OS_NONE

+ 2 - 7
examples/device/cdc_dual_ports/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 8
examples/device/cdc_msc/src/tusb_config.h

@@ -45,15 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
-      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
-      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/dfu/src/tusb_config.h

@@ -27,14 +27,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/dfu_runtime/src/tusb_config.h

@@ -27,14 +27,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/dynamic_configuration/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 8
examples/device/hid_boot_interface/src/tusb_config.h

@@ -45,15 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X || \
-       CFG_TUSB_MCU == OPT_MCU_FT90X   || CFG_TUSB_MCU == OPT_MCU_FT93X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 8
examples/device/hid_composite/src/tusb_config.h

@@ -45,15 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
-      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
-      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 1 - 1
examples/device/hid_composite_freertos/src/CMakeLists.txt

@@ -31,5 +31,5 @@ target_sources(${COMPONENT_TARGET} PUBLIC
   "${TOP}/src/class/net/ncm_device.c"
   "${TOP}/src/class/usbtmc/usbtmc_device.c"
   "${TOP}/src/class/vendor/vendor_device.c"
-  "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c"
+  "${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c"
 )

+ 2 - 7
examples/device/hid_composite_freertos/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/hid_generic_inout/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 8
examples/device/hid_multiple_interface/src/tusb_config.h

@@ -45,15 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56 || \
-       CFG_TUSB_MCU == OPT_MCU_FT90X   || CFG_TUSB_MCU == OPT_MCU_FT93X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 8
examples/device/midi_test/src/tusb_config.h

@@ -45,15 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56 || \
-       CFG_TUSB_MCU == OPT_MCU_FT90X   || CFG_TUSB_MCU == OPT_MCU_FT93X)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/msc_dual_lun/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/net_lwip_webserver/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 0 - 4
examples/device/uac2_headset/src/tusb_config.h

@@ -42,11 +42,7 @@ extern "C" {
 #error CFG_TUSB_MCU must be defined
 #endif
 
-#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
-#define CFG_TUSB_RHPORT0_MODE       (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
-#else
 #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_DEVICE
-#endif
 
 #ifndef CFG_TUSB_OS
 #define CFG_TUSB_OS                 OPT_OS_NONE

+ 1 - 1
examples/device/uac2_headset/src/usb_descriptors.h

@@ -86,7 +86,7 @@ enum
 
 #define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \
     /* Standard Interface Association Descriptor (IAD) */\
-    TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\
+    TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\
     /* Standard AC Interface Descriptor(4.7.1) */\
     TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
     /* Class-Specific AC Interface Header Descriptor(4.7.2) */\

+ 2 - 7
examples/device/usbtmc/src/tusb_config.h

@@ -27,14 +27,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/video_capture/src/tusb_config.h

@@ -40,14 +40,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 2 - 7
examples/device/webusb_serial/src/tusb_config.h

@@ -45,14 +45,9 @@
 #endif
 
 // RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+// Default to max (auto) speed for MCU with internal HighSpeed PHY
 #ifndef BOARD_DEVICE_RHPORT_SPEED
-  #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
-       CFG_TUSB_MCU == OPT_MCU_NUC505  || CFG_TUSB_MCU == OPT_MCU_CXD56)
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
-  #else
-    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
-  #endif
+  #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_DEFAULT_SPEED
 #endif
 
 // Device mode with rhport and speed defined by board.mk

+ 27 - 0
examples/host/bare_api/CMakeLists.txt

@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT})
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+        )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}/src
+        )
+
+# Configure compilation flags and libraries for the example... see the corresponding function
+# in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT})

+ 27 - 0
examples/host/bare_api/Makefile

@@ -0,0 +1,27 @@
+include ../../../tools/top.mk
+include ../../make.mk
+
+INC += \
+	src \
+	$(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += \
+	src/main.c
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+# TODO: suppress warning caused by host stack
+CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
+
+# TinyUSB Host Stack source
+SRC_C += \
+	src/class/cdc/cdc_host.c \
+	src/class/hid/hid_host.c \
+	src/class/msc/msc_host.c \
+	src/host/hub.c \
+	src/host/usbh.c \
+	src/portable/ohci/ohci.c \
+	src/portable/nxp/lpc17_40/hcd_lpc17_40.c
+
+include ../../rules.mk

+ 9 - 0
examples/host/bare_api/only.txt

@@ -0,0 +1,9 @@
+mcu:LPC175X_6X
+mcu:LPC177X_8X
+mcu:LPC18XX
+mcu:LPC40XX
+mcu:LPC43XX
+mcu:MIMXRT10XX
+mcu:RP2040
+mcu:MSP432E4
+mcu:RX65X

+ 221 - 0
examples/host/bare_api/src/main.c

@@ -0,0 +1,221 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+/* This example current worked and tested with following controller
+ * - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+void led_blinking_task(void);
+
+/*------------- MAIN -------------*/
+int main(void)
+{
+  board_init();
+
+  printf("TinyUSB Host HID Controller Example\r\n");
+  tusb_init();
+
+  while (1)
+  {
+    // tinyusb host task
+    tuh_task();
+    led_blinking_task();
+  }
+
+  return 0;
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+// English
+#define LANGUAGE_ID 0x0409
+
+//uint8_t usb_buf[256] TU_ATTR_ALIGNED(4);
+tusb_desc_device_t desc_device;
+
+static volatile xfer_result_t _get_string_result;
+
+static bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) {
+    (void)daddr;
+    (void)request;
+    _get_string_result = result;
+    return true;
+}
+
+static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
+    // TODO: Check for runover.
+    (void)utf8_len;
+    // Get the UTF-16 length out of the data itself.
+
+    for (size_t i = 0; i < utf16_len; i++) {
+        uint16_t chr = utf16[i];
+        if (chr < 0x80) {
+            *utf8++ = chr & 0xff;
+        } else if (chr < 0x800) {
+            *utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F));
+            *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
+        } else {
+            // TODO: Verify surrogate.
+            *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
+            *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
+            *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
+        }
+        // TODO: Handle UTF-16 code points that take two entries.
+    }
+}
+
+// Count how many bytes a utf-16-le encoded string will take in utf-8.
+static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
+    size_t total_bytes = 0;
+    for (size_t i = 0; i < len; i++) {
+        uint16_t chr = buf[i];
+        if (chr < 0x80) {
+            total_bytes += 1;
+        } else if (chr < 0x800) {
+            total_bytes += 2;
+        } else {
+            total_bytes += 3;
+        }
+        // TODO: Handle UTF-16 code points that take two entries.
+    }
+    return total_bytes;
+}
+
+static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) {
+    while (_get_string_result == 0xff) {
+        tuh_task();
+    }
+    if (_get_string_result != XFER_RESULT_SUCCESS) {
+        temp_buf[0] = 0;
+        return;
+    }
+    size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
+    size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len);
+    _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
+    ((uint8_t*) temp_buf)[utf8_len] = '\0';
+}
+
+bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result)
+{
+  (void) request;
+
+  if ( XFER_RESULT_SUCCESS != result )
+  {
+    printf("Failed to get device descriptor\r\n");
+    return false;
+  }
+
+  printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct);
+  printf("Device Descriptor:\r\n");
+  printf("  bLength             %u\r\n"     , desc_device.bLength);
+  printf("  bDescriptorType     %u\r\n"     , desc_device.bDescriptorType);
+  printf("  bcdUSB              %04x\r\n"   , desc_device.bcdUSB);
+  printf("  bDeviceClass        %u\r\n"     , desc_device.bDeviceClass);
+  printf("  bDeviceSubClass     %u\r\n"     , desc_device.bDeviceSubClass);
+  printf("  bDeviceProtocol     %u\r\n"     , desc_device.bDeviceProtocol);
+  printf("  bMaxPacketSize0     %u\r\n"     , desc_device.bMaxPacketSize0);
+  printf("  idVendor            0x%04x\r\n" , desc_device.idVendor);
+  printf("  idProduct           0x%04x\r\n" , desc_device.idProduct);
+  printf("  bcdDevice           %04x\r\n"   , desc_device.bcdDevice);
+
+  _get_string_result = 0xff;
+  uint16_t temp_buf[128];
+
+  printf("  iManufacturer       %u     "     , desc_device.iManufacturer);
+  temp_buf[0] = 0;
+  if (tuh_descriptor_get_manufacturer_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
+    _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf));
+    printf((const char*) temp_buf);
+  }
+  printf("\r\n");
+
+  printf("  iProduct            %u     "     , desc_device.iProduct);
+  _get_string_result = 0xff;
+  temp_buf[0] = 0;
+  if (tuh_descriptor_get_product_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
+    _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf));
+    printf((const char*) temp_buf);
+  }
+  printf("\r\n");
+
+  printf("  iSerialNumber       %u     "     , desc_device.iSerialNumber);
+  _get_string_result = 0xff;
+  temp_buf[0] = 0;
+  if (tuh_descriptor_get_serial_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
+    _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf));
+    printf((const char*) temp_buf);
+  }
+  printf("\r\n");
+
+  printf("  bNumConfigurations  %u\r\n"     , desc_device.bNumConfigurations);
+
+  return true;
+}
+
+// Invoked when device is mounted (configured)
+void tuh_mount_cb (uint8_t daddr)
+{
+  printf("Device attached, address = %d\r\n", daddr);
+
+  // Get Device Descriptor
+  tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor);
+}
+
+/// Invoked when device is unmounted (bus reset/unplugged)
+void tuh_umount_cb(uint8_t daddr)
+{
+  printf("Device removed, address = %d\r\n", daddr);
+}
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+void led_blinking_task(void)
+{
+  const uint32_t interval_ms = 1000;
+  static uint32_t start_ms = 0;
+
+  static bool led_state = false;
+
+  // Blink every interval ms
+  if ( board_millis() - start_ms < interval_ms) return; // not enough time
+  start_ms += interval_ms;
+
+  board_led_write(led_state);
+  led_state = 1 - led_state; // toggle
+}

+ 94 - 0
examples/host/bare_api/src/tusb_config.h

@@ -0,0 +1,94 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+  #error CFG_TUSB_MCU must be defined
+#endif
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
+  #define CFG_TUSB_RHPORT0_MODE       (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED)
+#else
+  #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_HOST
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS                 OPT_OS_NONE
+#endif
+
+// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
+// #define CFG_TUSB_DEBUG           0
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN   : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
+#endif
+
+#ifndef CFG_TUSB_MEM_ALIGN
+#define CFG_TUSB_MEM_ALIGN          __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// CONFIGURATION
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+// only hub class is enabled
+#define CFG_TUH_HUB                 1
+
+// max device support (excluding hub device)
+// 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX          (CFG_TUH_HUB ? 4 : 1)
+
+#define CFG_TUH_ENDPOINT_MAX       8
+
+//------------- HID -------------//
+
+#define CFG_TUH_HID_EP_BUFSIZE      64
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */

+ 0 - 1
examples/host/cdc_msc_hid/Makefile

@@ -19,7 +19,6 @@ SRC_C += \
 	src/class/msc/msc_host.c \
 	src/host/hub.c \
 	src/host/usbh.c \
-	src/host/usbh_control.c \
 	src/portable/ohci/ohci.c \
 	src/portable/nxp/lpc17_40/hcd_lpc17_40.c
 

+ 0 - 1
examples/host/hid_controller/Makefile

@@ -22,7 +22,6 @@ SRC_C += \
 	src/class/msc/msc_host.c \
 	src/host/hub.c \
 	src/host/usbh.c \
-	src/host/usbh_control.c \
 	src/portable/ohci/ohci.c \
 	src/portable/nxp/lpc17_40/hcd_lpc17_40.c
 

+ 28 - 0
examples/host/hid_to_cdc/CMakeLists.txt

@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT})
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+        )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}/src
+        )
+
+# Configure compilation flags and libraries for the example... see the corresponding function
+# in hw/bsp/FAMILY/family.cmake for details.
+family_configure_device_example(${PROJECT})

+ 19 - 0
examples/host/hid_to_cdc/Makefile

@@ -0,0 +1,19 @@
+include ../../../tools/top.mk
+include ../../make.mk
+
+INC += \
+	src \
+	$(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += $(wildcard src/*.c)
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
+
+SRC_C += \
+	src/class/hid/hid_host.c \
+	src/host/hub.c \
+	src/host/usbh.c
+
+include ../../rules.mk

+ 2 - 0
examples/host/hid_to_cdc/only.txt

@@ -0,0 +1,2 @@
+board:mimxrt1060_evk
+board:mimxrt1064_evk

+ 315 - 0
examples/host/hid_to_cdc/src/main.c

@@ -0,0 +1,315 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+// This example runs both host and device concurrently. The USB host looks for
+// any HID device with reports that are 8 bytes long and then assumes they are
+// keyboard reports. It translates the keypresses of the reports to ASCII and
+// transmits it over CDC to the device's host.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+
+// uncomment if you are using colemak layout
+// #define KEYBOARD_COLEMAK
+
+#ifdef KEYBOARD_COLEMAK
+const uint8_t colemak[128] = {
+  0  ,  0,  0,  0,  0,  0,  0, 22,
+  9  , 23,  7,  0, 24, 17,  8, 12,
+  0  , 14, 28, 51,  0, 19, 21, 10,
+  15 ,  0,  0,  0, 13,  0,  0,  0,
+  0  ,  0,  0,  0,  0,  0,  0,  0,
+  0  ,  0,  0,  0,  0,  0,  0,  0,
+  0  ,  0,  0, 18,  0,  0,  0,  0,
+  0  ,  0,  0,  0,  0,  0,  0,  0,
+  0  ,  0,  0,  0,  0,  0,  0,  0,
+  0  ,  0,  0,  0,  0,  0,  0,  0
+};
+#endif
+
+static uint8_t const keycode2ascii[128][2] =  { HID_KEYCODE_TO_ASCII };
+
+/* Blink pattern
+ * - 250 ms  : device not mounted
+ * - 1000 ms : device mounted
+ * - 2500 ms : device is suspended
+ */
+enum  {
+  BLINK_NOT_MOUNTED = 250,
+  BLINK_MOUNTED = 1000,
+  BLINK_SUSPENDED = 2500,
+};
+
+static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+
+void led_blinking_task(void);
+void cdc_task(void);
+
+/*------------- MAIN -------------*/
+int main(void)
+{
+  board_init();
+  tusb_init();
+
+  while (1)
+  {
+    tud_task(); // tinyusb device task
+    tuh_task(); // tinyusb host task
+    led_blinking_task();
+
+    cdc_task();
+  }
+
+  return 0;
+}
+
+//--------------------------------------------------------------------+
+// Device callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device is mounted
+void tud_mount_cb(void)
+{
+  blink_interval_ms = BLINK_MOUNTED;
+}
+
+// Invoked when device is unmounted
+void tud_umount_cb(void)
+{
+  blink_interval_ms = BLINK_NOT_MOUNTED;
+}
+
+// Invoked when usb bus is suspended
+// remote_wakeup_en : if host allow us  to perform remote wakeup
+// Within 7ms, device must draw an average of current less than 2.5 mA from bus
+void tud_suspend_cb(bool remote_wakeup_en)
+{
+  (void) remote_wakeup_en;
+  blink_interval_ms = BLINK_SUSPENDED;
+}
+
+// Invoked when usb bus is resumed
+void tud_resume_cb(void)
+{
+  blink_interval_ms = BLINK_MOUNTED;
+}
+
+//--------------------------------------------------------------------+
+// Host callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device with hid interface is mounted
+// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
+// can be used to parse common/simple enough descriptor.
+// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
+// therefore report_desc = NULL, desc_len = 0
+void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
+{
+  (void)desc_report;
+  (void)desc_len;
+  uint16_t vid, pid;
+  tuh_vid_pid_get(dev_addr, &vid, &pid);
+
+  printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
+  printf("VID = %04x, PID = %04x\r\n", vid, pid);
+
+  // Receive any report and treat it like a keyboard.
+  // tuh_hid_report_received_cb() will be invoked when report is available
+  if ( !tuh_hid_receive_report(dev_addr, instance) )
+  {
+    printf("Error: cannot request to receive report\r\n");
+  }
+}
+
+// Invoked when device with hid interface is un-mounted
+void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
+{
+  printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
+}
+
+// keycodes from last report to check if key is holding or newly pressed
+uint8_t last_keycodes[6] = {0};
+
+// look up new key in previous keys
+static inline bool key_in_last_report(const uint8_t key_arr[6], uint8_t keycode)
+{
+  for(uint8_t i=0; i<6; i++)
+  {
+    if (key_arr[i] == keycode) return true;
+  }
+
+  return false;
+}
+
+// Invoked when received report from device via interrupt endpoint
+void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
+{
+  if (len != 8)
+  {
+    char ch_num;
+
+    tud_cdc_write_str("incorrect report len: ");
+
+    if ( len > 10 )
+    {
+      ch_num = '0' + (len / 10);
+      tud_cdc_write(&ch_num, 1);
+      len = len % 10;
+    }
+
+    ch_num = '0' + len;
+    tud_cdc_write(&ch_num, 1);
+
+    tud_cdc_write_str("\r\n");
+    tud_cdc_write_flush();
+
+    // Don't request a new report for a wrong sized endpoint.
+    return;
+  }
+
+  uint8_t const modifiers = report[0];
+  bool flush = false;
+
+  for (int i = 2; i < 8; i++)
+  {
+    uint8_t keycode = report[i];
+
+    if (keycode)
+    {
+      if ( key_in_last_report(last_keycodes, keycode) )
+      {
+        // exist in previous report means the current key is holding
+        // do nothing
+      }else
+      {
+        // not existed in previous report means the current key is pressed
+        // Only print keycodes 0 - 128.
+        if (keycode < 128)
+        {
+          // remap the key code for Colemak layout so @tannewt can type.
+          #ifdef KEYBOARD_COLEMAK
+          uint8_t colemak_key_code = colemak[keycode];
+          if (colemak_key_code != 0) keycode = colemak_key_code;
+          #endif
+
+          bool const is_shift = modifiers & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
+          char c = keycode2ascii[keycode][is_shift ? 1 : 0];
+          if (c)
+          {
+            if (c == '\n') tud_cdc_write("\r", 1);
+            tud_cdc_write(&c, 1);
+            flush = true;
+          }
+        }
+      }
+    }
+  }
+
+  if (flush) tud_cdc_write_flush();
+
+  // save current report
+  memcpy(last_keycodes, report+2, 6);
+
+  // continue to request to receive report
+  if ( !tuh_hid_receive_report(dev_addr, instance) )
+  {
+    printf("Error: cannot request to receive report\r\n");
+  }
+}
+
+
+
+//--------------------------------------------------------------------+
+// USB CDC
+//--------------------------------------------------------------------+
+void cdc_task(void)
+{
+  // connected() check for DTR bit
+  // Most but not all terminal client set this when making connection
+  // if ( tud_cdc_connected() )
+  {
+    // connected and there are data available
+    if ( tud_cdc_available() )
+    {
+      // read datas
+      char buf[64];
+      uint32_t count = tud_cdc_read(buf, sizeof(buf));
+      (void) count;
+
+      // Echo back
+      // Note: Skip echo by commenting out write() and write_flush()
+      // for throughput test e.g
+      //    $ dd if=/dev/zero of=/dev/ttyACM0 count=10000
+      tud_cdc_write(buf, count);
+      tud_cdc_write_flush();
+    }
+  }
+}
+
+// Invoked when cdc when line state changed e.g connected/disconnected
+void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
+{
+  (void) itf;
+  (void) rts;
+
+  // TODO set some indicator
+  if ( dtr )
+  {
+    // Terminal connected
+  }else
+  {
+    // Terminal disconnected
+  }
+}
+
+// Invoked when CDC interface received data from host
+void tud_cdc_rx_cb(uint8_t itf)
+{
+  (void) itf;
+}
+
+//--------------------------------------------------------------------+
+// BLINKING TASK
+//--------------------------------------------------------------------+
+void led_blinking_task(void)
+{
+  static uint32_t start_ms = 0;
+  static bool led_state = false;
+
+  // Blink every interval ms
+  if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
+  start_ms += blink_interval_ms;
+
+  board_led_write(led_state);
+  led_state = 1 - led_state; // toggle
+}

+ 163 - 0
examples/host/hid_to_cdc/src/tusb_config.h

@@ -0,0 +1,163 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by board.mk
+#ifndef CFG_TUSB_MCU
+  #error CFG_TUSB_MCU must be defined
+#endif
+
+// RHPort number used for device can be defined by board.mk, default to port 0
+#ifndef BOARD_DEVICE_RHPORT_NUM
+  #define BOARD_DEVICE_RHPORT_NUM     0
+#endif
+
+// RHPort number used for device can be defined by board.mk, default to port 1
+#ifndef BOARD_HOST_RHPORT_NUM
+  #define BOARD_HOST_RHPORT_NUM     1
+#endif
+
+// RHPort max operational speed can defined by board.mk
+// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+#ifndef BOARD_DEVICE_RHPORT_SPEED
+  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
+      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
+      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
+    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
+  #else
+    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
+  #endif
+#endif
+
+// RHPort max operational speed can defined by board.mk
+// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
+#ifndef BOARD_HOST_RHPORT_SPEED
+  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
+      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
+      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
+    #define BOARD_HOST_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
+  #else
+    #define BOARD_HOST_RHPORT_SPEED   OPT_MODE_FULL_SPEED
+  #endif
+#endif
+
+// Device mode with rhport and speed defined by board.mk
+#if   BOARD_DEVICE_RHPORT_NUM == 0
+  #define CFG_TUSB_RHPORT0_MODE     (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
+#elif BOARD_DEVICE_RHPORT_NUM == 1
+  #define CFG_TUSB_RHPORT1_MODE     (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
+#else
+  #error "Incorrect RHPort configuration"
+#endif
+
+// Device mode with rhport and speed defined by board.mk
+#if   BOARD_HOST_RHPORT_NUM == 0
+  #define CFG_TUSB_RHPORT0_MODE     (OPT_MODE_HOST | BOARD_HOST_RHPORT_SPEED)
+#elif BOARD_HOST_RHPORT_NUM == 1
+  #define CFG_TUSB_RHPORT1_MODE     (OPT_MODE_HOST | BOARD_HOST_RHPORT_SPEED)
+#else
+  #error "Incorrect RHPort configuration"
+#endif
+
+// This example doesn't use an RTOS
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS               OPT_OS_NONE
+#endif
+
+// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
+// #define CFG_TUSB_DEBUG           0
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN   : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
+#endif
+
+#ifndef CFG_TUSB_MEM_ALIGN
+#define CFG_TUSB_MEM_ALIGN          __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#ifndef CFG_TUD_ENDPOINT0_SIZE
+#define CFG_TUD_ENDPOINT0_SIZE    64
+#endif
+
+//------------- CLASS -------------//
+#define CFG_TUD_CDC              1
+#define CFG_TUD_MSC              0
+#define CFG_TUD_HID              0
+#define CFG_TUD_MIDI             0
+#define CFG_TUD_VENDOR           0
+
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+// CDC Endpoint transfer buffer size, more is faster
+#define CFG_TUD_CDC_EP_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+//--------------------------------------------------------------------
+// HOST CONFIGURATION
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#define CFG_TUH_HUB                 1
+#define CFG_TUH_CDC                 0
+#define CFG_TUH_MSC                 0
+#define CFG_TUH_VENDOR              0
+
+// max device support (excluding hub device)
+#define CFG_TUH_DEVICE_MAX          (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
+
+//------------- HID -------------//
+#define CFG_TUH_HID                  4
+#define CFG_TUH_HID_EPIN_BUFSIZE    64
+#define CFG_TUH_HID_EPOUT_BUFSIZE   64
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */

+ 266 - 0
examples/host/hid_to_cdc/src/usb_descriptors.c

@@ -0,0 +1,266 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ *   [MSB]         HID | MSC | CDC          [LSB]
+ */
+#define _PID_MAP(itf, n)  ( (CFG_TUD_##itf) << (n) )
+#define USB_PID           (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
+                           _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
+
+#define USB_VID   0xCafe
+#define USB_BCD   0x0200
+
+//--------------------------------------------------------------------+
+// Device Descriptors
+//--------------------------------------------------------------------+
+tusb_desc_device_t const desc_device =
+{
+  .bLength            = sizeof(tusb_desc_device_t),
+  .bDescriptorType    = TUSB_DESC_DEVICE,
+  .bcdUSB             = USB_BCD,
+
+  // Use Interface Association Descriptor (IAD) for CDC
+  // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+  .bDeviceClass       = TUSB_CLASS_MISC,
+  .bDeviceSubClass    = MISC_SUBCLASS_COMMON,
+  .bDeviceProtocol    = MISC_PROTOCOL_IAD,
+
+  .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
+
+  .idVendor           = USB_VID,
+  .idProduct          = USB_PID,
+  .bcdDevice          = 0x0100,
+
+  .iManufacturer      = 0x01,
+  .iProduct           = 0x02,
+  .iSerialNumber      = 0x03,
+
+  .bNumConfigurations = 0x01
+};
+
+// Invoked when received GET DEVICE DESCRIPTOR
+// Application return pointer to descriptor
+uint8_t const * tud_descriptor_device_cb(void)
+{
+  return (uint8_t const *) &desc_device;
+}
+
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+
+enum
+{
+  ITF_NUM_CDC = 0,
+  ITF_NUM_CDC_DATA,
+  ITF_NUM_MSC,
+  ITF_NUM_TOTAL
+};
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+  // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+  // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
+  #define EPNUM_CDC_NOTIF   0x81
+  #define EPNUM_CDC_OUT     0x02
+  #define EPNUM_CDC_IN      0x82
+
+#elif CFG_TUSB_MCU == OPT_MCU_SAMG  || CFG_TUSB_MCU ==  OPT_MCU_SAMX7X
+  // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
+  //    e.g EP1 OUT & EP1 IN cannot exist together
+  #define EPNUM_CDC_NOTIF   0x81
+  #define EPNUM_CDC_OUT     0x02
+  #define EPNUM_CDC_IN      0x83
+
+#elif CFG_TUSB_MCU == OPT_MCU_CXD56
+  // CXD56 doesn't support a same endpoint number with different direction IN and OUT
+  //    e.g EP1 OUT & EP1 IN cannot exist together
+  // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
+  // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
+  #define EPNUM_CDC_NOTIF   0x83
+  #define EPNUM_CDC_OUT     0x02
+  #define EPNUM_CDC_IN      0x81
+
+#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
+  // FT9XX doesn't support a same endpoint number with different direction IN and OUT
+  //    e.g EP1 OUT & EP1 IN cannot exist together
+  #define EPNUM_CDC_NOTIF   0x81
+  #define EPNUM_CDC_OUT     0x02
+  #define EPNUM_CDC_IN      0x83
+
+#else
+  #define EPNUM_CDC_NOTIF   0x81
+  #define EPNUM_CDC_OUT     0x02
+  #define EPNUM_CDC_IN      0x82
+
+#endif
+
+#define CONFIG_TOTAL_LEN    (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
+
+// full speed configuration
+uint8_t const desc_fs_configuration[] =
+{
+  // Config number, interface count, string index, total length, attribute, power in mA
+  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+  // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+  TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
+};
+
+#if TUD_OPT_HIGH_SPEED
+// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
+
+// high speed configuration
+uint8_t const desc_hs_configuration[] =
+{
+  // Config number, interface count, string index, total length, attribute, power in mA
+  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+  // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+  TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
+};
+
+// other speed configuration
+uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
+
+// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
+tusb_desc_device_qualifier_t const desc_device_qualifier =
+{
+  .bLength            = sizeof(tusb_desc_device_qualifier_t),
+  .bDescriptorType    = TUSB_DESC_DEVICE_QUALIFIER,
+  .bcdUSB             = USB_BCD,
+
+  .bDeviceClass       = TUSB_CLASS_MISC,
+  .bDeviceSubClass    = MISC_SUBCLASS_COMMON,
+  .bDeviceProtocol    = MISC_PROTOCOL_IAD,
+
+  .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
+  .bNumConfigurations = 0x01,
+  .bReserved          = 0x00
+};
+
+// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
+// device_qualifier descriptor describes information about a high-speed capable device that would
+// change if the device were operating at the other speed. If not highspeed capable stall this request.
+uint8_t const* tud_descriptor_device_qualifier_cb(void)
+{
+  return (uint8_t const*) &desc_device_qualifier;
+}
+
+// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
+uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
+{
+  (void) index; // for multiple configurations
+
+  // if link speed is high return fullspeed config, and vice versa
+  // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
+  memcpy(desc_other_speed_config,
+         (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
+         CONFIG_TOTAL_LEN);
+
+  desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
+
+  return desc_other_speed_config;
+}
+
+#endif // highspeed
+
+
+// Invoked when received GET CONFIGURATION DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
+{
+  (void) index; // for multiple configurations
+
+#if TUD_OPT_HIGH_SPEED
+  // Although we are highspeed, host may be fullspeed.
+  return (tud_speed_get() == TUSB_SPEED_HIGH) ?  desc_hs_configuration : desc_fs_configuration;
+#else
+  return desc_fs_configuration;
+#endif
+}
+
+//--------------------------------------------------------------------+
+// String Descriptors
+//--------------------------------------------------------------------+
+
+// array of pointer to string descriptors
+char const* string_desc_arr [] =
+{
+  (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
+  "TinyUSB",                     // 1: Manufacturer
+  "TinyUSB Device",              // 2: Product
+  "123456789012",                // 3: Serials, should use chip ID
+  "TinyUSB CDC",                 // 4: CDC Interface
+};
+
+static uint16_t _desc_str[32];
+
+// Invoked when received GET STRING DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
+{
+  (void) langid;
+
+  uint8_t chr_count;
+
+  if ( index == 0)
+  {
+    memcpy(&_desc_str[1], string_desc_arr[0], 2);
+    chr_count = 1;
+  }else
+  {
+    // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
+    // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
+
+    if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+
+    const char* str = string_desc_arr[index];
+
+    // Cap at max char
+    chr_count = (uint8_t) strlen(str);
+    if ( chr_count > 31 ) chr_count = 31;
+
+    // Convert ASCII string into UTF-16
+    for(uint8_t i=0; i<chr_count; i++)
+    {
+      _desc_str[1+i] = str[i];
+    }
+  }
+
+  // first byte is length (including header), second byte is string type
+  _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
+
+  return _desc_str;
+}

+ 1 - 1
hw/bsp/board.h

@@ -120,7 +120,7 @@ static inline void board_delay(uint32_t ms)
   uint32_t start_ms = board_millis();
   while (board_millis() - start_ms < ms)
   {
-    #if TUSB_OPT_DEVICE_ENABLED
+    #if CFG_TUD_ENABLED
     // take chance to run usb background
     tud_task();
     #endif

+ 3 - 3
hw/bsp/brtmm90x/family.c

@@ -30,7 +30,7 @@
 #include <registers/ft900_registers.h>
 #include <ft900.h>
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 int8_t board_ft90x_vbus(void); // Board specific implementation of VBUS detection for USB device.
 extern void ft90x_usbd_pm_ISR(uint16_t pmcfg); // Interrupt handler for USB device power management
 #endif
@@ -152,14 +152,14 @@ void board_pm_ISR(void)
               MASK_SYS_PMCFG_HOST_RESUME_DEV)
     )
     {
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
         ft90x_usbd_pm_ISR(pmcfg);
 #endif
     }
 #endif
 }
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 int8_t board_ft90x_vbus(void)
 {
 	return gpio_read(USBD_VBUS_DTC_PIN);

+ 1 - 1
hw/bsp/d5035_01/d5035_01.c

@@ -270,7 +270,7 @@ void board_init(void)
 #endif
 
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 #if CFG_TUSB_DEBUG >= 2
 	uart_send_str(BOARD_NAME " USB device enabled\n");
 #endif

+ 1 - 1
hw/bsp/da14695_dk_usb/da14695_dk_usb.c

@@ -73,7 +73,7 @@ void board_init(void)
   // 1ms tick timer
   SysTick_Config(SystemCoreClock / 1000);
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   // This board is USB powered there is no need to monitor
   // VBUS line.  Notify driver that VBUS is present.
   tusb_vbus_changed(true);

+ 2 - 2
hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c

@@ -36,7 +36,7 @@ void USB_IRQHandler(void)
   tud_int_handler(0);
 }
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 // DA146xx driver function that must be called whenever VBUS changes
 extern void tusb_vbus_changed(bool present);
 
@@ -85,7 +85,7 @@ void board_init(void)
   // 1ms tick timer
   SysTick_Config(SystemCoreClock / 1000);
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   // Setup interrupt for both connect and disconnect
   CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk |
                                CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk;

+ 2 - 2
hw/bsp/frdm_kl25z/frdm_kl25z.c

@@ -39,10 +39,10 @@
 //--------------------------------------------------------------------+
 void USB0_IRQHandler(void)
 {
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   tuh_int_handler(0);
 #endif
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   tud_int_handler(0);
 #endif
 }

+ 3 - 0
hw/bsp/imxrt/boards/mimxrt1060_evk/board.mk

@@ -7,5 +7,8 @@ JLINK_DEVICE = MIMXRT1062xxx6A
 # For flash-pyocd target
 PYOCD_TARGET = mimxrt1060
 
+BOARD_DEVICE_RHPORT_NUM = 1
+BOARD_HOST_RHPORT_NUM = 0
+
 # flash using pyocd
 flash: flash-pyocd

+ 3 - 0
hw/bsp/imxrt/boards/mimxrt1064_evk/board.mk

@@ -7,5 +7,8 @@ JLINK_DEVICE = MIMXRT1064xxx6A
 # For flash-pyocd target
 PYOCD_TARGET = mimxrt1064
 
+BOARD_DEVICE_RHPORT_NUM = 1
+BOARD_HOST_RHPORT_NUM = 0
+
 # flash using pyocd
 flash: flash-pyocd

+ 22 - 5
hw/bsp/imxrt/family.c

@@ -98,13 +98,9 @@ void board_init(void)
   CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
   CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
 
-  // USB1
-//  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
-//  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
-
   USBPHY_Type* usb_phy;
 
-  // RT105x RT106x have dual USB controller. TODO support USB2
+  // RT105x RT106x have dual USB controller.
 #ifdef USBPHY1
   usb_phy = USBPHY1;
 #else
@@ -122,6 +118,27 @@ void board_init(void)
   phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
   phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
   usb_phy->TX = phytx;
+
+  // RT105x RT106x have dual USB controller.
+#ifdef USBPHY2
+  // USB1
+  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
+  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
+
+  usb_phy = USBPHY2;
+
+  // Enable PHY support for Low speed device + LS via FS Hub
+  usb_phy->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK;
+
+  // Enable all power for normal operation
+  usb_phy->PWD = 0;
+
+  // TX Timing
+  phytx = usb_phy->TX;
+  phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
+  phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
+  usb_phy->TX = phytx;
+#endif
 }
 
 //--------------------------------------------------------------------+

+ 7 - 0
hw/bsp/imxrt/family.mk

@@ -15,6 +15,13 @@ CFLAGS += \
   -DXIP_BOOT_HEADER_ENABLE=1 \
   -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX
 
+ifdef BOARD_DEVICE_RHPORT_NUM
+CFLAGS += -DBOARD_DEVICE_RHPORT_NUM=$(BOARD_DEVICE_RHPORT_NUM)
+endif
+ifdef BOARD_HOST_RHPORT_NUM
+CFLAGS += -DBOARD_HOST_RHPORT_NUM=$(BOARD_HOST_RHPORT_NUM)
+endif
+
 # mcu driver cause following warnings
 CFLAGS += -Wno-error=unused-parameter -Wno-error=implicit-fallthrough=
 

+ 2 - 2
hw/bsp/lpcxpresso1769/lpcxpresso1769.c

@@ -156,12 +156,12 @@ void board_init(void)
 //    0x1B // Host + Device + OTG + AHB
   };
 
-  uint32_t const clk_en = TUSB_OPT_DEVICE_ENABLED ? USBCLK_DEVCIE : USBCLK_HOST;
+  uint32_t const clk_en = CFG_TUD_ENABLED ? USBCLK_DEVCIE : USBCLK_HOST;
 
   LPC_USB->OTGClkCtrl = clk_en;
   while ( (LPC_USB->OTGClkSt & clk_en) != clk_en );
 
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   // set portfunc to host !!!
   LPC_USB->StCtrl = 0x3; // should be 1
 #endif

+ 2 - 2
hw/bsp/mbed1768/mbed1768.c

@@ -130,12 +130,12 @@ void board_init(void)
 //    0x1B // Host + Device + OTG + AHB
   };
 
-  uint32_t const clk_en = TUSB_OPT_DEVICE_ENABLED ? USBCLK_DEVCIE : USBCLK_HOST;
+  uint32_t const clk_en = CFG_TUD_ENABLED ? USBCLK_DEVCIE : USBCLK_HOST;
 
   LPC_USB->OTGClkCtrl = clk_en;
   while ( (LPC_USB->OTGClkSt & clk_en) != clk_en );
 
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   // set portfunc to host !!!
   LPC_USB->StCtrl = 0x3; // should be 1
 #endif

+ 5 - 5
hw/bsp/msp432e4/family.c

@@ -33,10 +33,10 @@
 //--------------------------------------------------------------------+
 void USB0_IRQHandler(void)
 {
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   tuh_int_handler(0);
 #endif
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   tud_int_handler(0);
 #endif
 }
@@ -123,7 +123,7 @@ void board_init(void)
   GPIOB->AMSEL      = TU_BIT(0) | TU_BIT(1);
   GPIOL->AMSEL      = TU_BIT(6) | TU_BIT(7);
 
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   /* USB PD6(EPEN) */
   bits              = TU_BIT(3);
   SYSCTL->RCGCGPIO |= bits;
@@ -144,11 +144,11 @@ void board_init(void)
 
   USB0->CC          = USB_CC_CLKEN | (3u << USB_CC_CLKDIV_S); /* 60MHz = 240MHz / 4 */
   __DMB(); /* Wait for completion of opening of the clock gate */
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   USB0->GPCS = USB_GPCS_DEVMOD_OTG;
   USB0->EPC  = USB_EPC_EPENDE | USB_EPC_EPEN_HIGH;
 #endif
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   USB0->GPCS = USB_GPCS_DEVMOD_DEVVBUS;
 #endif
 }

+ 1 - 1
hw/bsp/nrf/family.c

@@ -100,7 +100,7 @@ void board_init(void)
   nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler);
 
   //------------- USB -------------//
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice
   // 2 is highest for application
   NVIC_SetPriority(USBD_IRQn, 2);

+ 2 - 2
hw/bsp/rp2040/family.c

@@ -138,11 +138,11 @@ void board_init(void)
 #endif
 
   // todo probably set up device mode?
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 
 #endif
 
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   // set portfunc to host !!!
 #endif
 }

+ 0 - 1
hw/bsp/rp2040/family.cmake

@@ -83,7 +83,6 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 			${TOP}/src/portable/raspberrypi/rp2040/hcd_rp2040.c
 			${TOP}/src/portable/raspberrypi/rp2040/rp2040_usb.c
 			${TOP}/src/host/usbh.c
-			${TOP}/src/host/usbh_control.c
 			${TOP}/src/host/hub.c
 			${TOP}/src/class/cdc/cdc_host.c
 			${TOP}/src/class/hid/hid_host.c

+ 2 - 2
hw/bsp/rx/boards/rx65n_target/rx65n_target.c

@@ -176,10 +176,10 @@ void INT_Excep_SCI5_RXI5(void)
 //--------------------------------------------------------------------+
 void INT_Excep_USB0_USBI0(void)
 {
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   tuh_int_handler(0);
 #endif
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   tud_int_handler(0);
 #endif
 }

+ 1 - 1
hw/bsp/same54xplainedpro/same54xplainedpro.c

@@ -223,7 +223,7 @@ void board_init(void)
 #endif
 
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 #if CFG_TUSB_DEBUG >= 2
 	uart_send_str(BOARD_NAME " USB device enabled\n");
 #endif

+ 122 - 0
hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h

@@ -0,0 +1,122 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022, Jerzy Kasenberg
+ *
+ * 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 BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// LED
+#define LED_PORT              GPIOB
+#define LED_PIN               GPIO_PIN_5
+#define LED_STATE_ON          1
+
+// Button
+#define BUTTON_PORT           GPIOC
+#define BUTTON_PIN            GPIO_PIN_4
+#define BUTTON_STATE_ACTIVE   0
+
+// UART Enable for STLink VCOM
+#define UART_DEV              USART1
+#define UART_CLK_EN           __HAL_RCC_USART1_CLK_ENABLE
+#define UART_GPIO_PORT        GPIOB
+#define UART_GPIO_AF          GPIO_AF7_USART1
+#define UART_TX_PIN           GPIO_PIN_6
+#define UART_RX_PIN           GPIO_PIN_7
+
+
+//--------------------------------------------------------------------+
+// RCC Clock
+//--------------------------------------------------------------------+
+static inline void board_clock_init(void)
+{
+  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+
+  // Initializes the CPU, AHB and APB busses clocks
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSE;
+  RCC_OscInitStruct.HSEState       = RCC_HSE_ON;
+  RCC_OscInitStruct.HSI48State     = RCC_HSI48_ON;
+  RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_HSE;
+  RCC_OscInitStruct.PLL.PLLM       = RCC_PLLM_DIV4;
+  RCC_OscInitStruct.PLL.PLLN       = 24;
+  RCC_OscInitStruct.PLL.PLLP       = RCC_PLLP_DIV4;
+  RCC_OscInitStruct.PLL.PLLQ       = RCC_PLLQ_DIV4;
+  RCC_OscInitStruct.PLL.PLLR       = RCC_PLLR_DIV3;
+  HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+  // Initializes the CPU, AHB and APB busses clocks
+  RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
+  RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
+  RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;
+  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
+
+  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
+  PeriphClkInit.UsbClockSelection    = RCC_USBCLKSOURCE_HSI48;
+  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) ;
+
+#if 0 // TODO need to check if USB clock is enabled
+  /* Enable HSI48 */
+  memset(&RCC_OscInitStruct, 0, sizeof(RCC_OscInitStruct));
+
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
+  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
+  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
+  HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+  /*Enable CRS Clock*/
+  RCC_CRSInitTypeDef RCC_CRSInitStruct= {0};
+  __HAL_RCC_CRS_CLK_ENABLE();
+
+  /* Default Synchro Signal division factor (not divided) */
+  RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
+
+  /* Set the SYNCSRC[1:0] bits according to CRS_Source value */
+  RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
+
+  /* HSI48 is synchronized with USB SOF at 1KHz rate */
+  RCC_CRSInitStruct.ReloadValue =  __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000);
+  RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT;
+
+  /* Set the TRIM[5:0] to the default value */
+  RCC_CRSInitStruct.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT;
+
+  /* Start automatic synchronization */
+  HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);
+#endif
+}
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */

+ 9 - 0
hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk

@@ -0,0 +1,9 @@
+CFLAGS += \
+	-DSTM32WB55xx
+
+LD_FILE = $(BOARD_PATH)/stm32wb55xx_flash_cm4.ld
+
+SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32wb55xx_cm4.s
+
+# For flash-jlink target
+JLINK_DEVICE = STM32WB55RG

+ 171 - 0
hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld

@@ -0,0 +1,171 @@
+/**
+*****************************************************************************
+**
+**  File        : stm32wb55xx_flash_cm4.ld
+**
+**  Abstract    : System Workbench Minimal System calls file
+**
+** 		          For more information about which c-functions
+**                need which of these lowlevel functions
+**                please consult the Newlib libc-manual
+**
+**  Environment : System Workbench for MCU
+**
+**  Distribution: The file is distributed “as is,” without any warranty
+**                of any kind.
+**
+*****************************************************************************
+** @attention
+**
+** Copyright (c) 2019 STMicroelectronics.
+** All rights reserved.
+**
+** This software is licensed under terms that can be found in the LICENSE file
+** in the root directory of this software component.
+** If no LICENSE file comes with this software, it is provided AS-IS.
+**
+*****************************************************************************
+*/
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+/* Highest address of the user mode stack */
+_estack = 0x20030000;    /* end of RAM */
+/* Generate a link error if heap and stack don't fit into RAM */
+_Min_Heap_Size = 0x400;      /* required amount of heap  */
+_Min_Stack_Size = 0x1000;   /* required amount of stack */
+
+/* Specify the memory areas */
+MEMORY
+{
+FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 512K
+RAM1 (xrw)                 : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
+RAM_SHARED (xrw)           : ORIGIN = 0x20030000, LENGTH = 10K
+}
+
+/* Define output sections */
+SECTIONS
+{
+  /* The startup code goes first into FLASH */
+  .isr_vector :
+  {
+    . = ALIGN(4);
+    KEEP(*(.isr_vector)) /* Startup code */
+    . = ALIGN(4);
+  } >FLASH
+
+  /* The program code and other data goes into FLASH */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)           /* .text sections (code) */
+    *(.text*)          /* .text* sections (code) */
+    *(.glue_7)         /* glue arm to thumb code */
+    *(.glue_7t)        /* glue thumb to arm code */
+    *(.eh_frame)
+
+    KEEP (*(.init))
+    KEEP (*(.fini))
+
+    . = ALIGN(4);
+    _etext = .;        /* define a global symbols at end of code */
+  } >FLASH
+
+  /* Constant data goes into FLASH */
+  .rodata :
+  {
+    . = ALIGN(4);
+    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
+    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
+    . = ALIGN(4);
+  } >FLASH
+
+  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+  .ARM : {
+    __exidx_start = .;
+    *(.ARM.exidx*)
+    __exidx_end = .;
+  } >FLASH
+
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array*))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  } >FLASH
+  .init_array :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT(.init_array.*)))
+    KEEP (*(.init_array*))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  } >FLASH
+  .fini_array :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT(.fini_array.*)))
+    KEEP (*(.fini_array*))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  } >FLASH
+
+  /* used by the startup to initialize data */
+  _sidata = LOADADDR(.data);
+
+  /* Initialized data sections goes into RAM, load LMA copy after code */
+  .data : 
+  {
+    . = ALIGN(4);
+    _sdata = .;        /* create a global symbol at data start */
+    *(.data)           /* .data sections */
+    *(.data*)          /* .data* sections */
+
+    . = ALIGN(4);
+    _edata = .;        /* define a global symbol at data end */
+  } >RAM1 AT> FLASH
+
+  
+  /* Uninitialized data section */
+  . = ALIGN(4);
+  .bss :
+  {
+    /* This is used by the startup in order to initialize the .bss section */
+    _sbss = .;         /* define a global symbol at bss start */
+    __bss_start__ = _sbss;
+    *(.bss)
+    *(.bss*)
+    *(COMMON)
+
+    . = ALIGN(4);
+    _ebss = .;         /* define a global symbol at bss end */
+    __bss_end__ = _ebss;
+  } >RAM1
+
+  /* User_heap_stack section, used to check that there is enough RAM left */
+  ._user_heap_stack :
+  {
+    . = ALIGN(8);
+    PROVIDE ( end = . );
+    PROVIDE ( _end = . );
+    . = . + _Min_Heap_Size;
+    . = . + _Min_Stack_Size;
+    . = ALIGN(8);
+  } >RAM1
+
+  
+
+  /* Remove information from the standard libraries */
+  /DISCARD/ :
+  {
+    libc.a ( * )
+    libm.a ( * )
+    libgcc.a ( * )
+  }
+
+  .ARM.attributes 0       : { *(.ARM.attributes) }
+   MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED
+   MB_MEM1 (NOLOAD)       : { *(MB_MEM1) } >RAM_SHARED
+   MB_MEM2 (NOLOAD)       : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
+}
+
+

+ 190 - 0
hw/bsp/stm32wb/family.c

@@ -0,0 +1,190 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Jerzy Kasenberg
+ *
+ * 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.
+ */
+
+#include "stm32wbxx_hal.h"
+#include "bsp/board.h"
+#include "board.h"
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USB_HP_IRQHandler(void)
+{
+  tud_int_handler(0);
+}
+
+void USB_LP_IRQHandler(void)
+{
+  tud_int_handler(0);
+}
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM
+//--------------------------------------------------------------------+
+UART_HandleTypeDef UartHandle;
+
+void board_init(void)
+{
+  board_clock_init();
+
+  // Enable All GPIOs clocks
+  __HAL_RCC_GPIOA_CLK_ENABLE();
+  __HAL_RCC_GPIOB_CLK_ENABLE();
+  __HAL_RCC_GPIOC_CLK_ENABLE();
+  __HAL_RCC_GPIOD_CLK_ENABLE();
+  __HAL_RCC_GPIOE_CLK_ENABLE();
+
+  UART_CLK_EN();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+  // 1ms tick timer
+  SysTick_Config(SystemCoreClock / 1000);
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+  // Explicitly disable systick to prevent its ISR runs before scheduler start
+  SysTick->CTRL &= ~1U;
+
+  // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
+  NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
+#endif
+
+  GPIO_InitTypeDef  GPIO_InitStruct;
+
+  // LED
+  GPIO_InitStruct.Pin = LED_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+
+#if 0
+  // MCO configuration for System clock value verification PA8 will have SYSCLK / 2
+  GPIO_InitStruct.Pin = 8;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_2);
+#endif
+
+  board_led_write(false);
+
+  // Button
+  GPIO_InitStruct.Pin = BUTTON_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+  GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
+
+#ifdef UART_DEV
+  // UART
+  GPIO_InitStruct.Pin       = UART_TX_PIN | UART_RX_PIN;
+  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull      = GPIO_PULLUP;
+  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
+  GPIO_InitStruct.Alternate = UART_GPIO_AF;
+  HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
+
+  UartHandle = (UART_HandleTypeDef){
+    .Instance        = UART_DEV,
+    .Init.BaudRate   = CFG_BOARD_UART_BAUDRATE,
+    .Init.WordLength = UART_WORDLENGTH_8B,
+    .Init.StopBits   = UART_STOPBITS_1,
+    .Init.Parity     = UART_PARITY_NONE,
+    .Init.HwFlowCtl  = UART_HWCONTROL_NONE,
+    .Init.Mode       = UART_MODE_TX_RX,
+    .Init.OverSampling = UART_OVERSAMPLING_16
+  };
+  HAL_UART_Init(&UartHandle);
+#endif
+
+  // USB Pins TODO double check USB clock and pin setup
+  // Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
+  GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
+  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+  HAL_PWREx_EnableVddUSB();
+  __HAL_RCC_USB_CLK_ENABLE();
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state)
+{
+  HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
+}
+
+uint32_t board_button_read(void)
+{
+  return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t* buf, int len)
+{
+  (void) buf; (void) len;
+  return 0;
+}
+
+int board_uart_write(void const * buf, int len)
+{
+#ifdef UART_DEV
+  HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff);
+  return len;
+#else
+  (void) buf; (void) len; (void) UartHandle;
+  return 0;
+#endif
+}
+
+#if CFG_TUSB_OS  == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+void SysTick_Handler (void)
+{
+  system_ticks++;
+}
+
+uint32_t board_millis(void)
+{
+  return system_ticks;
+}
+#endif
+
+void HardFault_Handler (void)
+{
+  asm("bkpt");
+}
+
+// Required by __libc_init_array in startup code if we are compiling using
+// -nostdlib/-nostartfiles.
+void _init(void)
+{
+
+}

+ 44 - 0
hw/bsp/stm32wb/family.mk

@@ -0,0 +1,44 @@
+UF2_FAMILY_ID = 0x70d16653
+ST_FAMILY = wb
+DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
+
+ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
+ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+
+CFLAGS += \
+  -flto \
+  -mthumb \
+  -mabi=aapcs \
+  -mcpu=cortex-m4 \
+  -mfloat-abi=hard \
+  -mfpu=fpv4-sp-d16 \
+  -nostdlib -nostartfiles \
+  -DCFG_TUSB_MCU=OPT_MCU_STM32WB
+
+# suppress warning caused by vendor mcu driver
+CFLAGS += -Wno-error=cast-align -Wno-unused-parameter
+
+SRC_C += \
+	src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+	$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \
+	$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c
+
+INC += \
+	$(TOP)/$(BOARD_PATH) \
+	$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
+	$(TOP)/$(ST_CMSIS)/Include \
+	$(TOP)/$(ST_HAL_DRIVER)/Inc
+
+# For freeRTOS port source
+FREERTOS_PORT = ARM_CM4F
+
+# flash target using on-board stlink
+flash: flash-stlink

+ 349 - 0
hw/bsp/stm32wb/stm32wbxx_hal_conf.h

@@ -0,0 +1,349 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_conf.h
+  * @author  MCD Application Team
+  * @brief   HAL configuration file.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32WBxx_HAL_CONF_H
+#define __STM32WBxx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+  * @brief This is the list of modules to be used in the HAL driver
+  */
+#define HAL_MODULE_ENABLED
+/*#define HAL_ADC_MODULE_ENABLED   */
+/*#define HAL_COMP_MODULE_ENABLED   */
+/*#define HAL_CRC_MODULE_ENABLED   */
+/*#define HAL_HSEM_MODULE_ENABLED   */
+/*#define HAL_IPCC_MODULE_ENABLED   */
+/*#define HAL_IRDA_MODULE_ENABLED   */
+/*#define HAL_LCD_MODULE_ENABLED   */
+/*#define HAL_LPTIM_MODULE_ENABLED   */
+/*#define HAL_PCD_MODULE_ENABLED   */
+/*#define HAL_PKA_MODULE_ENABLED   */
+/*#define HAL_QSPI_MODULE_ENABLED   */
+#define HAL_RTC_MODULE_ENABLED
+/*#define HAL_SAI_MODULE_ENABLED   */
+/*#define HAL_SMBUS_MODULE_ENABLED   */
+/*#define HAL_SMARTCARD_MODULE_ENABLED   */
+/*#define HAL_TSC_MODULE_ENABLED   */
+#define HAL_UART_MODULE_ENABLED
+/*#define HAL_USART_MODULE_ENABLED   */
+/*#define HAL_WWDG_MODULE_ENABLED   */
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_IWDG_MODULE_ENABLED
+#define HAL_TIM_MODULE_ENABLED
+#define HAL_SPI_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
+/*#define HAL_CRYP_MODULE_ENABLED  */
+
+#define USE_HAL_ADC_REGISTER_CALLBACKS       0u
+#define USE_HAL_COMP_REGISTER_CALLBACKS      0u
+#define USE_HAL_CRYP_REGISTER_CALLBACKS      0u
+#define USE_HAL_I2C_REGISTER_CALLBACKS       0u
+#define USE_HAL_IRDA_REGISTER_CALLBACKS      0u
+#define USE_HAL_LPTIM_REGISTER_CALLBACKS     0u
+#define USE_HAL_PCD_REGISTER_CALLBACKS       0u
+#define USE_HAL_PKA_REGISTER_CALLBACKS       0u
+#define USE_HAL_QSPI_REGISTER_CALLBACKS      0u
+#define USE_HAL_RNG_REGISTER_CALLBACKS       0u
+#define USE_HAL_RTC_REGISTER_CALLBACKS       0u
+#define USE_HAL_SAI_REGISTER_CALLBACKS       0u
+#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u
+#define USE_HAL_SMBUS_REGISTER_CALLBACKS     0u
+#define USE_HAL_SPI_REGISTER_CALLBACKS       0u
+#define USE_HAL_TIM_REGISTER_CALLBACKS       0u
+#define USE_HAL_TSC_REGISTER_CALLBACKS       0u
+#define USE_HAL_UART_REGISTER_CALLBACKS      0u
+#define USE_HAL_USART_REGISTER_CALLBACKS     0u
+#define USE_HAL_WWDG_REGISTER_CALLBACKS      0u
+
+/* ########################## Oscillator Values adaptation ####################*/
+/**
+  * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSE is used as system clock source, directly or through the PLL).
+  */
+#if !defined  (HSE_VALUE)
+#define HSE_VALUE    32000000U             /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined  (HSE_STARTUP_TIMEOUT)
+  #define HSE_STARTUP_TIMEOUT    ((uint32_t)100)   /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief Internal Multiple Speed oscillator (MSI) default value.
+  *        This value is the default MSI range value after Reset.
+  */
+#if !defined  (MSI_VALUE)
+  #define MSI_VALUE    ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+/**
+  * @brief Internal High Speed oscillator (HSI) value.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSI is used as system clock source, directly or through the PLL).
+  */
+#if !defined  (HSI_VALUE)
+#define HSI_VALUE    16000000U            /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+  * @brief Internal Low Speed oscillator (LSI1) value.
+  */
+#if !defined  (LSI1_VALUE)
+ #define LSI1_VALUE  ((uint32_t)32000)       /*!< LSI1 Typical Value in Hz*/
+#endif /* LSI1_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+/**
+  * @brief Internal Low Speed oscillator (LSI2) value.
+  */
+#if !defined  (LSI2_VALUE)
+ #define LSI2_VALUE  ((uint32_t)32000)       /*!< LSI2 Typical Value in Hz*/
+#endif /* LSI2_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+
+/**
+  * @brief External Low Speed oscillator (LSE) value.
+  *        This value is used by the UART, RTC HAL module to compute the system frequency
+  */
+#if !defined  (LSE_VALUE)
+#define LSE_VALUE    32768U               /*!< Value of the External oscillator in Hz*/
+#endif /* LSE_VALUE */
+
+/**
+  * @brief Internal Multiple Speed oscillator (HSI48) default value.
+  *        This value is the default HSI48 range value after Reset.
+  */
+#if !defined (HSI48_VALUE)
+  #define HSI48_VALUE    ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI48_VALUE */
+
+#if !defined  (LSE_STARTUP_TIMEOUT)
+#define LSE_STARTUP_TIMEOUT    5000U      /*!< Time out for LSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief External clock source for SAI1 peripheral
+  *        This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
+  *        frequency.
+  */
+#if !defined (EXTERNAL_SAI1_CLOCK_VALUE)
+  #define EXTERNAL_SAI1_CLOCK_VALUE    ((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/
+#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+   ===  you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+  * @brief This is the HAL system configuration section
+  */
+
+#define  VDD_VALUE                    3300U   /*!< Value of VDD in mv */
+#define  TICK_INT_PRIORITY            0U      /*!< tick interrupt priority */
+#define  USE_RTOS                     0U
+#define  PREFETCH_ENABLE              1
+#define  INSTRUCTION_CACHE_ENABLE     1
+#define  DATA_CACHE_ENABLE            1
+
+/* ########################## Assert Selection ############################## */
+/**
+  * @brief Uncomment the line below to expanse the "assert_param" macro in the
+  *        HAL drivers code
+  */
+/* #define USE_FULL_ASSERT    1U */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+ * Activated: CRC code is present inside driver
+ * Deactivated: CRC code cleaned from driver
+ */
+
+#define USE_SPI_CRC                   0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+  * @brief Include module's header file
+  */
+#ifdef HAL_DMA_MODULE_ENABLED
+  #include "stm32wbxx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+  #include "stm32wbxx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+  #include "stm32wbxx_hal_comp.h"
+#endif /* HAL_COMP_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+  #include "stm32wbxx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+  #include "stm32wbxx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+  #include "stm32wbxx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+  #include "stm32wbxx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+  #include "stm32wbxx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+  #include "stm32wbxx_hal_hsem.h"
+#endif /* HAL_HSEM_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32wbxx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_IPCC_MODULE_ENABLED
+ #include "stm32wbxx_hal_ipcc.h"
+#endif /* HAL_IPCC_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32wbxx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LCD_MODULE_ENABLED
+ #include "stm32wbxx_hal_lcd.h"
+#endif /* HAL_LCD_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+  #include "stm32wbxx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+  #include "stm32wbxx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_PKA_MODULE_ENABLED
+  #include "stm32wbxx_hal_pka.h"
+#endif /* HAL_PKA_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32wbxx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #define USE_HAL_QSPI_REGISTER_CALLBACKS 0U
+ #include "stm32wbxx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+  #include "stm32wbxx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+  #include "stm32wbxx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32wbxx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32wbxx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32wbxx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+ #include "stm32wbxx_hal_smbus.h"
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32wbxx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32wbxx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_TSC_MODULE_ENABLED
+  #include "stm32wbxx_hal_tsc.h"
+#endif /* HAL_TSC_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32wbxx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32wbxx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param expr If expr is false, it calls assert_failed function
+  *         which reports the name of the source file and the source
+  *         line number of the call that failed.
+  *         If expr is true, it returns no value.
+  * @retval None
+  */
+#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32WBxx_HAL_CONF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 2 - 2
hw/bsp/tm4c123/family.c

@@ -7,11 +7,11 @@
 //--------------------------------------------------------------------+
 void USB0_Handler(void)
 {
-#if TUSB_OPT_HOST_ENABLED
+#if CFG_TUH_ENABLED
   tuh_int_handler(0);
 #endif
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
   tud_int_handler(0);
 #endif
 }

+ 1 - 0
hw/mcu/st/cmsis_device_wb

@@ -0,0 +1 @@
+Subproject commit 9c5d1920dd9fabbe2548e10561d63db829bb744f

+ 1 - 0
hw/mcu/st/stm32wbxx_hal_driver

@@ -0,0 +1 @@
+Subproject commit 2c5f06638be516c1b772f768456ba637f077bac8

+ 3 - 1
repository.yml

@@ -9,7 +9,9 @@ repo.versions:
     "0.10.0": "0.10.0"
     "0.10.1": "0.10.1"
     "0.11.0": "0.11.0"
+    "0.12.0": "0.12.0"
+    "0.13.0": "0.13.0"
 
     "0-dev": "0.0.0"        # master
-    "0-latest": "0.11.0"     # latest stable release
+    "0-latest": "0.13.0"    # latest stable release
 

+ 2 - 2
src/class/audio/audio_device.c

@@ -50,7 +50,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO)
+#if (CFG_TUD_ENABLED && CFG_TUD_AUDIO)
 
 //--------------------------------------------------------------------+
 // INCLUDE
@@ -2291,4 +2291,4 @@ uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio)
   return 0;
 }
 
-#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO
+#endif //CFG_TUD_ENABLED && CFG_TUD_AUDIO

+ 1 - 1
src/class/bth/bth_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH)
+#if (CFG_TUD_ENABLED && CFG_TUD_BTH)
 
 //--------------------------------------------------------------------+
 // INCLUDE

+ 1 - 1
src/class/cdc/cdc_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC)
+#if (CFG_TUD_ENABLED && CFG_TUD_CDC)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 3 - 3
src/class/cdc/cdc_host.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC)
+#if (CFG_TUH_ENABLED && CFG_TUH_CDC)
 
 #include "host/usbh.h"
 #include "host/usbh_classdriver.h"
@@ -100,7 +100,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i
 {
   (void) is_notify;
   TU_VERIFY( tuh_cdc_mounted(dev_addr) );
-  TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
+  TU_VERIFY( p_data != NULL && length);
 
   uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
   if ( usbh_edpt_busy(dev_addr, ep_out) ) return false;
@@ -112,7 +112,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is
 {
   (void) is_notify;
   TU_VERIFY( tuh_cdc_mounted(dev_addr) );
-  TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
+  TU_VERIFY( p_buffer != NULL && length );
 
   uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
   if ( usbh_edpt_busy(dev_addr, ep_in) ) return false;

+ 11 - 1
src/class/cdc/cdc_rndis_host.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS)
+#if (CFG_TUH_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS)
 
 //--------------------------------------------------------------------+
 // INCLUDE
@@ -35,6 +35,16 @@
 #include "cdc_host.h"
 #include "cdc_rndis_host.h"
 
+#if 0  // TODO remove subtask related macros later
+// Sub Task
+#define OSAL_SUBTASK_BEGIN
+#define OSAL_SUBTASK_END                    return TUSB_ERROR_NONE;
+
+#define STASK_RETURN(_error)                return _error;
+#define STASK_INVOKE(_subtask, _status)     (_status) = _subtask
+#define STASK_ASSERT(_cond)                 TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED)
+#endif
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+

+ 1 - 1
src/class/cdc/cdc_rndis_host.h

@@ -50,7 +50,7 @@ typedef struct {
 }rndish_data_t;
 
 void rndish_init(void);
-tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc);
+bool rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc);
 void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
 void rndish_close(uint8_t dev_addr);
 

+ 1 - 1
src/class/dfu/dfu_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU)
+#if (CFG_TUD_ENABLED && CFG_TUD_DFU)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 1 - 1
src/class/dfu/dfu_rt_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME)
+#if (CFG_TUD_ENABLED && CFG_TUD_DFU_RUNTIME)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 4 - 1
src/class/hid/hid.h

@@ -1106,7 +1106,10 @@ enum
     {'8'   , 0      }, /* 0x60 */ \
     {'9'   , 0      }, /* 0x61 */ \
     {'0'   , 0      }, /* 0x62 */ \
-    {'0'   , 0      }, /* 0x63 */ \
+    {'.'   , 0      }, /* 0x63 */ \
+    {0     , 0      }, /* 0x64 */ \
+    {0     , 0      }, /* 0x65 */ \
+    {0     , 0      }, /* 0x66 */ \
     {'='   , '='    }, /* 0x67 */ \
 
 

+ 1 - 1
src/class/hid/hid_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_HID)
+#if (CFG_TUD_ENABLED && CFG_TUD_HID)
 
 //--------------------------------------------------------------------+
 // INCLUDE

+ 20 - 28
src/class/hid/hid_host.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID)
+#if (CFG_TUH_ENABLED && CFG_TUH_HID)
 
 #include "host/usbh.h"
 #include "host/usbh_classdriver.h"
@@ -286,28 +286,35 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
   hidh_device_t* hid_dev = get_dev(dev_addr);
   TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0);
 
-  //------------- Endpoint Descriptor -------------//
+  hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count);  
+
+  //------------- Endpoint Descriptors -------------//
   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);
 
-  // first endpoint may be OUT, skip to IN endpoint
-  // TODO also open endpoint OUT
-  if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT)
+  for(int i = 0; i < desc_itf->bNumEndpoints; i++)
   {
+    TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);
+    TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
+
+    if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
+    {
+      hid_itf->ep_in     = desc_ep->bEndpointAddress;
+      hid_itf->epin_size = tu_edpt_packet_size(desc_ep);
+    }
+    else
+    {
+      hid_itf->ep_out     = desc_ep->bEndpointAddress;
+      hid_itf->epout_size = tu_edpt_packet_size(desc_ep);
+    }
+
     p_desc = tu_desc_next(p_desc);
     desc_ep = (tusb_desc_endpoint_t const *) p_desc;
-    TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);
   }
 
-  TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
-
-  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->epin_size = tu_edpt_packet_size(desc_ep);
 
   // Assume bNumDescriptors = 1
   hid_itf->report_desc_type = desc_hid->bReportType;
@@ -402,22 +409,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons
     config_driver_mount_complete(dev_addr, instance, NULL, 0);
   }else
   {
-    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));
+    TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete));
   }
 
   return true;

+ 1 - 1
src/class/midi/midi_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MIDI)
+#if (CFG_TUD_ENABLED && CFG_TUD_MIDI)
 
 //--------------------------------------------------------------------+
 // INCLUDE

+ 2 - 1
src/class/msc/msc_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC)
+#if (CFG_TUD_ENABLED && CFG_TUD_MSC)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"
@@ -753,6 +753,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
           .is_removable         = 1,
           .version              = 2,
           .response_data_format = 2,
+          .additional_length    = sizeof(scsi_inquiry_resp_t) - 5,
       };
 
       // vendor_id, product_id, product_rev is space padded string

+ 1 - 1
src/class/msc/msc_host.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC
+#if CFG_TUH_ENABLED && CFG_TUH_MSC
 
 #include "host/usbh.h"
 #include "host/usbh_classdriver.h"

+ 1 - 1
src/class/net/ecm_rndis_device.c

@@ -27,7 +27,7 @@
 
 #include "tusb_option.h"
 
-#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_ECM_RNDIS )
+#if ( CFG_TUD_ENABLED && CFG_TUD_ECM_RNDIS )
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 1 - 1
src/class/net/ncm_device.c

@@ -28,7 +28,7 @@
 
 #include "tusb_option.h"
 
-#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NCM )
+#if ( CFG_TUD_ENABLED && CFG_TUD_NCM )
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 1 - 1
src/class/usbtmc/usbtmc_device.c

@@ -68,7 +68,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC)
+#if (CFG_TUD_ENABLED && CFG_TUD_USBTMC)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 15 - 4
src/class/vendor/vendor_device.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR)
+#if (CFG_TUD_ENABLED && CFG_TUD_VENDOR)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"
@@ -113,7 +113,7 @@ void tud_vendor_n_read_flush (uint8_t itf)
 //--------------------------------------------------------------------+
 // Write API
 //--------------------------------------------------------------------+
-static bool maybe_transmit(vendord_interface_t* p_itf)
+static uint16_t maybe_transmit(vendord_interface_t* p_itf)
 {
   // skip if previous transfer not complete
   TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in) );
@@ -123,14 +123,24 @@ static bool maybe_transmit(vendord_interface_t* p_itf)
   {
     TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) );
   }
-  return true;
+  return count;
 }
 
 uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize)
 {
   vendord_interface_t* p_itf = &_vendord_itf[itf];
   uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize);
-  maybe_transmit(p_itf);
+  if (tu_fifo_count(&p_itf->tx_ff) >= CFG_TUD_VENDOR_EPSIZE) {
+    maybe_transmit(p_itf);
+  }
+  return ret;
+}
+
+uint32_t tud_vendor_n_flush (uint8_t itf)
+{
+  vendord_interface_t* p_itf = &_vendord_itf[itf];
+  uint32_t ret = maybe_transmit(p_itf);
+
   return ret;
 }
 
@@ -247,6 +257,7 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
   }
   else if ( ep_addr == p_itf->ep_in )
   {
+    if (tud_vendor_tx_cb) tud_vendor_tx_cb(itf, xferred_bytes);
     // Send complete, try to send more if possible
     maybe_transmit(p_itf);
   }

+ 9 - 0
src/class/vendor/vendor_device.h

@@ -52,6 +52,7 @@ uint32_t tud_vendor_n_write_available (uint8_t itf);
 
 static inline
 uint32_t tud_vendor_n_write_str       (uint8_t itf, char const* str);
+uint32_t tud_vendor_n_flush           (uint8_t itf);
 
 //--------------------------------------------------------------------+
 // Application API (Single Port)
@@ -64,6 +65,7 @@ static inline void     tud_vendor_read_flush      (void);
 static inline uint32_t tud_vendor_write           (void const* buffer, uint32_t bufsize);
 static inline uint32_t tud_vendor_write_str       (char const* str);
 static inline uint32_t tud_vendor_write_available (void);
+static inline uint32_t tud_vendor_flush           (void);
 
 //--------------------------------------------------------------------+
 // Application Callback API (weak is optional)
@@ -71,6 +73,8 @@ static inline uint32_t tud_vendor_write_available (void);
 
 // Invoked when received new data
 TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf);
+// Invoked when last rx transfer finished
+TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes);
 
 //--------------------------------------------------------------------+
 // Inline Functions
@@ -121,6 +125,11 @@ static inline uint32_t tud_vendor_write_available (void)
   return tud_vendor_n_write_available(0);
 }
 
+static inline uint32_t tud_vendor_flush (void)
+{
+  return tud_vendor_n_flush(0);
+}
+
 //--------------------------------------------------------------------+
 // Internal Class Driver API
 //--------------------------------------------------------------------+

+ 1 - 1
src/class/vendor/vendor_host.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_VENDOR)
+#if (CFG_TUH_ENABLED && CFG_TUH_VENDOR)
 
 //--------------------------------------------------------------------+
 // INCLUDE

+ 6 - 6
src/class/vendor/vendor_host.h

@@ -49,16 +49,16 @@ static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id,
   return false;
 }
 
-tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length);
-tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length);
+bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length);
+bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length);
 
 //--------------------------------------------------------------------+
 // Internal Class Driver API
 //--------------------------------------------------------------------+
-void         cush_init(void);
-tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length);
-void         cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event);
-void         cush_close(uint8_t dev_addr);
+void cush_init(void);
+bool cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length);
+void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event);
+void cush_close(uint8_t dev_addr);
 
 #ifdef __cplusplus
  }

+ 1 - 1
src/class/video/video_device.c

@@ -27,7 +27,7 @@
 
 #include "tusb_option.h"
 
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING)
+#if (CFG_TUD_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING)
 
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"

+ 2 - 146
src/common/tusb_common.h

@@ -38,6 +38,7 @@
 #define TU_MIN(_x, _y)        ( ( (_x) < (_y) ) ? (_x) : (_y) )
 #define TU_MAX(_x, _y)        ( ( (_x) > (_y) ) ? (_x) : (_y) )
 
+#define TU_U16(_high, _low)   ((uint16_t) (((_high) << 8) | (_low)))
 #define TU_U16_HIGH(_u16)     ((uint8_t) (((_u16) >> 8) & 0x00ff))
 #define TU_U16_LOW(_u16)      ((uint8_t) ((_u16)       & 0x00ff))
 #define U16_TO_U8S_BE(_u16)   TU_U16_HIGH(_u16), TU_U16_LOW(_u16)
@@ -70,23 +71,10 @@
 #include "tusb_compiler.h"
 #include "tusb_verify.h"
 #include "tusb_types.h"
+#include "tusb_debug.h"
 
-#include "tusb_error.h"   // TODO remove
 #include "tusb_timeout.h" // TODO remove
 
-//--------------------------------------------------------------------+
-// Internal Helper used by Host and Device Stack
-//--------------------------------------------------------------------+
-
-// Check if endpoint descriptor is valid per USB specs
-bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
-
-// Bind all endpoint of a interface descriptor to class driver
-void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
-
-// Calculate total length of n interfaces (depending on IAD)
-uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
-
 //--------------------------------------------------------------------+
 // Internal Inline Functions
 //--------------------------------------------------------------------+
@@ -267,138 +255,6 @@ TU_ATTR_ALWAYS_INLINE static inline void     tu_unaligned_write16 (void* mem, ui
             + TU_BIN8(dlsb))
 #endif
 
-//--------------------------------------------------------------------+
-// Debug Function
-//--------------------------------------------------------------------+
-
-// CFG_TUSB_DEBUG for debugging
-// 0 : no debug
-// 1 : print error
-// 2 : print warning
-// 3 : print info
-#if CFG_TUSB_DEBUG
-
-void tu_print_mem(void const *buf, uint32_t count, uint8_t indent);
-
-#ifdef CFG_TUSB_DEBUG_PRINTF
-  extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...);
-  #define tu_printf    CFG_TUSB_DEBUG_PRINTF
-#else
-  #define tu_printf    printf
-#endif
-
-static inline
-void tu_print_var(uint8_t const* buf, uint32_t bufsize)
-{
-  for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
-}
-
-// Log with Level
-#define TU_LOG(n, ...)        TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__)
-#define TU_LOG_MEM(n, ...)    TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__)
-#define TU_LOG_VAR(n, ...)    TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__)
-#define TU_LOG_INT(n, ...)    TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__)
-#define TU_LOG_HEX(n, ...)    TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__)
-#define TU_LOG_LOCATION()     tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
-#define TU_LOG_FAILED()       tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
-
-// Log Level 1: Error
-#define TU_LOG1               tu_printf
-#define TU_LOG1_MEM           tu_print_mem
-#define TU_LOG1_VAR(_x)       tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
-#define TU_LOG1_INT(_x)       tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) )
-#define TU_LOG1_HEX(_x)       tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) )
-
-// Log Level 2: Warn
-#if CFG_TUSB_DEBUG >= 2
-  #define TU_LOG2             TU_LOG1
-  #define TU_LOG2_MEM         TU_LOG1_MEM
-  #define TU_LOG2_VAR         TU_LOG1_VAR
-  #define TU_LOG2_INT         TU_LOG1_INT
-  #define TU_LOG2_HEX         TU_LOG1_HEX
-#endif
-
-// Log Level 3: Info
-#if CFG_TUSB_DEBUG >= 3
-  #define TU_LOG3             TU_LOG1
-  #define TU_LOG3_MEM         TU_LOG1_MEM
-  #define TU_LOG3_VAR         TU_LOG1_VAR
-  #define TU_LOG3_INT         TU_LOG1_INT
-  #define TU_LOG3_HEX         TU_LOG1_HEX
-#endif
-
-typedef struct
-{
-  uint32_t key;
-  const char* data;
-} tu_lookup_entry_t;
-
-typedef struct
-{
-  uint16_t count;
-  tu_lookup_entry_t const* items;
-} tu_lookup_table_t;
-
-static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key)
-{
-  static char not_found[11];
-
-  for(uint16_t i=0; i<p_table->count; i++)
-  {
-    if (p_table->items[i].key == key) return p_table->items[i].data;
-  }
-
-  // not found return the key value in hex
-  sprintf(not_found, "0x%08lX", (unsigned long) key);
-
-  return not_found;
-}
-
-#endif // CFG_TUSB_DEBUG
-
-#ifndef TU_LOG
-#define TU_LOG(n, ...)
-#define TU_LOG_MEM(n, ...)
-#define TU_LOG_VAR(n, ...)
-#define TU_LOG_INT(n, ...)
-#define TU_LOG_HEX(n, ...)
-#define TU_LOG_LOCATION()
-#define TU_LOG_FAILED()
-#endif
-
-// TODO replace all TU_LOGn with TU_LOG(n)
-
-#define TU_LOG0(...)
-#define TU_LOG0_MEM(...)
-#define TU_LOG0_VAR(...)
-#define TU_LOG0_INT(...)
-#define TU_LOG0_HEX(...)
-
-
-#ifndef TU_LOG1
-  #define TU_LOG1(...)
-  #define TU_LOG1_MEM(...)
-  #define TU_LOG1_VAR(...)
-  #define TU_LOG1_INT(...)
-  #define TU_LOG1_HEX(...)
-#endif
-
-#ifndef TU_LOG2
-  #define TU_LOG2(...)
-  #define TU_LOG2_MEM(...)
-  #define TU_LOG2_VAR(...)
-  #define TU_LOG2_INT(...)
-  #define TU_LOG2_HEX(...)
-#endif
-
-#ifndef TU_LOG3
-  #define TU_LOG3(...)
-  #define TU_LOG3_MEM(...)
-  #define TU_LOG3_VAR(...)
-  #define TU_LOG3_INT(...)
-  #define TU_LOG3_HEX(...)
-#endif
-
 #ifdef __cplusplus
  }
 #endif

+ 8 - 4
src/common/tusb_compiler.h

@@ -51,10 +51,10 @@
 #endif
 
 // Compile-time Assert
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
-  #define TU_VERIFY_STATIC   _Static_assert
-#elif defined (__cplusplus) && __cplusplus >= 201103L
+#if defined (__cplusplus) && __cplusplus >= 201103L
   #define TU_VERIFY_STATIC   static_assert
+#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+  #define TU_VERIFY_STATIC   _Static_assert
 #elif defined(__CCRX__)
   #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0];
 #else
@@ -75,7 +75,11 @@
  * Nth position is the same as the number of arguments
  * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma)
  *------------------------------------------------------------------*/
-#define TU_ARGS_NUM(...) 	 _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N())
+#if !defined(__CCRX__)
+#define TU_ARGS_NUM(...)   _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N())
+#else
+#define TU_ARGS_NUM(...)   _TU_NARG(_0, __VA_ARGS__,_RSEQ_N())
+#endif
 
 #define _TU_NARG(...)      _GET_NTH_ARG(__VA_ARGS__)
 #define _GET_NTH_ARG( \

+ 174 - 0
src/common/tusb_debug.h

@@ -0,0 +1,174 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022, 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_DEBUG_H_
+#define _TUSB_DEBUG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Debug
+//--------------------------------------------------------------------+
+
+// CFG_TUSB_DEBUG for debugging
+// 0 : no debug
+// 1 : print error
+// 2 : print warning
+// 3 : print info
+#if CFG_TUSB_DEBUG
+
+// Enum to String for debugging purposes
+#if CFG_TUSB_DEBUG >= 2
+extern char const* const tu_str_speed[];
+extern char const* const tu_str_std_request[];
+#endif
+
+void tu_print_mem(void const *buf, uint32_t count, uint8_t indent);
+
+#ifdef CFG_TUSB_DEBUG_PRINTF
+  extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...);
+  #define tu_printf    CFG_TUSB_DEBUG_PRINTF
+#else
+  #define tu_printf    printf
+#endif
+
+static inline void tu_print_var(uint8_t const* buf, uint32_t bufsize)
+{
+  for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
+}
+
+// Log with Level
+#define TU_LOG(n, ...)        TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__)
+#define TU_LOG_MEM(n, ...)    TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__)
+#define TU_LOG_VAR(n, ...)    TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__)
+#define TU_LOG_INT(n, ...)    TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__)
+#define TU_LOG_HEX(n, ...)    TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__)
+#define TU_LOG_LOCATION()     tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
+#define TU_LOG_FAILED()       tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
+
+// Log Level 1: Error
+#define TU_LOG1               tu_printf
+#define TU_LOG1_MEM           tu_print_mem
+#define TU_LOG1_VAR(_x)       tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
+#define TU_LOG1_INT(_x)       tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) )
+#define TU_LOG1_HEX(_x)       tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) )
+
+// Log Level 2: Warn
+#if CFG_TUSB_DEBUG >= 2
+  #define TU_LOG2             TU_LOG1
+  #define TU_LOG2_MEM         TU_LOG1_MEM
+  #define TU_LOG2_VAR         TU_LOG1_VAR
+  #define TU_LOG2_INT         TU_LOG1_INT
+  #define TU_LOG2_HEX         TU_LOG1_HEX
+#endif
+
+// Log Level 3: Info
+#if CFG_TUSB_DEBUG >= 3
+  #define TU_LOG3             TU_LOG1
+  #define TU_LOG3_MEM         TU_LOG1_MEM
+  #define TU_LOG3_VAR         TU_LOG1_VAR
+  #define TU_LOG3_INT         TU_LOG1_INT
+  #define TU_LOG3_HEX         TU_LOG1_HEX
+#endif
+
+typedef struct
+{
+  uint32_t key;
+  const char* data;
+} tu_lookup_entry_t;
+
+typedef struct
+{
+  uint16_t count;
+  tu_lookup_entry_t const* items;
+} tu_lookup_table_t;
+
+static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key)
+{
+  static char not_found[11];
+
+  for(uint16_t i=0; i<p_table->count; i++)
+  {
+    if (p_table->items[i].key == key) return p_table->items[i].data;
+  }
+
+  // not found return the key value in hex
+  snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key);
+
+  return not_found;
+}
+
+#endif // CFG_TUSB_DEBUG
+
+#ifndef TU_LOG
+  #define TU_LOG(n, ...)
+  #define TU_LOG_MEM(n, ...)
+  #define TU_LOG_VAR(n, ...)
+  #define TU_LOG_INT(n, ...)
+  #define TU_LOG_HEX(n, ...)
+  #define TU_LOG_LOCATION()
+  #define TU_LOG_FAILED()
+#endif
+
+// TODO replace all TU_LOGn with TU_LOG(n)
+
+#define TU_LOG0(...)
+#define TU_LOG0_MEM(...)
+#define TU_LOG0_VAR(...)
+#define TU_LOG0_INT(...)
+#define TU_LOG0_HEX(...)
+
+#ifndef TU_LOG1
+  #define TU_LOG1(...)
+  #define TU_LOG1_MEM(...)
+  #define TU_LOG1_VAR(...)
+  #define TU_LOG1_INT(...)
+  #define TU_LOG1_HEX(...)
+#endif
+
+#ifndef TU_LOG2
+  #define TU_LOG2(...)
+  #define TU_LOG2_MEM(...)
+  #define TU_LOG2_VAR(...)
+  #define TU_LOG2_INT(...)
+  #define TU_LOG2_HEX(...)
+#endif
+
+#ifndef TU_LOG3
+  #define TU_LOG3(...)
+  #define TU_LOG3_MEM(...)
+  #define TU_LOG3_VAR(...)
+  #define TU_LOG3_INT(...)
+  #define TU_LOG3_HEX(...)
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_DEBUG_H_ */

+ 0 - 75
src/common/tusb_error.h

@@ -1,75 +0,0 @@
-/* 
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-/** \ingroup Group_Common
- *  \defgroup Group_Error Error Codes
- *  @{ */
-
-#ifndef _TUSB_ERRORS_H_
-#define _TUSB_ERRORS_H_
-
-#include "tusb_option.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#define ERROR_ENUM(x) x,
-#define ERROR_STRING(x) #x,
-
-#define ERROR_TABLE(ENTRY) \
-    ENTRY(TUSB_ERROR_NONE                            )\
-    ENTRY(TUSB_ERROR_INVALID_PARA                    )\
-    ENTRY(TUSB_ERROR_DEVICE_NOT_READY                )\
-    ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY               )\
-    ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED            )\
-    ENTRY(TUSB_ERROR_OSAL_TIMEOUT                    )\
-    ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED         )\
-    ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED         )\
-    ENTRY(TUSB_ERROR_NOT_SUPPORTED                   )\
-    ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY               )\
-    ENTRY(TUSB_ERROR_FAILED                          )\
-
-/// \brief Error Code returned
-/// TODO obsolete and to be remove
-typedef enum
-{
-  ERROR_TABLE(ERROR_ENUM)
-  TUSB_ERROR_COUNT
-}tusb_error_t;
-
-#if CFG_TUSB_DEBUG
-/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0
-extern char const* const tusb_strerr[TUSB_ERROR_COUNT];
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_ERRORS_H_ */
-
-/**  @} */

+ 130 - 72
src/device/dcd_attr.h → src/common/tusb_mcu.h

@@ -24,112 +24,151 @@
  * This file is part of the TinyUSB stack.
  */
 
-#ifndef TUSB_DCD_ATTR_H_
-#define TUSB_DCD_ATTR_H_
+#ifndef TUSB_MCU_H_
+#define TUSB_MCU_H_
 
-#include "tusb_option.h"
+//--------------------------------------------------------------------+
+// Port Specific
+// TUP stand for TinyUSB Port (can be renamed)
+//--------------------------------------------------------------------+
 
-// Attribute includes
-// - ENDPOINT_MAX: max (logical) number of endpoint
-// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed,
-//                              e.g EP1 OUT & EP1 IN cannot exist together
-// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on.
+//------------- Unaligned Memory Access -------------//
+
+// ARMv7+ (M3-M7, M23-M33) can access unaligned memory
+#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
+  #define TUP_ARCH_STRICT_ALIGN   0
+#else
+  #define TUP_ARCH_STRICT_ALIGN   1
+#endif
+
+/* USB Controller Attributes for Device, Host or MCU (both)
+ * - ENDPOINT_MAX: max (logical) number of endpoint
+ * - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed,
+ *                              e.g EP1 OUT & EP1 IN cannot exist together
+ * - RHPORT_HIGHSPEED: mask to indicate which port support highspeed mode (without external PHY)
+ *                     bit0 for port0 and so on.
+ */
 
 //------------- NXP -------------//
 #if   TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX)
-  #define DCD_ATTR_ENDPOINT_MAX   5
+  #define TUP_DCD_ENDPOINT_MAX    5
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
+  #define TUP_USBIP_OHCI
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
   // TODO USB0 has 6, USB1 has 4
-  #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS
-  #define DCD_ATTR_ENDPOINT_MAX   6
+  #define TUP_USBIP_CHIPIDEA_HS
+  #define TUP_USBIP_EHCI
+
+  #define TUP_DCD_ENDPOINT_MAX    6
+  #define TUP_RHPORT_HIGHSPEED    0x01 // Port0 HS, Port1 FS
+
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX)
-   #define DCD_ATTR_ENDPOINT_MAX   5
+   #define TUP_DCD_ENDPOINT_MAX   5
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC54XXX)
   // TODO USB0 has 5, USB1 has 6
-  #define DCD_ATTR_ENDPOINT_MAX   6
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC55XX)
   // TODO USB0 has 5, USB1 has 6
-  #define DCD_ATTR_ENDPOINT_MAX   6
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 #elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX)
-  #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_USBIP_CHIPIDEA_HS
+  #define TUP_USBIP_EHCI
+
+  #define TUP_DCD_ENDPOINT_MAX    8
+  #define TUP_RHPORT_HIGHSPEED    0x03 // Port0 HS, Port1 HS
+
 
 #elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
 
 #elif TU_CHECK_MCU(OPT_MCU_MM32F327X)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
 
 //------------- Nordic -------------//
 #elif TU_CHECK_MCU(OPT_MCU_NRF5X)
   // 8 CBI + 1 ISO
-  #define DCD_ATTR_ENDPOINT_MAX   9
+  #define TUP_DCD_ENDPOINT_MAX    9
 
 //------------- Microchip -------------//
 #elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \
       TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_SAMG)
-  #define DCD_ATTR_ENDPOINT_MAX   6
-  #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+  #define TUP_DCD_ENDPOINT_MAX    6
+  #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER
 
 #elif TU_CHECK_MCU(OPT_MCU_SAMX7X)
-  #define DCD_ATTR_ENDPOINT_MAX   10
-  #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+  #define TUP_DCD_ENDPOINT_MAX    10
+  #define TUP_RHPORT_HIGHSPEED    0x01
+  #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER
 
 #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ)
-  #define DCD_ATTR_ENDPOINT_MAX   8
-  #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+  #define TUP_DCD_ENDPOINT_MAX    8
+  #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER
 
 //------------- ST -------------//
 #elif TU_CHECK_MCU(OPT_MCU_STM32F0)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32F1)
   #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \
       defined (STM32F107xB) || defined (STM32F107xC)
-    #define DCD_ATTR_ENDPOINT_MAX   4
-    #define DCD_ATTR_DWC2_STM32
+    #define TUP_USBIP_DWC2
+    #define TUP_USBIP_DWC2_STM32
+
+    #define TUP_DCD_ENDPOINT_MAX  4
   #else
-    #define DCD_ATTR_ENDPOINT_MAX   8
+    #define TUP_DCD_ENDPOINT_MAX  8
   #endif
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32F2)
+  #define TUP_USBIP_DWC2
+  #define TUP_USBIP_DWC2_STM32
+
   // FS has 4 ep, HS has 5 ep
-  #define DCD_ATTR_ENDPOINT_MAX   6
-  #define DCD_ATTR_DWC2_STM32
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32F3)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32F4)
+  #define TUP_USBIP_DWC2
+  #define TUP_USBIP_DWC2_STM32
+
   // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9
-  #define DCD_ATTR_ENDPOINT_MAX   6
-  #define DCD_ATTR_DWC2_STM32
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32F7)
+  #define TUP_USBIP_DWC2
+  #define TUP_USBIP_DWC2_STM32
+
   // FS has 6, HS has 9
-  #define DCD_ATTR_ENDPOINT_MAX   9
-  #define DCD_ATTR_DWC2_STM32
+  #define TUP_DCD_ENDPOINT_MAX    9
+
+  // MCU with on-chip HS Phy
+  #if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx)
+    #define TUP_RHPORT_HIGHSPEED  0x02 // Port 0: FS, Port 1: HS
+  #endif
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32H7)
-  #define DCD_ATTR_ENDPOINT_MAX   9
-  #define DCD_ATTR_DWC2_STM32
+  #define TUP_USBIP_DWC2
+  #define TUP_USBIP_DWC2_STM32
+
+  #define TUP_DCD_ENDPOINT_MAX    9
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32G4)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_STM32L4)
   #if defined (STM32L475xx) || defined (STM32L476xx) ||                          \
@@ -137,91 +176,110 @@
       defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
       defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \
       defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
-    #define DCD_ATTR_ENDPOINT_MAX   6
-    #define DCD_ATTR_DWC2_STM32
+    #define TUP_USBIP_DWC2
+    #define TUP_USBIP_DWC2_STM32
+
+    #define TUP_DCD_ENDPOINT_MAX  6
   #else
-    #define DCD_ATTR_ENDPOINT_MAX   8
+    #define TUP_DCD_ENDPOINT_MAX  8
   #endif
 
+#elif TU_CHECK_MCU(OPT_MCU_STM32WB)
+#define TUP_DCD_ENDPOINT_MAX    8
+
 //------------- Sony -------------//
 #elif TU_CHECK_MCU(OPT_MCU_CXD56)
-  #define DCD_ATTR_ENDPOINT_MAX   7
-  #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+  #define TUP_DCD_ENDPOINT_MAX    7
+  #define TUP_RHPORT_HIGHSPEED    0x01
+  #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER
 
 //------------- TI -------------//
 #elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 //------------- ValentyUSB -------------//
 #elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
 
 //------------- Nuvoton -------------//
 #elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 #elif TU_CHECK_MCU(OPT_MCU_NUC120)
-  #define DCD_ATTR_ENDPOINT_MAX   6
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 #elif TU_CHECK_MCU(OPT_MCU_NUC505)
-  #define DCD_ATTR_ENDPOINT_MAX   12
+  #define TUP_DCD_ENDPOINT_MAX    12
+  #define TUP_RHPORT_HIGHSPEED    0x01
 
 //------------- Espressif -------------//
 #elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
-  #define DCD_ATTR_ENDPOINT_MAX   6
+  #define TUP_USBIP_DWC2
+  #define TUP_DCD_ENDPOINT_MAX    6
 
 //------------- Dialog -------------//
 #elif TU_CHECK_MCU(OPT_MCU_DA1469X)
-  #define DCD_ATTR_ENDPOINT_MAX   4
+  #define TUP_DCD_ENDPOINT_MAX    4
 
 //------------- Raspberry Pi -------------//
 #elif TU_CHECK_MCU(OPT_MCU_RP2040)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
 
 //------------- Silabs -------------//
 #elif TU_CHECK_MCU(OPT_MCU_EFM32GG)
-  #define DCD_ATTR_ENDPOINT_MAX   7
+  #define TUP_USBIP_DWC2
+  #define TUP_DCD_ENDPOINT_MAX    7
 
 //------------- Renesas -------------//
 #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
-  #define DCD_ATTR_ENDPOINT_MAX   10
+  #define TUP_DCD_ENDPOINT_MAX    10
 
 //------------- GigaDevice -------------//
 #elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
-  #define DCD_ATTR_ENDPOINT_MAX   4
+  #define TUP_USBIP_DWC2
+  #define TUP_DCD_ENDPOINT_MAX    4
 
 //------------- Broadcom -------------//
 #elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_USBIP_DWC2
+  #define TUP_DCD_ENDPOINT_MAX    8
+  #define TUP_RHPORT_HIGHSPEED    0x01
 
 //------------- Broadcom -------------//
 #elif TU_CHECK_MCU(OPT_MCU_XMC4000)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_USBIP_DWC2
+  #define TUP_DCD_ENDPOINT_MAX    8
 
 //------------- BridgeTek -------------//
 #elif TU_CHECK_MCU(OPT_MCU_FT90X)
-  #define DCD_ATTR_ENDPOINT_MAX   8
+  #define TUP_DCD_ENDPOINT_MAX    8
+  #define TUP_RHPORT_HIGHSPEED    0x01
 
 #elif TU_CHECK_MCU(OPT_MCU_FT93X)
-  #define DCD_ATTR_ENDPOINT_MAX   16
+  #define TUP_DCD_ENDPOINT_MAX    16
+  #define TUP_RHPORT_HIGHSPEED    0x01
 
 //------------ Allwinner -------------//
 #elif TU_CHECK_MCU(OPT_MCU_F1C100S)
-  #define DCD_ATTR_ENDPOINT_MAX   4
+  #define TUP_DCD_ENDPOINT_MAX    4
 
-#elif TU_CHECK_MCU(OPT_MCU_HPM)
-  #define DCD_ATTR_ENDPOINT_MAX   8
-#else
-  #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8"
-  #define DCD_ATTR_ENDPOINT_MAX   8
+#endif
+
+//--------------------------------------------------------------------+
+// Default Values
+//--------------------------------------------------------------------+
+
+#ifndef TUP_DCD_ENDPOINT_MAX
+  #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8"
+  #define TUP_DCD_ENDPOINT_MAX    8
 #endif
 
 // Default to fullspeed if not defined
-//#ifndef PORT_HIGHSPEED
-//  #define DCD_ATTR_PORT_HIGHSPEED 0x00
-//#endif
+#ifndef TUP_RHPORT_HIGHSPEED
+  #define TUP_RHPORT_HIGHSPEED    0x00
+#endif
 
 #endif

+ 65 - 0
src/common/tusb_private.h

@@ -0,0 +1,65 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022, 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_PRIVATE_H_
+#define _TUSB_PRIVATE_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+typedef struct TU_ATTR_PACKED
+{
+  volatile uint8_t busy    : 1;
+  volatile uint8_t stalled : 1;
+  volatile uint8_t claimed : 1;
+}tu_edpt_state_t;
+
+//--------------------------------------------------------------------+
+// Internal Helper used by Host and Device Stack
+//--------------------------------------------------------------------+
+
+// Check if endpoint descriptor is valid per USB specs
+bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
+
+// Bind all endpoint of a interface descriptor to class driver
+void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
+
+// Calculate total length of n interfaces (depending on IAD)
+uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
+
+// Claim an endpoint with provided mutex
+bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
+
+// Release an endpoint with provided mutex
+bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_PRIVATE_H_ */

+ 1 - 8
src/common/tusb_types.h

@@ -223,14 +223,6 @@ enum {
 
 #define TUSB_DESC_CONFIG_POWER_MA(x)  ((x)/2)
 
-/// Device State TODO remove
-typedef enum
-{
-  TUSB_DEVICE_STATE_UNPLUG = 0  ,
-  TUSB_DEVICE_STATE_CONFIGURED  ,
-  TUSB_DEVICE_STATE_SUSPENDED   ,
-}tusb_device_state_t;
-
 typedef enum
 {
   XFER_RESULT_SUCCESS,
@@ -265,6 +257,7 @@ typedef enum
 
 enum
 {
+  CONTROL_STAGE_IDLE,
   CONTROL_STAGE_SETUP,
   CONTROL_STAGE_DATA,
   CONTROL_STAGE_ACK

+ 0 - 28
src/common/tusb_verify.h

@@ -74,10 +74,8 @@
 
 #if CFG_TUSB_DEBUG
   #include <stdio.h>
-  #define _MESS_ERR(_err)   tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err])
   #define _MESS_FAILED()    tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__)
 #else
-  #define _MESS_ERR(_err) do {} while (0)
   #define _MESS_FAILED() do {} while (0)
 #endif
 
@@ -148,32 +146,6 @@
 #define TU_ASSERT(...)             GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
 #endif
 
-// TODO remove TU_ASSERT_ERR() later
-
-/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/
-#define TU_VERIFY_ERR_DEF2(_error, _handler)  do               \
-{                                                              \
-  uint32_t _err = (uint32_t)(_error);                          \
-  if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \
-} while(0)
-
-#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do          \
-{                                                              \
-  uint32_t _err = (uint32_t)(_error);                          \
-  if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \
-} while(0)
-
-/*------------------------------------------------------------------*/
-/* ASSERT Error
- * basically TU_VERIFY Error with TU_BREAKPOINT() as handler
- *------------------------------------------------------------------*/
-#define ASSERT_ERR_1ARGS(_error)         TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT())
-#define ASSERT_ERR_2ARGS(_error, _ret)   TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret)
-
-#ifndef TU_ASSERT_ERR
-#define TU_ASSERT_ERR(...)         GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__)
-#endif
-
 /*------------------------------------------------------------------*/
 /* ASSERT HDLR
  *------------------------------------------------------------------*/

+ 1 - 2
src/device/dcd.h

@@ -30,7 +30,6 @@
 #include "common/tusb_common.h"
 #include "osal/osal.h"
 #include "common/tusb_fifo.h"
-#include "dcd_attr.h"
 
 #ifdef __cplusplus
  extern "C" {
@@ -41,7 +40,7 @@
 //--------------------------------------------------------------------+
 
 #ifndef CFG_TUD_ENDPPOINT_MAX
-  #define CFG_TUD_ENDPPOINT_MAX   DCD_ATTR_ENDPOINT_MAX
+  #define CFG_TUD_ENDPPOINT_MAX   TUP_DCD_ENDPOINT_MAX
 #endif
 
 //--------------------------------------------------------------------+

+ 44 - 77
src/device/usbd.c

@@ -26,9 +26,11 @@
 
 #include "tusb_option.h"
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 
 #include "tusb.h"
+#include "common/tusb_private.h"
+
 #include "device/usbd.h"
 #include "device/usbd_pvt.h"
 #include "device/dcd.h"
@@ -67,17 +69,10 @@ typedef struct
   volatile uint8_t cfg_num; // current active configuration (0x00 is not configured)
   uint8_t speed;
 
-  uint8_t itf2drv[16];     // map interface number to driver (0xff is invalid)
-  uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid )
+  uint8_t itf2drv[16];                      // map interface number to driver (0xff is invalid)
+  uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each
 
-  struct TU_ATTR_PACKED
-  {
-    volatile bool busy    : 1;
-    volatile bool stalled : 1;
-    volatile bool claimed : 1;
-
-    // TODO merge ep2drv here, 4-bit should be sufficient
-  }ep_status[CFG_TUD_ENDPPOINT_MAX][2];
+  tu_edpt_state_t ep_status[CFG_TUD_ENDPPOINT_MAX][2];
 
 }usbd_device_t;
 
@@ -269,11 +264,12 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid)
 // DCD Event
 //--------------------------------------------------------------------+
 
-static bool _usbd_initialized = false;
+enum { RHPORT_INVALID = 0xFFu };
+static uint8_t _usbd_rhport = RHPORT_INVALID;
 
 // 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);
+// usbd_int_set() is used as mutex in OS NONE config
+OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t);
 static osal_queue_t _usbd_q;
 
 // Mutex for claiming endpoint, only needed when using with preempted RTOS
@@ -315,25 +311,6 @@ static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
   "Func Call"
 };
 
-static char const* const _tusb_std_request_str[] =
-{
-  "Get Status"        ,
-  "Clear Feature"     ,
-  "Reserved"          ,
-  "Set Feature"       ,
-  "Reserved"          ,
-  "Set Address"       ,
-  "Get Descriptor"    ,
-  "Set Descriptor"    ,
-  "Get Configuration" ,
-  "Set Configuration" ,
-  "Get Interface"     ,
-  "Set Interface"     ,
-  "Synch Frame"
-};
-
-static char const* const _tusb_speed_str[] = { "Full", "Low", "High" };
-
 // for usbd_control to print the name of control complete driver
 void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback)
 {
@@ -382,21 +359,21 @@ bool tud_remote_wakeup(void)
 {
   // only wake up host if this feature is supported and enabled and we are suspended
   TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en );
-  dcd_remote_wakeup(TUD_OPT_RHPORT);
+  dcd_remote_wakeup(_usbd_rhport);
   return true;
 }
 
 bool tud_disconnect(void)
 {
   TU_VERIFY(dcd_disconnect);
-  dcd_disconnect(TUD_OPT_RHPORT);
+  dcd_disconnect(_usbd_rhport);
   return true;
 }
 
 bool tud_connect(void)
 {
   TU_VERIFY(dcd_connect);
-  dcd_connect(TUD_OPT_RHPORT);
+  dcd_connect(_usbd_rhport);
   return true;
 }
 
@@ -405,15 +382,16 @@ bool tud_connect(void)
 //--------------------------------------------------------------------+
 bool tud_inited(void)
 {
-  return _usbd_initialized;
+  return _usbd_rhport != RHPORT_INVALID;
 }
 
 bool tud_init (uint8_t rhport)
 {
   // skip if already initialized
-  if (_usbd_initialized) return _usbd_initialized;
+  if ( tud_inited() ) return true;
 
   TU_LOG2("USBD init\r\n");
+  TU_LOG2_INT(sizeof(usbd_device_t));
 
   tu_varclr(&_usbd_dev);
 
@@ -445,7 +423,7 @@ bool tud_init (uint8_t rhport)
   dcd_init(rhport);
   dcd_int_enable(rhport);
 
-  _usbd_initialized = true;
+  _usbd_rhport = rhport;
 
   return true;
 }
@@ -514,7 +492,7 @@ void tud_task (void)
     switch ( event.event_id )
     {
       case DCD_EVENT_BUS_RESET:
-        TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]);
+        TU_LOG2(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]);
         usbd_reset(event.rhport);
         _usbd_dev.speed = event.bus_reset.speed;
       break;
@@ -661,7 +639,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
 #if CFG_TUSB_DEBUG >= 2
   if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME)
   {
-    TU_LOG2("  %s", _tusb_std_request_str[p_request->bRequest]);
+    TU_LOG2("  %s", tu_str_std_request[p_request->bRequest]);
     if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n");
   }
 #endif
@@ -1184,6 +1162,17 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_
 // USBD API For Class Driver
 //--------------------------------------------------------------------+
 
+void usbd_int_set(bool enabled)
+{
+  if (enabled)
+  {
+    dcd_int_enable(_usbd_rhport);
+  }else
+  {
+    dcd_int_disable(_usbd_rhport);
+  }
+}
+
 // Parse consecutive endpoint descriptors (IN & OUT)
 bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in)
 {
@@ -1242,52 +1231,30 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
   // TODO add this check later, also make sure we don't starve an out endpoint while suspending
   // TU_VERIFY(tud_ready());
 
-  uint8_t const epnum = tu_edpt_number(ep_addr);
-  uint8_t const dir   = tu_edpt_dir(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
-
-  // can only claim the endpoint if it is not busy and not claimed yet.
-  bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0);
-  if (ret)
-  {
-    _usbd_dev.ep_status[epnum][dir].claimed = 1;
-  }
+  uint8_t const epnum       = tu_edpt_number(ep_addr);
+  uint8_t const dir         = tu_edpt_dir(ep_addr);
+  tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
 
-#if CFG_TUSB_OS != OPT_OS_NONE
-  osal_mutex_unlock(_usbd_mutex);
+#if TUSB_OPT_MUTEX
+  return tu_edpt_claim(ep_state, _usbd_mutex);
+#else
+  return tu_edpt_claim(ep_state, NULL);
 #endif
-
-  return ret;
 }
 
 bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr)
 {
   (void) rhport;
 
-  uint8_t const epnum = tu_edpt_number(ep_addr);
-  uint8_t const dir   = tu_edpt_dir(ep_addr);
+  uint8_t const epnum       = tu_edpt_number(ep_addr);
+  uint8_t const dir         = tu_edpt_dir(ep_addr);
+  tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
 
-#if CFG_TUSB_OS != OPT_OS_NONE
-  osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
-#endif
-
-  // can only release the endpoint if it is claimed and not busy
-  bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1);
-  if (ret)
-  {
-    _usbd_dev.ep_status[epnum][dir].claimed = 0;
-  }
-
-#if CFG_TUSB_OS != OPT_OS_NONE
-  osal_mutex_unlock(_usbd_mutex);
+#if TUSB_OPT_MUTEX
+  return tu_edpt_release(ep_state, _usbd_mutex);
+#else
+  return tu_edpt_release(ep_state, NULL);
 #endif
-
-  return ret;
 }
 
 bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)

+ 4 - 4
src/device/usbd.h

@@ -456,7 +456,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
   /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
   TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
   /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
-  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
+  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
   /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
   TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
 
@@ -505,7 +505,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
   /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
   TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
   /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
-  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
+  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
   /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
   TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
 
@@ -553,7 +553,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
   /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
   TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
   /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
-  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
+  TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
   /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
   TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
   /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\
@@ -561,7 +561,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
 
 //   Calculate wMaxPacketSize of Endpoints
 #define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \
-    ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels)
+    ((((_maxFrequency + (TUD_OPT_HIGH_SPEED ? 7999 : 999)) / (TUD_OPT_HIGH_SPEED ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels)
 
 
 //--------------------------------------------------------------------+

+ 1 - 1
src/device/usbd_control.c

@@ -26,7 +26,7 @@
 
 #include "tusb_option.h"
 
-#if TUSB_OPT_DEVICE_ENABLED
+#if CFG_TUD_ENABLED
 
 #include "tusb.h"
 #include "device/usbd_pvt.h"

+ 3 - 1
src/device/usbd_pvt.h

@@ -58,6 +58,8 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR
 
 typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
 
+void usbd_int_set(bool enabled);
+
 //--------------------------------------------------------------------+
 // USBD Endpoint API
 //--------------------------------------------------------------------+
@@ -78,7 +80,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16
 // If caller does not make any transfer, it must release endpoint for others.
 bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr);
 
-// Release an endpoint without submitting a transfer
+// Release claimed endpoint without submitting a transfer
 bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr);
 
 // Check if endpoint is busy transferring

+ 15 - 15
src/host/hcd.h

@@ -30,12 +30,24 @@
 #include "common/tusb_common.h"
 #include "osal/osal.h"
 #include "common/tusb_fifo.h"
-#include "hcd_attr.h"
 
 #ifdef __cplusplus
  extern "C" {
 #endif
 
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUH_ENDPOINT_MAX
+  #define CFG_TUH_ENDPOINT_MAX   (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3)
+//  #ifdef TUP_HCD_ENDPOINT_MAX
+//    #define CFG_TUH_ENDPPOINT_MAX   TUP_HCD_ENDPOINT_MAX
+//  #else
+//    #define
+//  #endif
+#endif
+
  //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
@@ -82,26 +94,14 @@ typedef struct
 
 } hcd_event_t;
 
-#if TUSB_OPT_HOST_ENABLED
-// Max number of endpoints per device
-enum {
-  // TODO better computation
-  HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3),
-  HCD_MAX_XFER     = HCD_MAX_ENDPOINT*2,
-};
-
-//#define HCD_MAX_ENDPOINT 16
-//#define HCD_MAX_XFER 16
-
-typedef struct {
+typedef struct
+{
   uint8_t rhport;
   uint8_t hub_addr;
   uint8_t hub_port;
   uint8_t speed;
 } hcd_devtree_info_t;
 
-#endif
-
 //--------------------------------------------------------------------+
 // Controller API
 //--------------------------------------------------------------------+

Некоторые файлы не были показаны из-за большого количества измененных файлов