ソースを参照

Merge remote-tracking branch 'upstream/master' into CCRX_Port

Wini-Buh 5 年 前
コミット
5a554508ca
100 ファイル変更1523 行追加1635 行削除
  1. 1 0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 1 1
      .github/workflows/build.yml
  3. 9 1
      CONTRIBUTORS.md
  4. 3 1
      README.md
  5. 70 9
      docs/changelog.md
  6. 27 0
      examples/device/CMakeLists.txt
  7. 28 37
      examples/device/audio_4_channel_mic/CMakeLists.txt
  8. 28 37
      examples/device/audio_test/CMakeLists.txt
  9. 24 25
      examples/device/board_test/CMakeLists.txt
  10. 28 37
      examples/device/cdc_dual_ports/CMakeLists.txt
  11. 2 1
      examples/device/cdc_dual_ports/src/tusb_config.h
  12. 29 38
      examples/device/cdc_msc/CMakeLists.txt
  13. 28 37
      examples/device/dfu/CMakeLists.txt
  14. 28 37
      examples/device/dfu_runtime/CMakeLists.txt
  15. 29 38
      examples/device/dynamic_configuration/CMakeLists.txt
  16. 28 37
      examples/device/hid_composite/CMakeLists.txt
  17. 28 37
      examples/device/hid_generic_inout/CMakeLists.txt
  18. 28 37
      examples/device/hid_multiple_interface/CMakeLists.txt
  19. 28 37
      examples/device/midi_test/CMakeLists.txt
  20. 29 38
      examples/device/msc_dual_lun/CMakeLists.txt
  21. 71 74
      examples/device/net_lwip_webserver/CMakeLists.txt
  22. 28 37
      examples/device/uac2_headset/CMakeLists.txt
  23. 29 38
      examples/device/usbtmc/CMakeLists.txt
  24. 28 37
      examples/device/webusb_serial/CMakeLists.txt
  25. 9 0
      examples/host/CMakeLists.txt
  26. 29 38
      examples/host/cdc_msc_hid/CMakeLists.txt
  27. 4 0
      hw/bsp/esp32s2/family.cmake
  28. 4 0
      hw/bsp/esp32s3/family.cmake
  29. 57 0
      hw/bsp/family_common.cmake
  30. 8 4
      hw/bsp/rp2040/board.h
  31. 1 1
      hw/bsp/rp2040/boards/adafruit_feather_rp2040/board.cmake
  32. 0 53
      hw/bsp/rp2040/boards/adafruit_feather_rp2040/board.h
  33. 1 1
      hw/bsp/rp2040/boards/adafruit_itsybitsy_rp2040/board.cmake
  34. 0 53
      hw/bsp/rp2040/boards/adafruit_itsybitsy_rp2040/board.h
  35. 0 1
      hw/bsp/rp2040/boards/adafruit_qt_rp2040/board.cmake
  36. 0 55
      hw/bsp/rp2040/boards/adafruit_qt_rp2040/board.h
  37. 1 0
      hw/bsp/rp2040/boards/adafruit_qtpy_rp2040/board.cmake
  38. 1 0
      hw/bsp/rp2040/boards/pico_sdk/board.cmake
  39. 1 1
      hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake
  40. 12 5
      hw/bsp/rp2040/family.c
  41. 150 73
      hw/bsp/rp2040/family.cmake
  42. 5 4
      src/class/audio/audio_device.c
  43. 0 4
      src/class/audio/audio_device.h
  44. 0 1
      src/class/bth/bth_device.c
  45. 3 1
      src/class/cdc/cdc_device.c
  46. 0 1
      src/class/cdc/cdc_device.h
  47. 5 3
      src/class/cdc/cdc_host.c
  48. 0 2
      src/class/cdc/cdc_host.h
  49. 1 1
      src/class/cdc/cdc_rndis_host.c
  50. 3 1
      src/class/dfu/dfu_device.c
  51. 0 2
      src/class/dfu/dfu_device.h
  52. 3 1
      src/class/dfu/dfu_rt_device.c
  53. 0 2
      src/class/dfu/dfu_rt_device.h
  54. 4 3
      src/class/hid/hid_device.c
  55. 0 2
      src/class/hid/hid_device.h
  56. 1 1
      src/class/hid/hid_host.c
  57. 0 7
      src/class/hid/hid_host.h
  58. 3 2
      src/class/midi/midi_device.c
  59. 0 3
      src/class/midi/midi_device.h
  60. 0 10
      src/class/msc/msc.h
  61. 4 3
      src/class/msc/msc_device.c
  62. 30 42
      src/class/msc/msc_device.h
  63. 5 7
      src/class/msc/msc_host.c
  64. 0 2
      src/class/msc/msc_host.h
  65. 3 1
      src/class/net/net_device.c
  66. 0 2
      src/class/net/net_device.h
  67. 2 6
      src/class/usbtmc/usbtmc_device.c
  68. 4 2
      src/class/vendor/vendor_device.c
  69. 0 1
      src/class/vendor/vendor_device.h
  70. 3 3
      src/class/vendor/vendor_host.c
  71. 0 7
      src/class/vendor/vendor_host.h
  72. 45 19
      src/common/tusb_common.h
  73. 0 2
      src/common/tusb_fifo.c
  74. 12 14
      src/common/tusb_fifo.h
  75. 1 0
      src/device/dcd.h
  76. 1 1
      src/device/usbd.c
  77. 2 2
      src/device/usbd.h
  78. 2 2
      src/device/usbd_pvt.h
  79. 4 18
      src/host/hcd.h
  80. 146 136
      src/host/hub.c
  81. 3 2
      src/host/hub.h
  82. 4 2
      src/host/usbh.c
  83. 1 8
      src/host/usbh.h
  84. 2 2
      src/host/usbh_control.c
  85. 78 91
      src/portable/ehci/ehci.c
  86. 5 40
      src/portable/ehci/ehci.h
  87. 0 1
      src/portable/espressif/esp32sx/dcd_esp32sx.c
  88. 0 1
      src/portable/microchip/samg/dcd_samg.c
  89. 0 1
      src/portable/nuvoton/nuc120/dcd_nuc120.c
  90. 0 1
      src/portable/nuvoton/nuc121/dcd_nuc121.c
  91. 0 1
      src/portable/nuvoton/nuc505/dcd_nuc505.c
  92. 145 165
      src/portable/ohci/ohci.c
  93. 1 17
      src/portable/ohci/ohci.h
  94. 0 2
      src/portable/raspberrypi/rp2040/dcd_rp2040.c
  95. 6 14
      src/portable/raspberrypi/rp2040/hcd_rp2040.c
  96. 35 3
      src/portable/raspberrypi/rp2040/rp2040_usb.c
  97. 41 3
      src/portable/raspberrypi/rp2040/rp2040_usb.h
  98. 0 1
      src/portable/sony/cxd56/dcd_cxd56.c
  99. 0 1
      src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
  100. 0 2
      src/portable/st/synopsys/dcd_synopsys.c

+ 1 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -11,6 +11,7 @@ assignees: ''
 
 - **PC OS** e.g Ubuntu 20.04 / Windows 10/ macOS 10.15
 - **Board** e.g Feather nRF52840 Express (if custom specify your MCUs)
+- **TinyUSB version** relase version or git hash (preferrably running with master for lastest code) 
 - **Firmware** e.g examples/device/cdc_msc
 
 **Describe The Bug**

+ 1 - 1
.github/workflows/build.yml

@@ -67,7 +67,7 @@ jobs:
     - name: Checkout pico-sdk
       if: matrix.family == 'rp2040'
       run: |
-        git clone --depth 1 https://github.com/raspberrypi/pico-sdk ~/pico-sdk
+        git clone --depth 1 -b develop https://github.com/raspberrypi/pico-sdk ~/pico-sdk
         echo >> $GITHUB_ENV PICO_SDK_PATH=~/pico-sdk
 
     - name: Set Toolchain URL

+ 9 - 1
CONTRIBUTORS.md

@@ -25,6 +25,10 @@
   - Improve Audio driver and add uac2_headset example
   - Improve STM32 Synopsys DCD with various PRs
 
+- **[J McCarthy](https://github.com/xmos-jmccarthy)**
+  - Add new DFU 1.1 class driver
+  - Add new example for dfu
+
 - **[Kamil Tomaszewski](https://github.com/kamtom480)**
   - Add new DCD port for **Sony CXD56** (spresnese board)
 
@@ -53,10 +57,14 @@
 
 - **[Raspberry Pi Team](https://github.com/raspberrypi)**
   - Add new DCD port for **Raspberry Pi RP2040**
+  - Add new HCD port for **Raspberry Pi RP2040**
 
 - **[Reinhard Panhuber](https://github.com/PanRe)**
   - Add new class driver for **USB Audio Class 2.0 (UAC2)**
-  - Enhance tu_fifo with unmasked pointer, which better support DMA
+  - Rework tu_fifo with unmasked pointer, add DMA support, and constant address support
+  - Add new DCD/USBD edpt_xfer_fifo() API for optimizing endpoint transfer
+  - Add and greatly improve Isochronous transfer
+  - Add new audio examples: audio_test and audio_4_channel_mic
 
 - **[Scott Shawcroft](https://github.com/tannewt)**
   - Add new DCD port for **SAMD21 and SAMD51**

+ 3 - 1
README.md

@@ -65,6 +65,8 @@ Supports multiple device configurations by dynamically changing usb descriptors.
 - Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
 - [WebUSB](https://github.com/WICG/webusb) with vendor-specific class
 
+If you have special need, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how RPi team add their reset interface [raspberrypi/pico-sdk#197](https://github.com/raspberrypi/pico-sdk/pull/197)
+
 ## Host Stack
 
 **Most active development is on the Device stack. The Host stack is under rework and largely untested.**
@@ -77,7 +79,7 @@ Supports multiple device configurations by dynamically changing usb descriptors.
 
 TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box.
 
-- **No OS** : Disabling USB IRQ is used as way to provide mutex
+- **No OS**
 - **FreeRTOS**
 - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) 
 

+ 70 - 9
docs/changelog.md

@@ -1,19 +1,80 @@
 # TinyUSB Changelog
 
-## WIP
+## 0.10.1 - 2021.06.03
 
-- Add new port Silabs EFM32GG12, board EFM32GG12 Thunderboard Kit (SLTB009A)
-- Add new port Renesas RX63N, board GR-CITRUS
-- MIDI
-  - Fix MIDI buffer overflow issue
+- rework rp2040 examples and CMake build, allow better integration with pico-sdk
+
+### Host Controller Driver (HCD)
+
+- Fix rp2040 host driver: incorrect PID with low speed device with max packet size of 8 bytes
+- Improve hub driver
+- Remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer()
+- Use hcd_frame_number() instead of micro frame
+- Fix OHCI endpoint address and xferred_bytes in xfer complete event
+
+## 0.10.0 - 2021.05.28
+
+- Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode
+- Improve audio_test example and add audio_4_channel_mic example
+- Add new dfu example
+- Remove pico-sdk from submodule
+
+### Device Controller Driver (DCD)
+
+- Add new DCD port for Silabs EFM32GG12 with board Thunderboard Kit (SLTB009A)
+- Add new DCD port Renesas RX63N, board GR-CITRUS
+- Add new (optional) endpoint API dcd_edpt_xfer_fifo 
+- Fix build with nRF5340
+- Fix build with lpc15 and lpc54
+- Fix build with lpc177x_8x
+- STM32 Synopsys: greatly improve Isochronous transfer with edpt_xfer_fifo API
+- Support LPC55 port1 highspeed
+- Add support for Espressif esp32s3
+- nRF: fix race condition that could cause drop packet of Bulk OUT transfer
+
+### USB Device Driver (USBD)
+
+- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo
+
+### Device Class Driver
+
+CDC
+
+- [Breaking] tud_cdc_peek(), tud_vendor_peek() no longer support random offset and dropped position parameter.
+
+DFU
+
+- Add new DFU 1.1 class driver (WIP)
+
+HID
+
+- Fix keyboard report descriptor template
+- Add more hid keys constant from 0x6B to 0xA4
+- [Breaking] rename API
+  - HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE
+  - tud_hid_boot_mode() to tud_hid_get_protocol()
+  - tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb()
+
+MIDI
+
+- Fix MIDI buffer overflow issue
+- [Breaking] rename API
   - Rename tud_midi_read() to tud_midi_stream_read()
   - Rename tud_midi_write() to tud_midi_stream_write()
   - Rename tud_midi_receive() to tud_midi_packet_read()
   - Rename tud_midi_send() to tud_midi_packet_write()
-- New board stm32f072-eval
-- Breaking changes
-  - tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek
-    at random offset.
+
+### Host Controller Driver (HCD)
+
+- No noticable changes
+
+### USB Host Driver (USBH)
+
+- No noticable changes
+
+### Host Class Driver
+
+- HID: Rework host hid driver, basically everything changes
 
 ## 0.9.0 - 2021.03.12
 

+ 27 - 0
examples/device/CMakeLists.txt

@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/${FAMILY}/family.cmake)
+
+project(tinyusb_device_examples)
+family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR})
+
+# family_add_subdirectory will filter what to actually add based on selected FAMILY
+family_add_subdirectory(audio_4_channel_mic)
+family_add_subdirectory(audio_test)
+family_add_subdirectory(board_test)
+family_add_subdirectory(cdc_dual_ports)
+family_add_subdirectory(cdc_msc)
+family_add_subdirectory(cdc_msc_freertos)
+family_add_subdirectory(dfu)
+family_add_subdirectory(dfu_runtime)
+family_add_subdirectory(dynamic_configuration)
+family_add_subdirectory(hid_composite)
+family_add_subdirectory(hid_composite_freertos)
+family_add_subdirectory(hid_generic_inout)
+family_add_subdirectory(hid_multiple_interface)
+family_add_subdirectory(midi_test)
+family_add_subdirectory(msc_dual_lun)
+family_add_subdirectory(net_lwip_webserver)
+family_add_subdirectory(uac2_headset)
+family_add_subdirectory(usbtmc)
+family_add_subdirectory(webusb_serial)

+ 28 - 37
examples/device/audio_4_channel_mic/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use BOARD-Directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 28 - 37
examples/device/audio_test/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use BOARD-Directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 24 - 25
examples/device/board_test/CMakeLists.txt

@@ -1,44 +1,43 @@
 cmake_minimum_required(VERSION 3.5)
 
-# use BOARD-Directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
 
 # Check for -DFAMILY=
 if(FAMILY MATCHES "^esp32s[2-3]")
-  cmake_minimum_required(VERSION 3.5)
+  # use BOARD-Directory name for project id
+  get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+  set(PROJECT ${BOARD}-${PROJECT})
+
+  # TOP is absolute path to root directory of TinyUSB git repo
+  set(TOP "../../..")
+  get_filename_component(TOP "${TOP}" REALPATH)
 
   include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
   project(${PROJECT})
 
-elseif(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
+else()
+
+  # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+  family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
   project(${PROJECT})
-  add_executable(${PROJECT})
 
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+  # 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/main.c
+          )
 
   # Example include
   target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
+          ${CMAKE_CURRENT_SOURCE_DIR}/src
+          )
 
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
+  # 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})
 endif()

+ 28 - 37
examples/device/cdc_dual_ports/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

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

@@ -64,8 +64,9 @@
   #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

+ 29 - 38
examples/device/cdc_msc/CMakeLists.txt

@@ -1,38 +1,29 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
-  )
-
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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/msc_disk.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})

+ 28 - 37
examples/device/dfu/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 28 - 37
examples/device/dfu_runtime/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 29 - 38
examples/device/dynamic_configuration/CMakeLists.txt

@@ -1,38 +1,29 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)  
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
-  )
-
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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/msc_disk.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})

+ 28 - 37
examples/device/hid_composite/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)  
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 28 - 37
examples/device/hid_generic_inout/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 28 - 37
examples/device/hid_multiple_interface/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 28 - 37
examples/device/midi_test/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 29 - 38
examples/device/msc_dual_lun/CMakeLists.txt

@@ -1,38 +1,29 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk_dual.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
-  )
-
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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/msc_disk_dual.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})

+ 71 - 74
examples/device/net_lwip_webserver/CMakeLists.txt

@@ -1,84 +1,81 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
+cmake_minimum_required(VERSION 3.5)
 
-# TOP is absolute path to root directory of TinyUSB git repo
 set(TOP "../../..")
 get_filename_component(TOP "${TOP}" REALPATH)
 
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
+if (EXISTS ${TOP}/lib/lwip/src)
+    include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
 
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+    # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+    family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
 
-  # lwip Stack source
-  set(SRC_LWIP
-    ${TOP}/lib/lwip/src/core/altcp.c
-    ${TOP}/lib/lwip/src/core/altcp_alloc.c
-    ${TOP}/lib/lwip/src/core/altcp_tcp.c
-    ${TOP}/lib/lwip/src/core/def.c
-    ${TOP}/lib/lwip/src/core/dns.c
-    ${TOP}/lib/lwip/src/core/inet_chksum.c
-    ${TOP}/lib/lwip/src/core/init.c
-    ${TOP}/lib/lwip/src/core/ip.c
-    ${TOP}/lib/lwip/src/core/mem.c
-    ${TOP}/lib/lwip/src/core/memp.c
-    ${TOP}/lib/lwip/src/core/netif.c
-    ${TOP}/lib/lwip/src/core/pbuf.c
-    ${TOP}/lib/lwip/src/core/raw.c
-    ${TOP}/lib/lwip/src/core/stats.c
-    ${TOP}/lib/lwip/src/core/sys.c
-    ${TOP}/lib/lwip/src/core/tcp.c
-    ${TOP}/lib/lwip/src/core/tcp_in.c
-    ${TOP}/lib/lwip/src/core/tcp_out.c
-    ${TOP}/lib/lwip/src/core/timeouts.c
-    ${TOP}/lib/lwip/src/core/udp.c
-    ${TOP}/lib/lwip/src/core/ipv4/autoip.c
-    ${TOP}/lib/lwip/src/core/ipv4/dhcp.c
-    ${TOP}/lib/lwip/src/core/ipv4/etharp.c
-    ${TOP}/lib/lwip/src/core/ipv4/icmp.c
-    ${TOP}/lib/lwip/src/core/ipv4/igmp.c
-    ${TOP}/lib/lwip/src/core/ipv4/ip4.c
-    ${TOP}/lib/lwip/src/core/ipv4/ip4_addr.c
-    ${TOP}/lib/lwip/src/core/ipv4/ip4_frag.c
-    ${TOP}/lib/lwip/src/netif/ethernet.c
-    ${TOP}/lib/lwip/src/netif/slipif.c
-    ${TOP}/lib/lwip/src/apps/http/httpd.c
-    ${TOP}/lib/lwip/src/apps/http/fs.c
-    ${TOP}/lib/networking/dhserver.c
-    ${TOP}/lib/networking/dnserver.c
-    ${TOP}/lib/networking/rndis_reports.c
-  )
+    project(${PROJECT})
 
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
-    ${SRC_LWIP}
-  )
+    # Checks this example is valid for the family and initializes the project
+    family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
 
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-    ${TOP}/lib/lwip/src/include
-    ${TOP}/lib/lwip/src/include/ipv4
-    ${TOP}/lib/lwip/src/include/lwip/apps
-    ${TOP}/lib/networking
-  )
+    add_executable(${PROJECT})
 
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-    PBUF_POOL_SIZE=2 
-    TCP_WND=2*TCP_MSS
-    HTTPD_USE_CUSTOM_FSDATA=0
-  )
+    # Example source
+    target_sources(${PROJECT} PUBLIC
+            ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+            ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+            )
 
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+    # Example include
+    target_include_directories(${PROJECT} PUBLIC
+            ${CMAKE_CURRENT_SOURCE_DIR}/src
+            ${TOP}/lib/lwip/src/include
+            ${TOP}/lib/lwip/src/include/ipv4
+            ${TOP}/lib/lwip/src/include/lwip/apps
+            ${TOP}/lib/networking
+            )
+
+    target_sources(${PROJECT} PUBLIC
+            ${TOP}/lib/lwip/src/core/altcp.c
+            ${TOP}/lib/lwip/src/core/altcp_alloc.c
+            ${TOP}/lib/lwip/src/core/altcp_tcp.c
+            ${TOP}/lib/lwip/src/core/def.c
+            ${TOP}/lib/lwip/src/core/dns.c
+            ${TOP}/lib/lwip/src/core/inet_chksum.c
+            ${TOP}/lib/lwip/src/core/init.c
+            ${TOP}/lib/lwip/src/core/ip.c
+            ${TOP}/lib/lwip/src/core/mem.c
+            ${TOP}/lib/lwip/src/core/memp.c
+            ${TOP}/lib/lwip/src/core/netif.c
+            ${TOP}/lib/lwip/src/core/pbuf.c
+            ${TOP}/lib/lwip/src/core/raw.c
+            ${TOP}/lib/lwip/src/core/stats.c
+            ${TOP}/lib/lwip/src/core/sys.c
+            ${TOP}/lib/lwip/src/core/tcp.c
+            ${TOP}/lib/lwip/src/core/tcp_in.c
+            ${TOP}/lib/lwip/src/core/tcp_out.c
+            ${TOP}/lib/lwip/src/core/timeouts.c
+            ${TOP}/lib/lwip/src/core/udp.c
+            ${TOP}/lib/lwip/src/core/ipv4/autoip.c
+            ${TOP}/lib/lwip/src/core/ipv4/dhcp.c
+            ${TOP}/lib/lwip/src/core/ipv4/etharp.c
+            ${TOP}/lib/lwip/src/core/ipv4/icmp.c
+            ${TOP}/lib/lwip/src/core/ipv4/igmp.c
+            ${TOP}/lib/lwip/src/core/ipv4/ip4.c
+            ${TOP}/lib/lwip/src/core/ipv4/ip4_addr.c
+            ${TOP}/lib/lwip/src/core/ipv4/ip4_frag.c
+            ${TOP}/lib/lwip/src/netif/ethernet.c
+            ${TOP}/lib/lwip/src/netif/slipif.c
+            ${TOP}/lib/lwip/src/apps/http/httpd.c
+            ${TOP}/lib/lwip/src/apps/http/fs.c
+            ${TOP}/lib/networking/dhserver.c
+            ${TOP}/lib/networking/dnserver.c
+            ${TOP}/lib/networking/rndis_reports.c
+            )
+
+    target_compile_definitions(${PROJECT} PUBLIC
+            PBUF_POOL_SIZE=2
+            TCP_WND=2*TCP_MSS
+            HTTPD_USE_CUSTOM_FSDATA=0
+            )
+
+    # 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})
+endif()

+ 28 - 37
examples/device/uac2_headset/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 29 - 38
examples/device/usbtmc/CMakeLists.txt

@@ -1,38 +1,29 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)  
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/usbtmc_app.c
-  )
-
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/usbtmc_app.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})

+ 28 - 37
examples/device/webusb_serial/CMakeLists.txt

@@ -1,37 +1,28 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # 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
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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})

+ 9 - 0
examples/host/CMakeLists.txt

@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/${FAMILY}/family.cmake)
+
+project(tinyusb_host_examples)
+family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
+
+# family_add_subdirectory will filter what to actually add based on selected FAMILY
+family_add_subdirectory(cdc_msc_hid)

+ 29 - 38
examples/host/cdc_msc_hid/CMakeLists.txt

@@ -1,38 +1,29 @@
-# use directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
-# TOP is absolute path to root directory of TinyUSB git repo
-set(TOP "../../..")
-get_filename_component(TOP "${TOP}" REALPATH)
-
-# Check for -DFAMILY=
-if(FAMILY STREQUAL "rp2040")
-  cmake_minimum_required(VERSION 3.12)
-  
-  include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
-  project(${PROJECT})
-  add_executable(${PROJECT})
-
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-
-  # Example source
-  target_sources(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
-  )
-
-  # Example include
-  target_include_directories(${PROJECT} PUBLIC
-    ${CMAKE_CURRENT_SOURCE_DIR}/src
-  )
-
-  # Example defines
-  target_compile_definitions(${PROJECT} PUBLIC
-    CFG_TUSB_OS=OPT_OS_PICO
-  )
-
-else()
-  message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
-endif()
+cmake_minimum_required(VERSION 3.5)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.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/hid_app.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.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})

+ 4 - 0
hw/bsp/esp32s2/family.cmake

@@ -4,3 +4,7 @@ cmake_minimum_required(VERSION 3.5)
 set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")  
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32s2)
+
+# include basic family CMake functionality
+set(FAMILY_MCUS ESP32S2)
+include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)

+ 4 - 0
hw/bsp/esp32s3/family.cmake

@@ -4,3 +4,7 @@ cmake_minimum_required(VERSION 3.5)
 set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components")  
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32s3)
+
+# include basic family CMake functionality
+set(FAMILY_MCUS ESP32S3)
+include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)

+ 57 - 0
hw/bsp/family_common.cmake

@@ -0,0 +1,57 @@
+if (NOT FAMILY_MCUS)
+    set(FAMILY_MCUS ${FAMILY})
+endif()
+
+# save it in case of re-inclusion
+set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "")
+
+function(family_filter RESULT DIR)
+    get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+    file(GLOB ONLYS "${DIR}/.only.MCU_*")
+    if (ONLYS)
+        foreach(MCU IN LISTS FAMILY_MCUS)
+            if (EXISTS ${DIR}/.only.MCU_${MCU})
+                set(${RESULT} 1 PARENT_SCOPE)
+                return()
+            endif()
+        endforeach()
+    else()
+        foreach(MCU IN LISTS FAMILY_MCUS)
+            if (EXISTS ${DIR}/.skip.MCU_${MCU})
+                set(${RESULT} 0 PARENT_SCOPE)
+                return()
+            endif()
+        endforeach()
+    endif()
+    set(${RESULT} 1 PARENT_SCOPE)
+endfunction()
+
+function(family_add_subdirectory DIR)
+    family_filter(SHOULD_ADD "${DIR}")
+    if (SHOULD_ADD)
+        add_subdirectory(${DIR})
+    endif()
+endfunction()
+
+function(family_get_project_name OUTPUT_NAME DIR)
+    get_filename_component(SHORT_NAME ${DIR} NAME)
+    set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
+endfunction()
+
+function(family_initialize_project PROJECT DIR)
+    family_filter(ALLOWED "${DIR}")
+    if (NOT ALLOWED)
+        get_filename_component(SHORT_NAME ${DIR} NAME)
+        message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}")
+    endif()
+endfunction()
+
+# configure an executable target to link to tinyusb in device mode, and add the board implementation
+function(family_configure_device_example TARGET)
+    # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
+endfunction()
+
+# configure an executable target to link to tinyusb in host mode, and add the board implementation
+function(family_configure_host_example TARGET)
+    # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
+endfunction()

+ 8 - 4
hw/bsp/rp2040/boards/raspberry_pi_pico/board.h → hw/bsp/rp2040/board.h

@@ -31,16 +31,20 @@
  extern "C" {
 #endif
 
+#ifdef PICO_DEFAULT_LED_PIN
 #define LED_PIN               PICO_DEFAULT_LED_PIN
-#define LED_STATE_ON          1
+#define LED_STATE_ON          (!(PICO_DEFAULT_LED_PIN_INVERTED))
+#endif
 
 // Button pin is BOOTSEL which is flash CS pin
 #define BUTTON_BOOTSEL
 #define BUTTON_STATE_ACTIVE   0
 
-#define UART_DEV              uart0
-#define UART_TX_PIN           0
-#define UART_RX_PIN           1
+#if defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN) && defined(PICO_DEFAULT_UART)
+#define UART_DEV              PICO_DEFAULT_UART
+#define UART_TX_PIN           PICO_DEFAULT_UART_TX_PIN
+#define UART_RX_PIN           PICO_DEFAULT_UART_RX_PIN
+#endif
 
 #ifdef __cplusplus
  }

+ 1 - 1
hw/bsp/rp2040/boards/adafruit_feather_rp2040/board.cmake

@@ -1 +1 @@
-set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_SDK_PATH}/src/rp2_common/boot_stage2/boot2_generic_03h.S")
+set(PICO_BOARD adafruit_feather_rp2040)

+ 0 - 53
hw/bsp/rp2040/boards/adafruit_feather_rp2040/board.h

@@ -1,53 +0,0 @@
-/* 
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef BOARD_H_
-#define BOARD_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#define LED_PIN               13
-#define LED_STATE_ON          1
-
-#define NEOPIXEL_PIN          16
-#define NEOPIXEL_POWER_PIN    17
-#define NEOPIXEL_POWER_STATE  1
-
-// Button pin is BOOTSEL which is flash CS pin
-#define BUTTON_BOOTSEL
-#define BUTTON_STATE_ACTIVE   0
-
-#define UART_DEV              uart0
-#define UART_TX_PIN           0
-#define UART_RX_PIN           1
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* BOARD_H_ */

+ 1 - 1
hw/bsp/rp2040/boards/adafruit_itsybitsy_rp2040/board.cmake

@@ -1 +1 @@
-set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_SDK_PATH}/src/rp2_common/boot_stage2/boot2_w25q080.S")
+set(PICO_BOARD adafruit_itsybitsy_rp2040)

+ 0 - 53
hw/bsp/rp2040/boards/adafruit_itsybitsy_rp2040/board.h

@@ -1,53 +0,0 @@
-/* 
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef BOARD_H_
-#define BOARD_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#define LED_PIN               11
-#define LED_STATE_ON          1
-
-#define NEOPIXEL_PIN          17
-#define NEOPIXEL_POWER_PIN    16
-#define NEOPIXEL_POWER_STATE  1
-
-// Button pin is BOOTSEL which is flash CS pin
-#define BUTTON_BOOTSEL
-#define BUTTON_STATE_ACTIVE   0
-
-#define UART_DEV              uart0
-#define UART_TX_PIN           0
-#define UART_RX_PIN           1
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* BOARD_H_ */

+ 0 - 1
hw/bsp/rp2040/boards/adafruit_qt_rp2040/board.cmake

@@ -1 +0,0 @@
-set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_SDK_PATH}/src/rp2_common/boot_stage2/boot2_w25q080.S")

+ 0 - 55
hw/bsp/rp2040/boards/adafruit_qt_rp2040/board.h

@@ -1,55 +0,0 @@
-/* 
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef BOARD_H_
-#define BOARD_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// TODO QT RP2040 only has neopixel
-#define LED_PIN               11
-#define LED_STATE_ON          1
-
-#define NEOPIXEL_PIN          12
-#define NEOPIXEL_POWER_PIN    11
-#define NEOPIXEL_POWER_STATE  1
-
-// Button pin is BOOTSEL which is flash CS pin
-#define BUTTON_BOOTSEL
-#define BUTTON_STATE_ACTIVE   0
-
-
-#define UART_DEV              uart0
-#define UART_TX_PIN           0
-#define UART_RX_PIN           1
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* BOARD_H_ */

+ 1 - 0
hw/bsp/rp2040/boards/adafruit_qtpy_rp2040/board.cmake

@@ -0,0 +1 @@
+set(PICO_BOARD adafruit_qtpy_rp2040)

+ 1 - 0
hw/bsp/rp2040/boards/pico_sdk/board.cmake

@@ -0,0 +1 @@
+# This builds with settings based purely on the current PICO_BOARD set via the SDK

+ 1 - 1
hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake

@@ -1 +1 @@
-set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_SDK_PATH}/src/rp2_common/boot_stage2/boot2_w25q080.S")
+set(PICO_BOARD pico)

+ 12 - 5
hw/bsp/rp2040/family.c

@@ -26,6 +26,7 @@
  */
 
 #include "pico/stdlib.h"
+#include "pico/binary_info.h"
 #include "hardware/gpio.h"
 #include "hardware/sync.h"
 #include "hardware/structs/ioqspi.h"
@@ -110,10 +111,14 @@ void stdio_rtt_init(void)
 
 #endif
 
+#ifdef UART_DEV
+static uart_inst_t *uart_inst;
+#endif
 
 void board_init(void)
 {
 #ifdef LED_PIN
+  bi_decl(bi_1pin_with_name(LED_PIN, "LED"));
   gpio_init(LED_PIN);
   gpio_set_dir(LED_PIN, GPIO_OUT);
 #endif
@@ -122,8 +127,10 @@ void board_init(void)
 #ifndef BUTTON_BOOTSEL
 #endif
 
-#ifdef UART_DEV
-  stdio_uart_init_full(UART_DEV, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, UART_RX_PIN);
+#if defined(UART_DEV) && defined(LIB_PICO_STDIO_UART)
+  bi_decl(bi_2pins_with_func(UART_TX_PIN, UART_TX_PIN, GPIO_FUNC_UART));
+  uart_inst = uart_get_instance(UART_DEV);
+  stdio_uart_init_full(uart_inst, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, UART_RX_PIN);
 #endif
 
 #if defined(LOGGER_RTT)
@@ -164,7 +171,7 @@ int board_uart_read(uint8_t* buf, int len)
 {
 #ifdef UART_DEV
   for(int i=0;i<len;i++) {
-    buf[i] = uart_getc(UART_DEV);
+    buf[i] = uart_getc(uart_inst);
   }
   return len;
 #else
@@ -175,9 +182,9 @@ int board_uart_read(uint8_t* buf, int len)
 int board_uart_write(void const * buf, int len)
 {
 #ifdef UART_DEV
-  char const* bufch = (uint8_t const*) buf;
+  char const* bufch = (char const*) buf;
   for(int i=0;i<len;i++) {
-    uart_putc(UART_DEV, bufch[i]);
+    uart_putc(uart_inst, bufch[i]);
   }
   return len;
 #else

+ 150 - 73
hw/bsp/rp2040/family.cmake

@@ -1,77 +1,154 @@
-# Board specific define e.g boot stage2
-# PICO_DEFAULT_BOOT_STAGE2_FILE must be set before pico_sdk_init()
-include(${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake)
-
-pico_sdk_init()
-
-target_link_libraries(${PROJECT}
-  pico_stdlib
-  pico_bootsel_via_double_reset
-  pico_fix_rp2040_usb_device_enumeration
-)
-
-pico_add_extra_outputs(${PROJECT})
-pico_enable_stdio_uart(${PROJECT} 1)
-
-# TinyUSB Stack source
-set(SRC_TINYUSB
-	${TOP}/src/tusb.c
-	${TOP}/src/common/tusb_fifo.c
-	${TOP}/src/device/usbd.c
-	${TOP}/src/device/usbd_control.c
-	${TOP}/src/class/audio/audio_device.c
-	${TOP}/src/class/cdc/cdc_device.c
-	${TOP}/src/class/dfu/dfu_device.c
-	${TOP}/src/class/dfu/dfu_rt_device.c
-	${TOP}/src/class/hid/hid_device.c
-	${TOP}/src/class/midi/midi_device.c
-	${TOP}/src/class/msc/msc_device.c
-	${TOP}/src/class/net/net_device.c
-	${TOP}/src/class/usbtmc/usbtmc_device.c
-	${TOP}/src/class/vendor/vendor_device.c
-	${TOP}/src/host/hub.c
-	${TOP}/src/host/usbh.c
-	${TOP}/src/host/usbh_control.c
-	${TOP}/src/class/cdc/cdc_host.c
-	${TOP}/src/class/hid/hid_host.c
-	${TOP}/src/class/msc/msc_host.c
-	${TOP}/src/portable/raspberrypi/${FAMILY}/rp2040_usb.c
-	${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c
-	${TOP}/src/portable/raspberrypi/${FAMILY}/hcd_rp2040.c
-)
-
-target_sources(${PROJECT} PUBLIC
-  ${TOP}/hw/bsp/${FAMILY}/family.c
-  ${SRC_TINYUSB}
-)
-
-target_include_directories(${PROJECT} PUBLIC
-  ${TOP}/hw
-  ${TOP}/src
-  ${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}
-)
-
-target_compile_definitions(${PROJECT} PUBLIC
-  CFG_TUSB_MCU=OPT_MCU_RP2040
-  PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1
-)
-
-if(DEFINED LOG)
-  target_compile_definitions(${PROJECT} PUBLIC CFG_TUSB_DEBUG=${LOG} )
-endif()
+cmake_minimum_required(VERSION 3.13)
+if (NOT TARGET _rp2040_family_inclusion_marker)
+	add_library(_rp2040_family_inclusion_marker INTERFACE)
 
-if(LOGGER STREQUAL "rtt")
-  target_compile_definitions(${PROJECT} PUBLIC
-    LOGGER_RTT
-    SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
-  )
+	if (NOT BOARD)
+		message(FATAL_ERROR "BOARD must be specified")
+	endif()
 
-  target_sources(${PROJECT} PUBLIC
-    ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c
-  )
+	# add the SDK in case we are standalone tinyusb example (noop if already present)
+	include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_import.cmake)
 
-  target_include_directories(${PROJECT} PUBLIC
-    ${TOP}/lib/SEGGER_RTT/RTT
-  )
-endif()
+	# include basic family CMake functionality
+	set(FAMILY_MCUS RP2040)
+	include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)
+
+	include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+	# TOP is absolute path to root directory of TinyUSB git repo
+	set(TOP "${CMAKE_CURRENT_LIST_DIR}/../../..")
+	get_filename_component(TOP "${TOP}" REALPATH)
+
+	if (NOT PICO_TINYUSB_PATH)
+		set(PICO_TINYUSB_PATH ${TOP})
+	endif()
+
+	# Base config for both device and host; wrapped by SDK's tinyusb_common
+	add_library(tinyusb_common_base INTERFACE)
+	
+	target_sources(tinyusb_common_base INTERFACE
+			${TOP}/src/tusb.c
+			${TOP}/src/common/tusb_fifo.c
+			)
+
+	target_include_directories(tinyusb_common_base INTERFACE
+			${TOP}/src
+			${TOP}/src/common
+			${TOP}/hw
+			)
+
+	target_link_libraries(tinyusb_common_base INTERFACE
+			hardware_structs
+			hardware_irq
+			hardware_resets
+			pico_sync
+			)
+
+	set(TINYUSB_DEBUG_LEVEL 0)
+	if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+		message("Compiling TinyUSB with CFG_TUSB_DEBUG=1")
+		set(TINYUSB_DEBUG_LEVEL 1)
+	endif ()
+	
+	target_compile_definitions(tinyusb_common_base INTERFACE
+			CFG_TUSB_MCU=OPT_MCU_RP2040
+			CFG_TUSB_OS=OPT_OS_PICO
+			CFG_TUSB_DEBUG=${TINYUSB_DEBUG_LEVEL}
+	)
+
+	# Base config for device mode; wrapped by SDK's tinyusb_device
+	add_library(tinyusb_device_base INTERFACE)
+	target_sources(tinyusb_device_base INTERFACE
+			${TOP}/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+			${TOP}/src/portable/raspberrypi/rp2040/rp2040_usb.c
+			${TOP}/src/device/usbd.c
+			${TOP}/src/device/usbd_control.c
+			${TOP}/src/class/audio/audio_device.c
+			${TOP}/src/class/cdc/cdc_device.c
+			${TOP}/src/class/dfu/dfu_device.c
+			${TOP}/src/class/dfu/dfu_rt_device.c
+			${TOP}/src/class/hid/hid_device.c
+			${TOP}/src/class/midi/midi_device.c
+			${TOP}/src/class/msc/msc_device.c
+			${TOP}/src/class/net/net_device.c
+			${TOP}/src/class/usbtmc/usbtmc_device.c
+			${TOP}/src/class/vendor/vendor_device.c
+			)
+
+
+	# Base config for host mode; wrapped by SDK's tinyusb_host
+	add_library(tinyusb_host_base INTERFACE)
+	target_sources(tinyusb_host_base INTERFACE
+			${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
+			${TOP}/src/class/msc/msc_host.c
+			${TOP}/src/class/vendor/vendor_host.c
+			)
 
+	# Sometimes have to do host specific actions in mostly
+	# common functions
+	target_compile_definitions(tinyusb_host_base INTERFACE
+			RP2040_USB_HOST_MODE=1
+	)
+
+	add_library(tinyusb_bsp INTERFACE)
+	target_sources(tinyusb_bsp INTERFACE
+			${TOP}/hw/bsp/rp2040/family.c
+			)
+#	target_include_directories(tinyusb_bsp INTERFACE
+#			${TOP}/hw/bsp/rp2040)
+
+	# tinyusb_additions will hold our extra settings for examples
+	add_library(tinyusb_additions INTERFACE)
+
+	target_compile_definitions(tinyusb_additions INTERFACE
+		PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1
+	)
+
+	if(DEFINED LOG)
+	  target_compile_definitions(tinyusb_additions INTERFACE CFG_TUSB_DEBUG=${LOG} )
+	endif()
+
+	if(LOGGER STREQUAL "rtt")
+	  target_compile_definitions(tinyusb_additions INTERFACE
+		LOGGER_RTT
+		SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
+	  )
+
+	  target_sources(tinyusb_additions INTERFACE
+		${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c
+	  )
+
+	  target_include_directories(tinyusb_additions INTERFACE
+		${TOP}/lib/SEGGER_RTT/RTT
+	  )
+	endif()
+
+	function(family_configure_target TARGET)
+		pico_add_extra_outputs(${TARGET})
+		pico_enable_stdio_uart(${TARGET} 1)
+		target_link_libraries(${TARGET} PUBLIC pico_stdlib pico_bootsel_via_double_reset tinyusb_board tinyusb_additions)
+	endfunction()
+
+	function(family_configure_device_example TARGET)
+		family_configure_target(${TARGET})
+		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device)
+	endfunction()
+
+	function(family_configure_host_example TARGET)
+		family_configure_target(${TARGET})
+		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_host)
+	endfunction()
+
+	function(family_initialize_project PROJECT DIR)
+		# call the original version of this function from family_common.cmake
+		_family_initialize_project(${PROJECT} ${DIR})
+		enable_language(C CXX ASM)
+		pico_sdk_init()
+	endfunction()
+endif()

+ 5 - 4
src/class/audio/audio_device.c

@@ -55,9 +55,10 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
+
 #include "audio_device.h"
-//#include "common/tusb_fifo.h"
 
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
@@ -548,7 +549,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t
   TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false);
 #else
   // Data is already placed in EP FIFO, schedule for next receive
-  TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false);
+  TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false);
 #endif
 
 #endif
@@ -852,7 +853,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio)
   TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
 #else
   // Send everything in ISO EP FIFO
-  TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx));
+  TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx));
 #endif
 
 #endif
@@ -1611,7 +1612,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
 #if USE_LINEAR_BUFFER_RX
             TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false);
 #else
-            TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false);
+            TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false);
 #endif
           }
 

+ 0 - 4
src/class/audio/audio_device.h

@@ -28,10 +28,6 @@
 #ifndef _TUSB_AUDIO_DEVICE_H_
 #define _TUSB_AUDIO_DEVICE_H_
 
-#include "assert.h"
-#include "common/tusb_common.h"
-#include "device/usbd.h"
-
 #include "audio.h"
 
 //--------------------------------------------------------------------+

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

@@ -32,7 +32,6 @@
 // INCLUDE
 //--------------------------------------------------------------------+
 #include "bth_device.h"
-#include <common/tusb_types.h>
 #include <device/usbd_pvt.h>
 
 //--------------------------------------------------------------------+

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

@@ -28,9 +28,11 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC)
 
-#include "cdc_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "cdc_device.h"
+
 #if defined(TU_HAS_NO_ATTR_WEAK)
 static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB;
 static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB;

+ 0 - 1
src/class/cdc/cdc_device.h

@@ -28,7 +28,6 @@
 #define _TUSB_CDC_DEVICE_H_
 
 #include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "cdc.h"
 
 //--------------------------------------------------------------------+

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

@@ -28,7 +28,7 @@
 
 #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC)
 
-#include "common/tusb_common.h"
+#include "host/usbh.h"
 #include "cdc_host.h"
 
 //--------------------------------------------------------------------+
@@ -96,24 +96,26 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr)
 
 bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify)
 {
+  (void) is_notify;
   TU_VERIFY( tuh_cdc_mounted(dev_addr) );
   TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
 
   uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
   if ( hcd_edpt_busy(dev_addr, ep_out) ) return false;
 
-  return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify);
+  return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length);
 }
 
 bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
 {
+  (void) is_notify;
   TU_VERIFY( tuh_cdc_mounted(dev_addr) );
   TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
 
   uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
   if ( hcd_edpt_busy(dev_addr, ep_in) ) return false;
 
-  return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify);
+  return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length);
 }
 
 bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb)

+ 0 - 2
src/class/cdc/cdc_host.h

@@ -27,8 +27,6 @@
 #ifndef _TUSB_CDC_HOST_H_
 #define _TUSB_CDC_HOST_H_
 
-#include "common/tusb_common.h"
-#include "host/usbh.h"
 #include "cdc.h"
 
 #ifdef __cplusplus

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

@@ -239,7 +239,7 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da
   if ( TUSB_ERROR_NONE != error )   STASK_RETURN(error);
 
   //------------- waiting for Response Available notification -------------//
-  (void) hcd_pipe_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8, true);
+  (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8);
   osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error);
   if ( TUSB_ERROR_NONE != error )   STASK_RETURN(error);
   STASK_ASSERT(msg_notification[dev_addr-1][0] == 1);

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

@@ -28,9 +28,11 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE)
 
-#include "dfu_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "dfu_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+

+ 0 - 2
src/class/dfu/dfu_device.h

@@ -27,8 +27,6 @@
 #ifndef _TUSB_DFU_DEVICE_H_
 #define _TUSB_DFU_DEVICE_H_
 
-#include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "dfu.h"
 
 #ifdef __cplusplus

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

@@ -28,9 +28,11 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME)
 
-#include "dfu_rt_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "dfu_rt_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+

+ 0 - 2
src/class/dfu/dfu_rt_device.h

@@ -27,8 +27,6 @@
 #ifndef _TUSB_DFU_RT_DEVICE_H_
 #define _TUSB_DFU_RT_DEVICE_H_
 
-#include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "dfu.h"
 
 #ifdef __cplusplus

+ 4 - 3
src/class/hid/hid_device.c

@@ -31,10 +31,11 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
-#include "common/tusb_common.h"
-#include "hid_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "hid_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
@@ -224,7 +225,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1
   {
     if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) )
     {
-      TU_LOG1_FAILED();
+      TU_LOG_FAILED();
       TU_BREAKPOINT();
     }
   }

+ 0 - 2
src/class/hid/hid_device.h

@@ -27,8 +27,6 @@
 #ifndef _TUSB_HID_DEVICE_H_
 #define _TUSB_HID_DEVICE_H_
 
-#include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "hid.h"
 
 #ifdef __cplusplus

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

@@ -28,7 +28,7 @@
 
 #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID)
 
-#include "common/tusb_common.h"
+#include "host/usbh.h"
 #include "hid_host.h"
 
 //--------------------------------------------------------------------+

+ 0 - 7
src/class/hid/hid_host.h

@@ -24,14 +24,9 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \addtogroup ClassDriver_HID
- *  @{ */
-
 #ifndef _TUSB_HID_HOST_H_
 #define _TUSB_HID_HOST_H_
 
-#include "common/tusb_common.h"
-#include "host/usbh.h"
 #include "hid.h"
 
 #ifdef __cplusplus
@@ -134,5 +129,3 @@ void hidh_close(uint8_t dev_addr);
 #endif
 
 #endif /* _TUSB_HID_HOST_H_ */
-
-/** @} */ // ClassDriver_HID

+ 3 - 2
src/class/midi/midi_device.c

@@ -31,10 +31,11 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
-#include "midi_device.h"
-#include "class/audio/audio.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "midi_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+

+ 0 - 3
src/class/midi/midi_device.h

@@ -27,9 +27,6 @@
 #ifndef _TUSB_MIDI_DEVICE_H_
 #define _TUSB_MIDI_DEVICE_H_
 
-#include "common/tusb_common.h"
-#include "device/usbd.h"
-
 #include "class/audio/audio.h"
 #include "midi.h"
 

+ 0 - 10
src/class/msc/msc.h

@@ -24,13 +24,6 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \ingroup group_class
- *  \defgroup ClassDriver_MSC MassStorage (MSC)
- *  @{ */
-
-/**  \defgroup ClassDriver_MSC_Common Common Definitions
- *  @{ */
-
 #ifndef _TUSB_MSC_H_
 #define _TUSB_MSC_H_
 
@@ -387,6 +380,3 @@ TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct");
 #endif
 
 #endif /* _TUSB_MSC_H_ */
-
-/// @}
-/// @}

+ 4 - 3
src/class/msc/msc_device.c

@@ -28,11 +28,12 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC)
 
-#include "common/tusb_common.h"
-#include "msc_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 #include "device/dcd.h"         // for faking dcd_event_xfer_complete
 
+#include "msc_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
@@ -171,7 +172,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
   // Prepare for Command Block Wrapper
   if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) )
   {
-    TU_LOG1_FAILED();
+    TU_LOG_FAILED();
     TU_BREAKPOINT();
   }
 

+ 30 - 42
src/class/msc/msc_device.h

@@ -28,7 +28,6 @@
 #define _TUSB_MSC_DEVICE_H_
 
 #include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "msc.h"
 
 #ifdef __cplusplus
@@ -51,53 +50,45 @@
 
 TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct");
 
-/** \addtogroup ClassDriver_MSC
- *  @{
- * \defgroup MSC_Device Device
- *  @{ */
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
 
+// Set SCSI sense response
 bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier);
 
 //--------------------------------------------------------------------+
 // Application Callbacks (WEAK is optional)
 //--------------------------------------------------------------------+
 
-/**
- * Invoked when received \ref SCSI_CMD_READ_10 command
- * \param[in]   lun         Logical unit number
- * \param[in]   lba         Logical Block Address to be read
- * \param[in]   offset      Byte offset from LBA
- * \param[out]  buffer      Buffer which application need to update with the response data.
- * \param[in]   bufsize     Requested bytes
- *
- * \return      Number of byte read, if it is less than requested bytes by \a \b bufsize. Tinyusb will transfer
- *              this amount first and invoked this again for remaining data.
- *
- * \retval      zero        Indicate application is not ready yet to response e.g disk I/O is not complete.
- *                          tinyusb will invoke this callback with the same parameters again some time later.
- *
- * \retval      negative    Indicate error e.g reading disk I/O. tinyusb will \b STALL the corresponding
- *                          endpoint and return failed status in command status wrapper phase.
- */
+// Invoked when received SCSI READ10 command
+// - Address = lba * BLOCK_SIZE + offset
+//   - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
+//
+// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If
+//   - read < bufsize : These bytes are transferred first and callback invoked again for remaining data.
+//
+//   - read == 0      : Indicate application is not ready yet e.g disk I/O busy.
+//                      Callback invoked again with the same parameters later on.
+//
+//   - read < 0       : Indicate application error e.g invalid address. This request will be STALLed
+//                      and return failed status in command status wrapper phase.
 int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
 
-/**
- * Invoked when received \ref SCSI_CMD_WRITE_10 command
- * \param[in]   lun         Logical unit number
- * \param[in]   lba         Logical Block Address to be write
- * \param[in]   offset      Byte offset from LBA
- * \param[out]  buffer      Buffer which holds written data.
- * \param[in]   bufsize     Requested bytes
- *
- * \return      Number of byte written, if it is less than requested bytes by \a \b bufsize. Tinyusb will proceed with
- *              other work and invoked this again with adjusted parameters.
- *
- * \retval      zero        Indicate application is not ready yet e.g disk I/O is not complete.
- *                          Tinyusb will invoke this callback with the same parameters again some time later.
- *
- * \retval      negative    Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding
- *                          endpoint and return failed status in command status wrapper phase.
- */
+// Invoked when received SCSI WRITE10 command
+// - Address = lba * BLOCK_SIZE + offset
+//   - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
+//
+// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If
+//   - write < bufsize : callback invoked again with remaining data later on.
+//
+//   - write == 0      : Indicate application is not ready yet e.g disk I/O busy.
+//                       Callback invoked again with the same parameters later on.
+//
+//   - write < 0       : Indicate application error e.g invalid address. This request will be STALLed
+//                       and return failed status in command status wrapper phase.
+//
+// TODO change buffer to const uint8_t*
 int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
 
 // Invoked when received SCSI_CMD_INQUIRY
@@ -152,9 +143,6 @@ TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[1
 // Hook to make a mass storage device read-only. TODO remove
 TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
 
-/** @} */
-/** @} */
-
 //--------------------------------------------------------------------+
 // Internal Class Driver API
 //--------------------------------------------------------------------+

+ 5 - 7
src/class/msc/msc_host.c

@@ -28,10 +28,7 @@
 
 #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC
 
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "common/tusb_common.h"
+#include "host/usbh.h"
 #include "msc_host.h"
 
 //--------------------------------------------------------------------+
@@ -74,7 +71,8 @@ CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX]
 
 // buffer used to read scsi information when mounted
 // largest response data currently is inquiry TODO Inquiry is not part of enum anymore
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
+CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4)
+static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
 
 static inline msch_interface_t* get_itf(uint8_t dev_addr)
 {
@@ -441,7 +439,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
   {
     // Unit is ready, read its capacity
     TU_LOG2("SCSI Read Capacity\r\n");
-    tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete);
+    tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete);
   }else
   {
     // Note: During enumeration, some device fails Test Unit Ready and require a few retries
@@ -468,7 +466,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw
   msch_interface_t* p_msc = get_itf(dev_addr);
 
   // Capacity response field: Block size and Last LBA are both Big-Endian
-  scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer;
+  scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer);
   p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
   p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
 

+ 0 - 2
src/class/msc/msc_host.h

@@ -27,8 +27,6 @@
 #ifndef _TUSB_MSC_HOST_H_
 #define _TUSB_MSC_HOST_H_
 
-#include "common/tusb_common.h"
-#include "host/usbh.h"
 #include "msc.h"
 
 #ifdef __cplusplus

+ 3 - 1
src/class/net/net_device.c

@@ -29,8 +29,10 @@
 
 #if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET )
 
-#include "net_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
+
+#include "net_device.h"
 #include "rndis_protocol.h"
 
 void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */

+ 0 - 2
src/class/net/net_device.h

@@ -28,8 +28,6 @@
 #ifndef _TUSB_NET_DEVICE_H_
 #define _TUSB_NET_DEVICE_H_
 
-#include "common/tusb_common.h"
-#include "device/usbd.h"
 #include "class/cdc/cdc.h"
 
 /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */

+ 2 - 6
src/class/usbtmc/usbtmc_device.c

@@ -77,15 +77,11 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC)
 
-#include <string.h>
-#include "usbtmc.h"
-#include "usbtmc_device.h"
 #include "device/usbd.h"
-#include "osal/osal.h"
-
-// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy
 #include "device/usbd_pvt.h"
 
+#include "usbtmc_device.h"
+
 #ifdef xDEBUG
 #include "uart_util.h"
 static char logMsg[150];

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

@@ -28,9 +28,11 @@
 
 #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR)
 
-#include "vendor_device.h"
+#include "device/usbd.h"
 #include "device/usbd_pvt.h"
 
+#include "vendor_device.h"
+
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
@@ -193,7 +195,7 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui
   // Prepare for incoming data
   if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) )
   {
-    TU_LOG1_FAILED();
+    TU_LOG_FAILED();
     TU_BREAKPOINT();
   }
 

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

@@ -28,7 +28,6 @@
 #define _TUSB_VENDOR_DEVICE_H_
 
 #include "common/tusb_common.h"
-#include "device/usbd.h"
 
 #ifndef CFG_TUD_VENDOR_EPSIZE
 #define CFG_TUD_VENDOR_EPSIZE     64

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

@@ -31,7 +31,7 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
-#include "common/tusb_common.h"
+#include "host/usbh.h"
 #include "vendor_host.h"
 
 //--------------------------------------------------------------------+
@@ -66,7 +66,7 @@ tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t pr
     return TUSB_ERROR_INTERFACE_IS_BUSY;
   }
 
-  (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length, true);
+  (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length);
 
   return TUSB_ERROR_NONE;
 }
@@ -80,7 +80,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p
     return TUSB_ERROR_INTERFACE_IS_BUSY;
   }
 
-  (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length, true);
+  (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length);
 
   return TUSB_ERROR_NONE;
 }

+ 0 - 7
src/class/vendor/vendor_host.h

@@ -24,15 +24,10 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \ingroup group_class
- *  \defgroup Group_Custom Custom Class (not supported yet)
- *  @{ */
-
 #ifndef _TUSB_VENDOR_HOST_H_
 #define _TUSB_VENDOR_HOST_H_
 
 #include "common/tusb_common.h"
-#include "host/usbh.h"
 
 #ifdef __cplusplus
  extern "C" {
@@ -70,5 +65,3 @@ void         cush_close(uint8_t dev_addr);
 #endif
 
 #endif /* _TUSB_VENDOR_HOST_H_ */
-
-/** @} */

+ 45 - 19
src/common/tusb_common.h

@@ -24,10 +24,6 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \ingroup Group_Common
- *  \defgroup Group_CommonH common.h
- *  @{ */
-
 #ifndef _TUSB_COMMON_H_
 #define _TUSB_COMMON_H_
 
@@ -72,10 +68,11 @@
 #include "tusb_option.h"
 #include "tusb_compiler.h"
 #include "tusb_verify.h"
-#include "tusb_error.h" // TODO remove
-#include "tusb_timeout.h"
 #include "tusb_types.h"
 
+#include "tusb_error.h"   // TODO remove
+#include "tusb_timeout.h" // TODO remove
+
 //------------- Mem -------------//
 #define tu_memclr(buffer, size)  memset((buffer), 0, (size))
 #define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
@@ -287,8 +284,9 @@ TU_ATTR_ALWAYS_INLINE static inline void     tu_unaligned_write16 (void* mem, ui
 
 // CFG_TUSB_DEBUG for debugging
 // 0 : no debug
-// 1 : print when there is error
-// 2 : print out log
+// 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);
@@ -306,25 +304,39 @@ 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 debug level 1
+// Log with Level
+#define TU_LOG(n, ...)        TU_LOG##n(__VA_ARGS__)
+#define TU_LOG_MEM(n, ...)    TU_LOG##n##_MEM(__VA_ARGS__)
+#define TU_LOG_VAR(n, ...)    TU_LOG##n##_VAR(__VA_ARGS__)
+#define TU_LOG_INT(n, ...)    TU_LOG##n##_INT(__VA_ARGS__)
+#define TU_LOG_HEX(n, ...)    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\n", (uint32_t) (_x) )
 #define TU_LOG1_HEX(_x)       tu_printf(#_x " = %lX\n", (uint32_t) (_x) )
-#define TU_LOG1_LOCATION()    tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
-#define TU_LOG1_FAILED()      tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
 
-// Log with debug level 2
-#if CFG_TUSB_DEBUG > 1
+// 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
-  #define TU_LOG2_LOCATION()  TU_LOG1_LOCATION()
 #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
 {
@@ -350,14 +362,23 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
 
 #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)
 #ifndef TU_LOG1
   #define TU_LOG1(...)
   #define TU_LOG1_MEM(...)
   #define TU_LOG1_VAR(...)
   #define TU_LOG1_INT(...)
   #define TU_LOG1_HEX(...)
-  #define TU_LOG1_LOCATION()
-  #define TU_LOG1_FAILED()
 #endif
 
 #ifndef TU_LOG2
@@ -366,7 +387,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
   #define TU_LOG2_VAR(...)
   #define TU_LOG2_INT(...)
   #define TU_LOG2_HEX(...)
-  #define TU_LOG2_LOCATION()
+#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
@@ -374,5 +402,3 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
 #endif
 
 #endif /* _TUSB_COMMON_H_ */
-
-/**  @} */

+ 0 - 2
src/common/tusb_fifo.c

@@ -25,8 +25,6 @@
  * This file is part of the TinyUSB stack.
  */
 
-#include <string.h>
-
 #include "osal/osal.h"
 #include "tusb_fifo.h"
 

+ 12 - 14
src/common/tusb_fifo.h

@@ -28,6 +28,10 @@
 #ifndef _TUSB_FIFO_H_
 #define _TUSB_FIFO_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Due to the use of unmasked pointers, this FIFO does not suffer from loosing
 // one item slice. Furthermore, write and read operations are completely
 // decoupled as write and read functions do not modify a common state. Henceforth,
@@ -37,25 +41,17 @@
 // read pointers can be updated from within a DMA ISR. Overflows are detectable
 // within a certain number (see tu_fifo_overflow()).
 
+#include "common/tusb_common.h"
+
 // mutex is only needed for RTOS
 // for OS None, we don't get preempted
 #define CFG_FIFO_MUTEX      (CFG_TUSB_OS != OPT_OS_NONE)
 
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #if CFG_FIFO_MUTEX
 #include "osal/osal.h"
 #define tu_fifo_mutex_t  osal_mutex_t
 #endif
 
-/** \struct tu_fifo_t
- * \brief Simple Circular FIFO
- */
 typedef struct
 {
   uint8_t* buffer               ; ///< buffer pointer
@@ -104,7 +100,8 @@ bool tu_fifo_clear(tu_fifo_t *f);
 bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
 
 #if CFG_FIFO_MUTEX
-static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl)
+TU_ATTR_ALWAYS_INLINE static inline
+void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl)
 {
   f->mutex_wr = write_mutex_hdl;
   f->mutex_rd = read_mutex_hdl;
@@ -129,15 +126,16 @@ uint16_t tu_fifo_remaining              (tu_fifo_t* f);
 bool     tu_fifo_overflowed             (tu_fifo_t* f);
 void     tu_fifo_correct_read_pointer   (tu_fifo_t* f);
 
-static inline uint16_t tu_fifo_depth(tu_fifo_t* f)
+TU_ATTR_ALWAYS_INLINE static inline
+uint16_t tu_fifo_depth(tu_fifo_t* f)
 {
   return f->depth;
 }
 
 // Pointer modifications intended to be used in combinations with DMAs.
 // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED!
-void     tu_fifo_advance_write_pointer  (tu_fifo_t *f, uint16_t n);
-void     tu_fifo_advance_read_pointer   (tu_fifo_t *f, uint16_t n);
+void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n);
+void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n);
 
 // If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies
 // to handle a possible wrapping part. These functions deliver a pointer to start

+ 1 - 0
src/device/dcd.h

@@ -28,6 +28,7 @@
 #define _TUSB_DCD_H_
 
 #include "common/tusb_common.h"
+#include "osal/osal.h"
 #include "common/tusb_fifo.h"
 
 #ifdef __cplusplus

+ 1 - 1
src/device/usbd.c

@@ -1292,7 +1292,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
 // bytes should be written and second to keep the return value free to give back a boolean
 // success message. If total_bytes is too big, the FIFO will copy only what is available
 // into the USB buffer!
-bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
 {
   uint8_t const epnum = tu_edpt_number(ep_addr);
   uint8_t const dir   = tu_edpt_dir(ep_addr);

+ 2 - 2
src/device/usbd.h

@@ -70,8 +70,8 @@ bool tud_mounted(void);
 bool tud_suspended(void);
 
 // Check if device is ready to transfer
-TU_ATTR_ALWAYS_INLINE
-static inline bool tud_ready(void)
+TU_ATTR_ALWAYS_INLINE static inline
+bool tud_ready(void)
 {
   return tud_mounted() && !tud_suspended();
 }

+ 2 - 2
src/device/usbd_pvt.h

@@ -84,7 +84,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr);
 bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
 
 // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted
-bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes);
+bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes);
 
 // Claim an endpoint before submitting a transfer.
 // If caller does not make any transfer, it must release endpoint for others.
@@ -105,7 +105,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr);
 // Check if endpoint is stalled
 bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr);
 
-static inline
+TU_ATTR_ALWAYS_INLINE static inline
 bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr)
 {
   return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr);

+ 4 - 18
src/host/hcd.h

@@ -28,6 +28,8 @@
 #define _TUSB_HCD_H_
 
 #include "common/tusb_common.h"
+#include "osal/osal.h"
+#include "common/tusb_fifo.h"
 
 #ifdef __cplusplus
  extern "C" {
@@ -106,15 +108,8 @@ void hcd_int_enable (uint8_t rhport);
 // Disable USB interrupt
 void hcd_int_disable(uint8_t rhport);
 
-// Get micro frame number (125 us)
-uint32_t hcd_uframe_number(uint8_t rhport);
-
 // Get frame number (1ms)
-TU_ATTR_ALWAYS_INLINE static inline
-uint32_t hcd_frame_number(uint8_t rhport)
-{
-  return hcd_uframe_number(rhport) >> 3;
-}
+uint32_t hcd_frame_number(uint8_t rhport);
 
 //--------------------------------------------------------------------+
 // Port API
@@ -141,21 +136,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr);
 
 bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
 bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
 
 bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr);
 bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr);
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
 
-// TODO merge with pipe_xfer
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
-
-//--------------------------------------------------------------------+
-// PIPE API - TODO remove later
-//--------------------------------------------------------------------+
-// TODO control xfer should be used via usbh layer
-bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet
-bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete);
-
 //--------------------------------------------------------------------+
 // Event API (implemented by stack)
 //--------------------------------------------------------------------+

+ 146 - 136
src/host/hub.c

@@ -28,9 +28,7 @@
 
 #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB)
 
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
+#include "usbh.h"
 #include "hub.h"
 
 //--------------------------------------------------------------------+
@@ -44,13 +42,30 @@ typedef struct
   uint8_t status_change; // data from status change interrupt endpoint
 
   hub_port_status_response_t port_status;
-}usbh_hub_t;
+} hub_interface_t;
 
-CFG_TUSB_MEM_SECTION static usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX];
+CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUSB_HOST_DEVICE_MAX];
 TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)];
 
-//OSAL_SEM_DEF(hub_enum_semaphore);
-//static osal_semaphore_handle_t hub_enum_sem_hdl;
+#if CFG_TUSB_DEBUG
+static char const* const _hub_feature_str[] =
+{
+  [HUB_FEATURE_PORT_CONNECTION          ] = "PORT_CONNECTION",
+  [HUB_FEATURE_PORT_ENABLE              ] = "PORT_ENABLE",
+  [HUB_FEATURE_PORT_SUSPEND             ] = "PORT_SUSPEND",
+  [HUB_FEATURE_PORT_OVER_CURRENT        ] = "PORT_OVER_CURRENT",
+  [HUB_FEATURE_PORT_RESET               ] = "PORT_RESET",
+  [HUB_FEATURE_PORT_POWER               ] = "PORT_POWER",
+  [HUB_FEATURE_PORT_LOW_SPEED           ] = "PORT_LOW_SPEED",
+  [HUB_FEATURE_PORT_CONNECTION_CHANGE   ] = "PORT_CONNECTION_CHANGE",
+  [HUB_FEATURE_PORT_ENABLE_CHANGE       ] = "PORT_ENABLE_CHANGE",
+  [HUB_FEATURE_PORT_SUSPEND_CHANGE      ] = "PORT_SUSPEND_CHANGE",
+  [HUB_FEATURE_PORT_OVER_CURRENT_CHANGE ] = "PORT_OVER_CURRENT_CHANGE",
+  [HUB_FEATURE_PORT_RESET_CHANGE        ] = "PORT_RESET_CHANGE",
+  [HUB_FEATURE_PORT_TEST                ] = "PORT_TEST",
+  [HUB_FEATURE_PORT_INDICATOR           ] = "PORT_INDICATOR",
+};
+#endif
 
 //--------------------------------------------------------------------+
 // HUB
@@ -71,12 +86,12 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
     .wLength  = 0
   };
 
-  TU_LOG2("HUB Clear Port Feature: addr = %u port = %u, feature = %u\r\n", hub_addr, hub_port, feature);
+  TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
   TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) );
   return true;
 }
 
-bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb)
+bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb)
 {
   tusb_control_request_t const request =
   {
@@ -84,20 +99,25 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con
     {
       .recipient = TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
-      .direction = TUSB_DIR_IN
+      .direction = TUSB_DIR_OUT
     },
-    .bRequest = HUB_REQUEST_GET_STATUS,
-    .wValue   = 0,
+    .bRequest = HUB_REQUEST_SET_FEATURE,
+    .wValue   = feature,
     .wIndex   = hub_port,
-    .wLength  = 4
+    .wLength  = 0
   };
 
-  TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port);
-  TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) );
+  TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
+  TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) );
   return true;
 }
 
 bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb)
+{
+  return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb);
+}
+
+bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb)
 {
   tusb_control_request_t const request =
   {
@@ -105,16 +125,16 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_
     {
       .recipient = TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
-      .direction = TUSB_DIR_OUT
+      .direction = TUSB_DIR_IN
     },
-    .bRequest = HUB_REQUEST_SET_FEATURE,
-    .wValue   = HUB_FEATURE_PORT_RESET,
+    .bRequest = HUB_REQUEST_GET_STATUS,
+    .wValue   = 0,
     .wIndex   = hub_port,
-    .wLength  = 0
+    .wLength  = 4
   };
 
-  TU_LOG2("HUB Reset Port: addr = %u port = %u\r\n", hub_addr, hub_port);
-  TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) );
+  TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port);
+  TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) );
   return true;
 }
 
@@ -123,8 +143,7 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_
 //--------------------------------------------------------------------+
 void hub_init(void)
 {
-  tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t));
-//  hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) );
+  tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t));
 }
 
 bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
@@ -149,46 +168,72 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf
   return true;
 }
 
-static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
-static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+void hub_close(uint8_t dev_addr)
+{
+  tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t));
+}
 
-static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+bool hub_status_pipe_queue(uint8_t dev_addr)
 {
-  (void) request;
-  TU_ASSERT(XFER_RESULT_SUCCESS == result);
+  hub_interface_t * p_hub = &hub_data[dev_addr-1];
+  return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1);
+}
 
-  usbh_hub_t* p_hub = &hub_data[dev_addr-1];
 
-  // only use number of ports in hub descriptor
-  descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer;
-  p_hub->port_count = desc_hub->bNbrPorts;
+//--------------------------------------------------------------------+
+// Set Configure
+//--------------------------------------------------------------------+
 
-  // May need to GET_STATUS
+static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+
+bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
+{
+   hub_interface_t* p_hub = &hub_data[dev_addr-1];
+  TU_ASSERT(itf_num == p_hub->itf_num);
 
-  // Ports must be powered on to be able to detect connection
-  tusb_control_request_t const new_request =
+  // Get Hub Descriptor
+  tusb_control_request_t const request =
   {
     .bmRequestType_bit =
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = TUSB_REQ_RCPT_DEVICE,
       .type      = TUSB_REQ_TYPE_CLASS,
-      .direction = TUSB_DIR_OUT
+      .direction = TUSB_DIR_IN
     },
-    .bRequest = HUB_REQUEST_SET_FEATURE,
-    .wValue   = HUB_FEATURE_PORT_POWER,
-    .wIndex   = 1, // starting with port 1
-    .wLength  = 0
+    .bRequest = HUB_REQUEST_GET_DESCRIPTOR,
+    .wValue   = 0,
+    .wIndex   = 0,
+    .wLength  = sizeof(descriptor_hub_desc_t)
   };
 
-  TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) );
+  TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) );
 
   return true;
 }
 
+static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+{
+  (void) request;
+  TU_ASSERT(XFER_RESULT_SUCCESS == result);
+
+  hub_interface_t* p_hub = &hub_data[dev_addr-1];
+
+  // only use number of ports in hub descriptor
+  descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer;
+  p_hub->port_count = desc_hub->bNbrPorts;
+
+  // May need to GET_STATUS
+
+  // Set Port Power to be able to detect connection, starting with port 1
+  uint8_t const hub_port = 1;
+  return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete);
+}
+
 static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
 {
   TU_ASSERT(XFER_RESULT_SUCCESS == result);
-  usbh_hub_t* p_hub = &hub_data[dev_addr-1];
+   hub_interface_t* p_hub = &hub_data[dev_addr-1];
 
   if (request->wIndex == p_hub->port_count)
   {
@@ -199,64 +244,71 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t
     usbh_driver_set_config_complete(dev_addr, p_hub->itf_num);
   }else
   {
-    tusb_control_request_t new_request = *request;
-    new_request.wIndex++; // power next port
-
-    TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) );
+    // power next port
+    uint8_t const hub_port = (uint8_t) (request->wIndex + 1);
+    return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete);
   }
 
   return true;
 }
 
-bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
+//--------------------------------------------------------------------+
+// Connection Changes
+//--------------------------------------------------------------------+
+
+static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+
+// callback as response of interrupt endpoint polling
+bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
 {
-  usbh_hub_t* p_hub = &hub_data[dev_addr-1];
-  TU_ASSERT(itf_num == p_hub->itf_num);
+  (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
+  (void) ep_addr;
+  TU_ASSERT(result == XFER_RESULT_SUCCESS);
+
+  hub_interface_t * p_hub = &hub_data[dev_addr-1];
+
+  TU_LOG2("  Port Status Change = 0x%02X\r\n", p_hub->status_change);
 
-  //------------- Get Hub Descriptor -------------//
-  tusb_control_request_t request =
+  // Hub ignore bit0 in status change
+  for (uint8_t port=1; port <= p_hub->port_count; port++)
   {
-    .bmRequestType_bit =
+    if ( tu_bit_test(p_hub->status_change, port) )
     {
-      .recipient = TUSB_REQ_RCPT_DEVICE,
-      .type      = TUSB_REQ_TYPE_CLASS,
-      .direction = TUSB_DIR_IN
-    },
-    .bRequest = HUB_REQUEST_GET_DESCRIPTOR,
-    .wValue   = 0,
-    .wIndex   = 0,
-    .wLength  = sizeof(descriptor_hub_desc_t)
-  };
+      hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete);
+      break;
+    }
+  }
 
-  TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_get_hub_desc_complete) );
+  // NOTE: next status transfer is queued by usbh.c after handling this request
 
   return true;
 }
 
-static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
-static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
-static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
-
-static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
 {
   TU_ASSERT(result == XFER_RESULT_SUCCESS);
-
-  // usbh_hub_t * p_hub = &hub_data[dev_addr-1];
+  hub_interface_t * p_hub = &hub_data[dev_addr-1];
   uint8_t const port_num = (uint8_t) request->wIndex;
 
-  // submit attach event
-  hcd_event_t event =
+  // Connection change
+  if (p_hub->port_status.change.connection)
   {
-    .rhport     = usbh_get_rhport(dev_addr),
-    .event_id   = HCD_EVENT_DEVICE_ATTACH,
-    .connection =
-    {
-      .hub_addr = dev_addr,
-      .hub_port = port_num
-    }
-  };
+    // Port is powered and enabled
+    //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, );
 
-  hcd_event_handler(&event, false);
+    // Acknowledge Port Connection Change
+    hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete);
+  }else
+  {
+    // Other changes are: Enable, Suspend, Over Current, Reset, L1 state
+    // TODO clear change
+
+    // prepare for next hub status
+    // TODO continue with status_change, or maybe we can do it again with status
+    hub_status_pipe_queue(dev_addr);
+  }
 
   return true;
 }
@@ -265,7 +317,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro
 {
   TU_ASSERT(result == XFER_RESULT_SUCCESS);
 
-  usbh_hub_t * p_hub = &hub_data[dev_addr-1];
+  hub_interface_t * p_hub = &hub_data[dev_addr-1];
   uint8_t const port_num = (uint8_t) request->wIndex;
 
   if ( p_hub->port_status.status.connection )
@@ -292,70 +344,28 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro
   return true;
 }
 
-static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
 {
   TU_ASSERT(result == XFER_RESULT_SUCCESS);
-  usbh_hub_t * p_hub = &hub_data[dev_addr-1];
-  uint8_t const port_num = (uint8_t) request->wIndex;
 
-  // Connection change
-  if (p_hub->port_status.change.connection)
-  {
-    // Port is powered and enabled
-    //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, );
-
-    // Acknowledge Port Connection Change
-    hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete);
-  }else
-  {
-    // Other changes are: Enable, Suspend, Over Current, Reset, L1 state
-    // TODO clear change
-
-    // prepare for next hub status
-    // TODO continue with status_change, or maybe we can do it again with status
-    hub_status_pipe_queue(dev_addr);
-  }
-
-  return true;
-}
-
-// is the response of interrupt endpoint polling
-#include "usbh_hcd.h" // FIXME remove
-bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
-  (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
-  (void) ep_addr;
-  TU_ASSERT( result == XFER_RESULT_SUCCESS);
-
-  usbh_hub_t * p_hub = &hub_data[dev_addr-1];
+  // usbh_hub_t * p_hub = &hub_data[dev_addr-1];
+  uint8_t const port_num = (uint8_t) request->wIndex;
 
-  TU_LOG2("Port Status Change = 0x%02X\r\n", p_hub->status_change);
-  for (uint8_t port=1; port <= p_hub->port_count; port++)
+  // submit attach event
+  hcd_event_t event =
   {
-    // TODO HUB ignore bit0 hub_status_change
-    if ( tu_bit_test(p_hub->status_change, port) )
+    .rhport     = usbh_get_rhport(dev_addr),
+    .event_id   = HCD_EVENT_DEVICE_ATTACH,
+    .connection =
     {
-      hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete);
-      break;
+      .hub_addr = dev_addr,
+      .hub_port = port_num
     }
-  }
+  };
 
-  // NOTE: next status transfer is queued by usbh.c after handling this request
+  hcd_event_handler(&event, false);
 
   return true;
 }
 
-void hub_close(uint8_t dev_addr)
-{
-  tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t));
-//  osal_semaphore_reset(hub_enum_sem_hdl);
-}
-
-bool hub_status_pipe_queue(uint8_t dev_addr)
-{
-  usbh_hub_t * p_hub = &hub_data[dev_addr-1];
-  return hcd_pipe_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1, true);
-}
-
-
 #endif

+ 3 - 2
src/host/hub.h

@@ -37,7 +37,6 @@
 #define _TUSB_HUB_H_
 
 #include "common/tusb_common.h"
-#include "usbh.h"
 
 #ifdef __cplusplus
  extern "C" {
@@ -172,9 +171,11 @@ typedef struct {
 
 TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct");
 
+bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb);
+bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb);
+
 bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb);
 bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb);
-bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb);
 bool hub_status_pipe_queue(uint8_t dev_addr);
 
 //--------------------------------------------------------------------+

+ 4 - 2
src/host/usbh.c

@@ -378,6 +378,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_
 
 bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
 {
+  TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size);
+
   tusb_desc_endpoint_t ep0_desc =
   {
     .bLength          = sizeof(tusb_desc_endpoint_t),
@@ -455,7 +457,7 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr)
 {
   hcd_event_t event =
   {
-    .rhport = rhport,
+    .rhport   = rhport,
     .event_id = HCD_EVENT_DEVICE_ATTACH
   };
 
@@ -469,7 +471,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr)
 {
   hcd_event_t event =
   {
-    .rhport = hostid,
+    .rhport   = hostid,
     .event_id = HCD_EVENT_DEVICE_REMOVE
   };
 

+ 1 - 8
src/host/usbh.h

@@ -34,10 +34,7 @@
  extern "C" {
 #endif
 
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "osal/osal.h" // TODO refractor move to common.h ?
+#include "common/tusb_common.h"
 #include "hcd.h"
 
 //--------------------------------------------------------------------+
@@ -67,10 +64,6 @@ typedef struct {
 
 typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
 
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
-
 //--------------------------------------------------------------------+
 // APPLICATION API
 //--------------------------------------------------------------------+

+ 2 - 2
src/host/usbh_control.c

@@ -108,7 +108,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu
         _ctrl_xfer.stage = STAGE_DATA;
         if (request->wLength)
         {
-          // Note: initial data toggle is always 1
+          // DATA stage: initial data toggle is always 1
           hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength);
           return true;
         }
@@ -123,7 +123,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu
           TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2);
         }
 
-        // data toggle is always 1
+        // ACK stage: toggle is always 1
         hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0);
       break;
 

+ 78 - 91
src/portable/ehci/ehci.c

@@ -44,6 +44,27 @@
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
 
+typedef struct
+{
+  ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE];
+
+  // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
+  // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms
+  ehci_qhd_t period_head_arr[4];
+
+  // Note control qhd of dev0 is used as head of async list
+  struct {
+    ehci_qhd_t qhd;
+    ehci_qtd_t qtd;
+  }control[CFG_TUSB_HOST_DEVICE_MAX+1];
+
+  ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT];
+  ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32);
+
+  ehci_registers_t* regs;
+
+  volatile uint32_t uframe_number;
+}ehci_data_t;
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION
 //--------------------------------------------------------------------+
@@ -67,7 +88,8 @@ static inline ehci_qhd_t* qhd_control(uint8_t dev_addr)
 static inline ehci_qhd_t* qhd_async_head(uint8_t rhport)
 {
   (void) rhport;
-  return qhd_control(0); // control qhd of dev0 is used as async head
+  // control qhd of dev0 is used as async head
+  return qhd_control(0);
 }
 
 static inline ehci_qtd_t* qtd_control(uint8_t dev_addr)
@@ -102,10 +124,10 @@ static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer);
 // HCD API
 //--------------------------------------------------------------------+
 
-uint32_t hcd_uframe_number(uint8_t rhport)
+uint32_t hcd_frame_number(uint8_t rhport)
 {
   (void) rhport;
-  return ehci_data.uframe_number + ehci_data.regs->frame_index;
+  return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3;
 }
 
 void hcd_port_reset(uint8_t rhport)
@@ -293,81 +315,9 @@ static void ehci_stop(uint8_t rhport)
 #endif
 
 //--------------------------------------------------------------------+
-// CONTROL PIPE API
+// Endpoint API
 //--------------------------------------------------------------------+
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
-{
-  (void) rhport;
-
-  uint8_t const epnum = tu_edpt_number(ep_addr);
-  uint8_t const dir   = tu_edpt_dir(ep_addr);
-
-  // FIXME control only for now
-  if ( epnum == 0 )
-  {
-    ehci_qhd_t* qhd = qhd_control(dev_addr);
-    ehci_qtd_t* qtd = qtd_control(dev_addr);
-
-    qtd_init(qtd, buffer, buflen);
-
-    // first first data toggle is always 1 (data & setup stage)
-    qtd->data_toggle = 1;
-    qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT;
-    qtd->int_on_complete = 1;
-    qtd->next.terminate  = 1;
-
-    // sw region
-    qhd->p_qtd_list_head = qtd;
-    qhd->p_qtd_list_tail = qtd;
-
-    // attach TD
-    qhd->qtd_overlay.next.address = (uint32_t) qtd;
-  }else
-  {
-    ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
-    ehci_qtd_t *p_qtd = qtd_find_free();
-    TU_ASSERT(p_qtd);
-
-    qtd_init(p_qtd, buffer, buflen);
-    p_qtd->pid = p_qhd->pid;
-
-    // Insert TD to QH
-    qtd_insert_to_qhd(p_qhd, p_qtd);
-
-    p_qhd->p_qtd_list_tail->int_on_complete = 1;
-
-    // attach head QTD to QHD start transferring
-    p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head;
-  }
-
-  return true;
-}
-
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
-{
-  (void) rhport;
-
-  ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd;
-  ehci_qtd_t* td  = &ehci_data.control[dev_addr].qtd;
-
-  qtd_init(td, (void*) setup_packet, 8);
-  td->pid          = EHCI_PID_SETUP;
-  td->int_on_complete = 1;
-  td->next.terminate  = 1;
-
-  // sw region
-  qhd->p_qtd_list_head = td;
-  qhd->p_qtd_list_tail = td;
-
-  // attach TD
-  qhd->qtd_overlay.next.address = (uint32_t) td;
-
-  return true;
-}
 
-//--------------------------------------------------------------------+
-// BULK/INT/ISO PIPE API
-//--------------------------------------------------------------------+
 bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
 {
   (void) rhport;
@@ -421,34 +371,71 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
   return true;
 }
 
-bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes)
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
 {
-  //------------- set up QTD -------------//
-  ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
-  ehci_qtd_t *p_qtd = qtd_find_free();
+  (void) rhport;
 
-  TU_ASSERT(p_qtd);
+  ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd;
+  ehci_qtd_t* td  = &ehci_data.control[dev_addr].qtd;
 
-  qtd_init(p_qtd, buffer, total_bytes);
-  p_qtd->pid = p_qhd->pid;
+  qtd_init(td, (void*) setup_packet, 8);
+  td->pid          = EHCI_PID_SETUP;
+  td->int_on_complete = 1;
+  td->next.terminate  = 1;
+
+  // sw region
+  qhd->p_qtd_list_head = td;
+  qhd->p_qtd_list_tail = td;
 
-  //------------- insert TD to TD list -------------//
-  qtd_insert_to_qhd(p_qhd, p_qtd);
+  // attach TD
+  qhd->qtd_overlay.next.address = (uint32_t) td;
 
   return true;
 }
 
-bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
 {
-  TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) );
+  (void) rhport;
 
-  ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
+  if ( epnum == 0 )
+  {
+    ehci_qhd_t* qhd = qhd_control(dev_addr);
+    ehci_qtd_t* qtd = qtd_control(dev_addr);
+
+    qtd_init(qtd, buffer, buflen);
+
+    // first first data toggle is always 1 (data & setup stage)
+    qtd->data_toggle = 1;
+    qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT;
+    qtd->int_on_complete = 1;
+    qtd->next.terminate  = 1;
+
+    // sw region
+    qhd->p_qtd_list_head = qtd;
+    qhd->p_qtd_list_tail = qtd;
+
+    // attach TD
+    qhd->qtd_overlay.next.address = (uint32_t) qtd;
+  }else
+  {
+    ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
+    ehci_qtd_t *p_qtd = qtd_find_free();
+    TU_ASSERT(p_qtd);
+
+    qtd_init(p_qtd, buffer, buflen);
+    p_qtd->pid = p_qhd->pid;
+
+    // Insert TD to QH
+    qtd_insert_to_qhd(p_qhd, p_qtd);
 
-  if ( int_on_complete )
-  { // the just added qtd is pointed by list_tail
     p_qhd->p_qtd_list_tail->int_on_complete = 1;
+
+    // attach head QTD to QHD start transferring
+    p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head;
   }
-  p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring
 
   return true;
 }

+ 5 - 40
src/portable/ehci/ehci.h

@@ -24,12 +24,6 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \ingroup Group_HCD
- * @{
- *  \defgroup EHCI
- *  \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise
- *  @{ */
-
 #ifndef _TUSB_EHCI_H_
 #define _TUSB_EHCI_H_
 
@@ -309,12 +303,11 @@ enum ehci_usbcmd_pos_ {
 
 enum ehci_portsc_change_mask_{
   EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0),
-  EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1),
-  EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2),
-  EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3),
-  EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5),
-
-  EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8),
+  EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE  = TU_BIT(1),
+  EHCI_PORTSC_MASK_PORT_EANBLED           = TU_BIT(2),
+  EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE     = TU_BIT(3),
+  EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE    = TU_BIT(5),
+  EHCI_PORTSC_MASK_PORT_RESET             = TU_BIT(8),
 
   EHCI_PORTSC_MASK_ALL =
       EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE |
@@ -425,36 +418,8 @@ typedef volatile struct
   };
 }ehci_registers_t;
 
-//--------------------------------------------------------------------+
-// EHCI Data Organization
-//--------------------------------------------------------------------+
-typedef struct
-{
-  ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE];
-
-  // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
-  // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms
-  ehci_qhd_t period_head_arr[4];
-
-  // Note control qhd of dev0 is used as head of async list
-  struct {
-    ehci_qhd_t qhd;
-    ehci_qtd_t qtd;
-  }control[CFG_TUSB_HOST_DEVICE_MAX+1];
-
-  ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT];
-  ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32);
-
-  ehci_registers_t* regs;
-
-  volatile uint32_t uframe_number;
-}ehci_data_t;
-
 #ifdef __cplusplus
  }
 #endif
 
 #endif /* _TUSB_EHCI_H_ */
-
-/** @} */
-/** @} */

+ 0 - 1
src/portable/espressif/esp32sx/dcd_esp32sx.c

@@ -40,7 +40,6 @@
 #include "soc/gpio_sig_map.h"
 #include "soc/usb_periph.h"
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 
 // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)

+ 0 - 1
src/portable/microchip/samg/dcd_samg.c

@@ -29,7 +29,6 @@
 #if CFG_TUSB_MCU == OPT_MCU_SAMG
 
 #include "sam.h"
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 
 // TODO should support (SAM3S || SAM4S || SAM4E || SAMG55)

+ 0 - 1
src/portable/nuvoton/nuc120/dcd_nuc120.c

@@ -37,7 +37,6 @@
 
 #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120)
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 #include "NUC100Series.h"
 

+ 0 - 1
src/portable/nuvoton/nuc121/dcd_nuc121.c

@@ -37,7 +37,6 @@
 
 #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) )
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 #include "NuMicro.h"
 

+ 0 - 1
src/portable/nuvoton/nuc505/dcd_nuc505.c

@@ -37,7 +37,6 @@
 
 #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505)
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 #include "NUC505Series.h"
 

+ 145 - 165
src/portable/ohci/ohci.c

@@ -27,7 +27,7 @@
 #include <common/tusb_common.h>
 
 #if TUSB_OPT_HOST_ENABLED && \
-    (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
+    (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
 
 //--------------------------------------------------------------------+
 // INCLUDE
@@ -84,23 +84,23 @@ enum {
 };
 
 enum {
-  OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK      = TU_BIT(0),
-  OHCI_RHPORT_PORT_ENABLE_STATUS_MASK          = TU_BIT(1),
-  OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK         = TU_BIT(2),
-  OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3),
-  OHCI_RHPORT_PORT_RESET_STATUS_MASK           = TU_BIT(4), ///< write '1' to reset port
-
-  OHCI_RHPORT_PORT_POWER_STATUS_MASK           = TU_BIT(8),
-  OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK   = TU_BIT(9),
-
-  OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK       = TU_BIT(16),
-  OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK          = TU_BIT(17),
-  OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK         = TU_BIT(18),
-  OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK         = TU_BIT(19),
-  OHCI_RHPORT_PORT_RESET_CHANGE_MASK           = TU_BIT(20),
-
-  OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK |
-    OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK
+  RHPORT_CURRENT_CONNECT_STATUS_MASK      = TU_BIT(0),
+  RHPORT_PORT_ENABLE_STATUS_MASK          = TU_BIT(1),
+  RHPORT_PORT_SUSPEND_STATUS_MASK         = TU_BIT(2),
+  RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3),
+  RHPORT_PORT_RESET_STATUS_MASK           = TU_BIT(4), ///< write '1' to reset port
+
+  RHPORT_PORT_POWER_STATUS_MASK           = TU_BIT(8),
+  RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK   = TU_BIT(9),
+
+  RHPORT_CONNECT_STATUS_CHANGE_MASK       = TU_BIT(16),
+  RHPORT_PORT_ENABLE_CHANGE_MASK          = TU_BIT(17),
+  RHPORT_PORT_SUSPEND_CHANGE_MASK         = TU_BIT(18),
+  RHPORT_OVER_CURRENT_CHANGE_MASK         = TU_BIT(19),
+  RHPORT_PORT_RESET_CHANGE_MASK           = TU_BIT(20),
+
+  RHPORT_ALL_CHANGE_MASK = RHPORT_CONNECT_STATUS_CHANGE_MASK | RHPORT_PORT_ENABLE_CHANGE_MASK |
+    RHPORT_PORT_SUSPEND_CHANGE_MASK | RHPORT_OVER_CURRENT_CHANGE_MASK | RHPORT_PORT_RESET_CHANGE_MASK
 };
 
 enum {
@@ -123,6 +123,23 @@ enum {
   OHCI_INT_ON_COMPLETE_YES = 0,
   OHCI_INT_ON_COMPLETE_NO  = TU_BIN8(111)
 };
+
+enum {
+  GTD_DT_TOGGLE_CARRY = 0,
+  GTD_DT_DATA0 = TU_BIT(1) | 0,
+  GTD_DT_DATA1 = TU_BIT(1) | 1,
+};
+
+enum {
+  PID_SETUP = 0,
+  PID_OUT,
+  PID_IN,
+};
+
+enum {
+  PID_FROM_TD = 0,
+};
+
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION
 //--------------------------------------------------------------------+
@@ -185,10 +202,10 @@ bool hcd_init(uint8_t rhport)
   return true;
 }
 
-uint32_t hcd_uframe_number(uint8_t rhport)
+uint32_t hcd_frame_number(uint8_t rhport)
 {
   (void) rhport;
-  return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3;
+  return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number;
 }
 
 
@@ -198,7 +215,7 @@ uint32_t hcd_uframe_number(uint8_t rhport)
 void hcd_port_reset(uint8_t hostid)
 {
   (void) hostid;
-  OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK;
+  OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK;
 }
 
 bool hcd_port_connect_status(uint8_t hostid)
@@ -244,16 +261,16 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
 //--------------------------------------------------------------------+
 
 //--------------------------------------------------------------------+
-// CONTROL PIPE API
+// List Helper
 //--------------------------------------------------------------------+
 static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed)
 {
-  return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL     :
-         (p_ed->is_iso               ) ? TUSB_XFER_ISOCHRONOUS :
-         (p_ed->is_interrupt_xfer    ) ? TUSB_XFER_INTERRUPT   : TUSB_XFER_BULK;
+  return (p_ed->ep_number == 0   ) ? TUSB_XFER_CONTROL     :
+         (p_ed->is_iso           ) ? TUSB_XFER_ISOCHRONOUS :
+         (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT   : TUSB_XFER_BULK;
 }
 
-static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval)
+static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval)
 {
   (void) interval;
 
@@ -263,18 +280,18 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size,
     tu_memclr(p_ed, sizeof(ohci_ed_t));
   }
 
-  p_ed->dev_addr    = dev_addr;
-  p_ed->ep_number   = endpoint_addr & 0x0F;
-  p_ed->pid         = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT );
+  p_ed->dev_addr          = dev_addr;
+  p_ed->ep_number         = ep_addr & 0x0F;
+  p_ed->pid               = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT);
   p_ed->speed             = _usbh_devices[dev_addr].speed;
   p_ed->is_iso            = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0;
-  p_ed->max_packet_size  = max_packet_size;
+  p_ed->max_packet_size   = ep_size;
 
   p_ed->used              = 1;
   p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0);
 }
 
-static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes)
+static void gtd_init(ohci_gtd_t* p_td, uint8_t* data_ptr, uint16_t total_bytes)
 {
   tu_memclr(p_td, sizeof(ohci_gtd_t));
 
@@ -286,81 +303,9 @@ static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes)
   p_td->condition_code         = OHCI_CCODE_NOT_ACCESSED;
 
   p_td->current_buffer_pointer = data_ptr;
-  p_td->buffer_end             = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL;
-}
-
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
-{
-  (void) rhport;
-
-  ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed;
-  ohci_gtd_t *p_setup  = &ohci_data.control[dev_addr].gtd;
-
-  gtd_init(p_setup, (void*) setup_packet, 8);
-  p_setup->index       = dev_addr;
-  p_setup->pid         = OHCI_PID_SETUP;
-  p_setup->data_toggle = TU_BIN8(10); // DATA0
-  p_setup->delay_interrupt = OHCI_INT_ON_COMPLETE_YES;
-
-  //------------- Attach TDs list to Control Endpoint -------------//
-  p_ed->td_head.address = (uint32_t) p_setup;
-
-  OHCI_REG->command_status_bit.control_list_filled = 1;
-
-  return true;
-}
-
-// TODO move around
-static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr);
-static ohci_gtd_t * gtd_find_free(void);
-static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd);
-
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
-{
-  (void) rhport;
-
-  uint8_t const epnum = tu_edpt_number(ep_addr);
-  uint8_t const dir   = tu_edpt_dir(ep_addr);
-
-  // FIXME control only for now
-  if ( epnum == 0 )
-  {
-    ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed;
-    ohci_gtd_t *p_data  = &ohci_data.control[dev_addr].gtd;
-
-    gtd_init(p_data, buffer, buflen);
-
-    p_data->index       = dev_addr;
-    p_data->pid         = dir ? OHCI_PID_IN : OHCI_PID_OUT;
-    p_data->data_toggle = TU_BIN8(11); // DATA1
-    p_data->delay_interrupt = OHCI_INT_ON_COMPLETE_YES;
-
-    p_ed->td_head.address = (uint32_t) p_data;
-
-    OHCI_REG->command_status_bit.control_list_filled = 1;
-  }else
-  {
-    ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr);
-    ohci_gtd_t* p_gtd = gtd_find_free();
-
-    TU_ASSERT(p_gtd);
-
-    gtd_init(p_gtd, buffer, buflen);
-    p_gtd->index = p_ed-ohci_data.ed_pool;
-    p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES;
-
-    td_insert_to_ed(p_ed, p_gtd);
-
-    tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) );
-    if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1;
-  }
-
-  return true;
+  p_td->buffer_end             = total_bytes ? (data_ptr + total_bytes-1) : data_ptr;
 }
 
-//--------------------------------------------------------------------+
-// BULK/INT/ISO PIPE API
-//--------------------------------------------------------------------+
 static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr)
 {
   if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed;
@@ -370,7 +315,7 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr)
   for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++)
   {
     if ( (ed_pool[i].dev_addr == dev_addr) &&
-          ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == OHCI_PID_IN) )
+          ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == PID_IN) )
     {
       return &ed_pool[i];
     }
@@ -420,9 +365,36 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr)
   }
 }
 
+static ohci_gtd_t * gtd_find_free(void)
+{
+  for(uint8_t i=0; i < HCD_MAX_XFER; i++)
+  {
+    if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i];
+  }
+
+  return NULL;
+}
+
+static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd)
+{
+  // tail is always NULL
+  if ( tu_align16(p_ed->td_head.address) == 0 )
+  { // TD queue is empty --> head = TD
+    p_ed->td_head.address |= (uint32_t) p_gtd;
+  }
+  else
+  { // TODO currently only support queue up to 2 TD each endpoint at a time
+    ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd;
+  }
+}
+
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+
 bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
 {
-  (void) rhport; 
+  (void) rhport;
 
   // TODO iso support
   TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
@@ -454,62 +426,65 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
   return true;
 }
 
-static ohci_gtd_t * gtd_find_free(void)
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
 {
-  for(uint8_t i=0; i < HCD_MAX_XFER; i++)
-  {
-    if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i];
-  }
+  (void) rhport;
 
-  return NULL;
-}
+  ohci_ed_t* ed   = &ohci_data.control[dev_addr].ed;
+  ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd;
 
-static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd)
-{
-  // tail is always NULL
-  if ( tu_align16(p_ed->td_head.address) == 0 )
-  { // TD queue is empty --> head = TD
-    p_ed->td_head.address |= (uint32_t) p_gtd;
-  }
-  else
-  { // TODO currently only support queue up to 2 TD each endpoint at a time
-    ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd;
-  }
+  gtd_init(qtd, (uint8_t*) setup_packet, 8);
+  qtd->index           = dev_addr;
+  qtd->pid             = PID_SETUP;
+  qtd->data_toggle     = GTD_DT_DATA0;
+  qtd->delay_interrupt = 0;
+
+  //------------- Attach TDs list to Control Endpoint -------------//
+  ed->td_head.address = (uint32_t) qtd;
+
+  OHCI_REG->command_status_bit.control_list_filled = 1;
+
+  return true;
 }
 
-static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
 {
-  ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr);
+  (void) rhport;
 
-  // not support ISO yet
-  TU_VERIFY ( !p_ed->is_iso );
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
 
-  ohci_gtd_t * const p_gtd = gtd_find_free();
-  TU_ASSERT(p_gtd); // not enough gtd
+  if ( epnum == 0 )
+  {
+    ohci_ed_t*  ed  = &ohci_data.control[dev_addr].ed;
+    ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd;
 
-  gtd_init(p_gtd, buffer, total_bytes);
-  p_gtd->index = p_ed-ohci_data.ed_pool;
+    gtd_init(gtd, buffer, buflen);
 
-  if ( int_on_complete )  p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES;
+    gtd->index           = dev_addr;
+    gtd->pid             = dir ? PID_IN : PID_OUT;
+    gtd->data_toggle     = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1
+    gtd->delay_interrupt = 0;
 
-  td_insert_to_ed(p_ed, p_gtd);
+    ed->td_head.address = (uint32_t) gtd;
 
-  return true;
-}
+    OHCI_REG->command_status_bit.control_list_filled = 1;
+  }else
+  {
+    ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr);
+    ohci_gtd_t* gtd = gtd_find_free();
 
-bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes)
-{
-  return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false);
-}
+    TU_ASSERT(gtd);
 
-bool  hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
-{
-  (void) int_on_complete;
-  TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) );
+    gtd_init(gtd, buffer, buflen);
+    gtd->index = ed-ohci_data.ed_pool;
+    gtd->delay_interrupt = 0;
 
-  tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) );
+    td_insert_to_ed(ed, gtd);
 
-  if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1;
+    tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) );
+    if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1;
+  }
 
   return true;
 }
@@ -580,7 +555,12 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd)
 }
 
 static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer)
-{ // 5.2.9 OHCI sample code
+{
+  // 5.2.9 OHCI sample code
+
+  // CBP is 0 mean all data is transferred
+  if (current_buffer == 0) return 0;
+
   return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) +
       tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1;
 }
@@ -596,16 +576,16 @@ static void done_queue_isr(uint8_t hostid)
   {
     // TODO check if td_head is iso td
     //------------- Non ISO transfer -------------//
-    ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head;
-    xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS :
-                                (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED;
+    ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head;
+    xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS :
+                                (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED;
 
-    p_qtd->used = 0; // free TD
-    if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) )
+    qtd->used = 0; // free TD
+    if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) )
     {
-      ohci_ed_t * const p_ed  = gtd_get_ed(p_qtd);
+      ohci_ed_t * const ed  = gtd_get_ed(qtd);
 
-      uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer);
+      uint32_t const xferred_bytes = qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer);
 
       // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs.
       // When there is a error resulting this ED is halted, and this EP still has other queued TD
@@ -616,14 +596,14 @@ static void done_queue_isr(uint8_t hostid)
       // the TailP must be set back to NULL for processing remaining TDs
       if ((event != XFER_RESULT_SUCCESS))
       {
-        p_ed->td_tail &= 0x0Ful;
-        p_ed->td_tail |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue
-        if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1;
+        ed->td_tail &= 0x0Ful;
+        ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue
+        if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1;
       }
 
-      hcd_event_xfer_complete(p_ed->dev_addr,
-                              tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN),
-                              xferred_bytes, event, true);
+      uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN);
+
+      hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true);
     }
 
     td_head = (ohci_td_item_t*) td_head->next;
@@ -646,16 +626,16 @@ void hcd_int_handler(uint8_t hostid)
   //------------- RootHub status -------------//
   if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK )
   {
-    uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK;
+    uint32_t const rhport_status = OHCI_REG->rhport_status[0] & RHPORT_ALL_CHANGE_MASK;
 
     // TODO dual port is not yet supported
-    if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK )
+    if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK )
     {
       // TODO check if remote wake-up
       if ( OHCI_REG->rhport_status_bit[0].current_connect_status )
       {
         // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change)
-        OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK;
+        OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK;
         hcd_event_device_attach(hostid, true);
       }else
       {
@@ -663,7 +643,7 @@ void hcd_int_handler(uint8_t hostid)
       }
     }
 
-    if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK)
+    if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK)
     {
 
     }
@@ -672,7 +652,7 @@ void hcd_int_handler(uint8_t hostid)
   }
 
   //------------- Transfer Complete -------------//
-  if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK)
+  if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK)
   {
     done_queue_isr(hostid);
   }

+ 1 - 17
src/portable/ohci/ohci.h

@@ -24,12 +24,6 @@
  * This file is part of the TinyUSB stack.
  */
 
-/** \ingroup Group_HCD
- * @{
- *  \defgroup OHCI
- *  \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise
- *  @{ */
-
 #ifndef _TUSB_OHCI_H_
 #define _TUSB_OHCI_H_
 
@@ -48,12 +42,6 @@ enum {
   OHCI_MAX_ITD = 4
 };
 
-enum {
-  OHCI_PID_SETUP = 0,
-  OHCI_PID_OUT,
-  OHCI_PID_IN,
-};
-
 //--------------------------------------------------------------------+
 // OHCI Data Structure
 //--------------------------------------------------------------------+
@@ -73,7 +61,6 @@ typedef struct {
   uint32_t reserved2;
 }ohci_td_item_t;
 
-
 typedef struct TU_ATTR_ALIGNED(16)
 {
 	// Word 0
@@ -105,7 +92,7 @@ typedef struct TU_ATTR_ALIGNED(16)
   // Word 0
 	uint32_t dev_addr          : 7;
 	uint32_t ep_number         : 4;
-	uint32_t pid               : 2; // 00b from TD, 01b Out, 10b In
+	uint32_t pid               : 2;
 	uint32_t speed             : 1;
 	uint32_t skip              : 1;
 	uint32_t is_iso            : 1;
@@ -286,6 +273,3 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct");
 #endif
 
 #endif /* _TUSB_OHCI_H_ */
-
-/** @} */
-/** @} */

+ 0 - 2
src/portable/raspberrypi/rp2040/dcd_rp2040.c

@@ -35,8 +35,6 @@
 #include "pico/fix/rp2040_usb_device_enumeration.h"
 #endif
 
-#include "osal/osal.h"
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 
 /*------------------------------------------------------------------*/

+ 6 - 14
src/portable/raspberrypi/rp2040/hcd_rp2040.c

@@ -212,6 +212,7 @@ static void hcd_rp2040_irq(void)
     if (status & USB_INTS_BUFF_STATUS_BITS)
     {
         handled |= USB_INTS_BUFF_STATUS_BITS;
+        // print_bufctrl32(*epx.buffer_control);
         hw_handle_buff_status();
     }
 
@@ -233,6 +234,7 @@ static void hcd_rp2040_irq(void)
     if (status & USB_INTS_ERROR_DATA_SEQ_BITS)
     {
         usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
+        // print_bufctrl32(*epx.buffer_control);
         panic("Data Seq Error \n");
     }
 
@@ -294,7 +296,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
     uint8_t const num = tu_edpt_number(ep_addr);
     tusb_dir_t const dir = tu_edpt_dir(ep_addr);
 
-    bool in = ep_addr & TUSB_DIR_IN_MASK;
     ep->ep_addr = ep_addr;
     ep->dev_addr = dev_addr;
 
@@ -452,6 +453,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
     if (ep_addr != ep->ep_addr)
     {
         // Direction has flipped so re init it but with same properties
+        // TODO treat IN and OUT as invidual endpoints
         _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0);
     }
 
@@ -501,10 +503,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
     return true;
 }
 
-uint32_t hcd_uframe_number(uint8_t rhport)
+uint32_t hcd_frame_number(uint8_t rhport)
 {
-    // Microframe number is (125us) but we are max full speed so return miliseconds * 8
-    return usb_hw->sof_rd * 8;
+    return usb_hw->sof_rd;
 }
 
 bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
@@ -531,6 +532,7 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
 bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr)
 {
     panic("hcd_pipe_stalled");
+    return false;
 }
 
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
@@ -539,14 +541,4 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
     return true;
 }
 
-bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
-{
-    pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n",
-        dev_addr, ep_addr, total_bytes, int_on_complete);
-
-    // Same logic as hcd_edpt_xfer as far as I am concerned
-    hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes);
-
-    return true;
-}
 #endif

+ 35 - 3
src/portable/raspberrypi/rp2040/rp2040_usb.c

@@ -46,7 +46,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) {
 #if TUSB_OPT_HOST_ENABLED
 static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep)
 {
-    ep->last_buf = ep->len + ep->transfer_size == ep->total_len;
+    ep->last_buf = (ep->len + ep->transfer_size == ep->total_len);
 }
 #endif
 
@@ -126,8 +126,30 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
 
     // PID
     val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
+
+#if TUSB_OPT_DEVICE_ENABLED
     ep->next_pid ^= 1u;
 
+#else
+    // For Host (also device but since we dictate the endpoint size, following scenario does not occur)
+    // Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12)
+    // Special case with control status stage where PID is always DATA1
+    if ( ep->transfer_size == 0 )
+    {
+      // ZLP also toggle data
+      ep->next_pid ^= 1u;
+    }else
+    {
+      uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize);
+
+      if ( packet_count & 0x01 )
+      {
+        ep->next_pid ^= 1u;
+      }
+    }
+#endif
+
+
 #if TUSB_OPT_HOST_ENABLED
     // Is this the last buffer? Only really matters for host mode. Will trigger
     // the trans complete irq but also stop it polling. We only really care about
@@ -143,6 +165,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
     // the next time the controller polls this dpram address
     _hw_endpoint_buffer_control_set_value32(ep, val);
     pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val);
+    //print_bufctrl16(val);
 }
 
 
@@ -161,7 +184,10 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t
     // Fill in info now that we're kicking off the hw
     ep->total_len = total_len;
     ep->len = 0;
-    ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize);
+
+    // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0)
+    ep->transfer_size = tu_min16(total_len, tu_max16(64, ep->wMaxPacketSize));
+
     ep->active = true;
     ep->user_buf = buffer;
 #if TUSB_OPT_HOST_ENABLED
@@ -185,11 +211,16 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep)
     uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
 
 #if TUSB_OPT_HOST_ENABLED
+    // RP2040-E4
     // tag::host_buf_sel_fix[]
+    // TODO need changes to support double buffering
     if (ep->buf_sel == 1)
     {
         // Host can erroneously write status to top half of buf_ctrl register
         buf_ctrl = buf_ctrl >> 16;
+
+        // update buf1 -> buf0 to prevent panic with "already available"
+        *ep->buffer_control = buf_ctrl;
     }
     // Flip buf sel for host
     ep->buf_sel ^= 1u;
@@ -240,8 +271,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep)
     _hw_endpoint_xfer_sync(ep);
 
     // Now we have synced our state with the hardware. Is there more data to transfer?
+    // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0)
     uint16_t remaining_bytes = ep->total_len - ep->len;
-    ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize);
+    ep->transfer_size = tu_min16(remaining_bytes, tu_max16(64, ep->wMaxPacketSize));
 #if TUSB_OPT_HOST_ENABLED
     _hw_endpoint_update_last_buf(ep);
 #endif

+ 41 - 3
src/portable/raspberrypi/rp2040/rp2040_usb.h

@@ -16,8 +16,6 @@
 #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX
 #endif
 
-// For memset
-#include <string.h>
 
 #if false && !defined(NDEBUG)
 #define pico_trace(format,args...) printf(format, ## args)
@@ -78,7 +76,7 @@ struct hw_endpoint
 #if TUSB_OPT_HOST_ENABLED
     // Only needed for host mode
     bool last_buf;
-    // HOST BUG. Host will incorrect write status to top half of buffer
+    // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer
     // control register when doing transfers > 1 packet
     uint8_t buf_sel;
     // Only needed for host
@@ -119,4 +117,44 @@ static inline uintptr_t hw_data_offset(uint8_t *buf)
 
 extern const char *ep_dir_string[];
 
+typedef union TU_ATTR_PACKED
+{
+  uint16_t u16;
+  struct TU_ATTR_PACKED
+  {
+    uint16_t xfer_len     : 10;
+    uint16_t available    : 1;
+    uint16_t stall        : 1;
+    uint16_t reset_bufsel : 1;
+    uint16_t data_toggle  : 1;
+    uint16_t last_buf     : 1;
+    uint16_t full         : 1;
+  };
+} rp2040_buffer_control_t;
+
+TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct");
+
+static inline void print_bufctrl16(uint32_t __unused u16)
+{
+  rp2040_buffer_control_t __unused bufctrl = {
+      .u16 = u16
+  };
+
+  TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n",
+         bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full);
+}
+
+static inline void print_bufctrl32(uint32_t u32)
+{
+  uint16_t u16;
+
+  u16 = u32 >> 16;
+  TU_LOG(2, "Buffer Control 1 0x%x: ", u16);
+  print_bufctrl16(u16);
+
+  u16 = u32 & 0x0000ffff;
+  TU_LOG(2, "Buffer Control 0 0x%x: ", u16);
+  print_bufctrl16(u16);
+}
+
 #endif

+ 0 - 1
src/portable/sony/cxd56/dcd_cxd56.c

@@ -33,7 +33,6 @@
 #include <nuttx/arch.h>
 
 #include "device/dcd.h"
-#include "osal/osal.h"
 
 #define CXD56_EPNUM (7)
 #define CXD56_SETUP_QUEUE_DEPTH (4)

+ 0 - 1
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c

@@ -120,7 +120,6 @@
 // Some definitions are copied to our private include file.
 #undef USE_HAL_DRIVER
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h"
 

+ 0 - 2
src/portable/st/synopsys/dcd_synopsys.c

@@ -94,10 +94,8 @@
 
 #else
 #error "Unsupported MCUs"
-
 #endif
 
-#include "common/tusb_fifo.h"
 #include "device/dcd.h"
 
 //--------------------------------------------------------------------+

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません