Procházet zdrojové kódy

update(cherryusb): update to v1.4.3

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu před 1 měsícem
rodič
revize
de30bd1105
94 změnil soubory, kde provedl 8718 přidání a 558 odebrání
  1. 3 1
      components/drivers/usb/cherryusb/Kconfig
  2. 4 4
      components/drivers/usb/cherryusb/README.md
  3. 4 4
      components/drivers/usb/cherryusb/README_zh.md
  4. 9 3
      components/drivers/usb/cherryusb/SConscript
  5. 1 1
      components/drivers/usb/cherryusb/VERSION
  6. 6 0
      components/drivers/usb/cherryusb/cherryusb.cmake
  7. 39 1
      components/drivers/usb/cherryusb/cherryusb_config_template.h
  8. 74 0
      components/drivers/usb/cherryusb/class/audio/usb_audio.h
  9. 2 2
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c
  10. 1 1
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h
  11. 4 4
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c
  12. 1 1
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h
  13. 122 36
      components/drivers/usb/cherryusb/class/hid/usb_hid.h
  14. 2 2
      components/drivers/usb/cherryusb/class/hub/usbh_hub.c
  15. 3 3
      components/drivers/usb/cherryusb/class/msc/usbd_msc.c
  16. 63 48
      components/drivers/usb/cherryusb/class/msc/usbh_msc.c
  17. 1 0
      components/drivers/usb/cherryusb/class/msc/usbh_msc.h
  18. 2 2
      components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c
  19. 1 1
      components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h
  20. 2 2
      components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c
  21. 1 1
      components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h
  22. 2 2
      components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c
  23. 1 1
      components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h
  24. 46 10
      components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c
  25. 4 0
      components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h
  26. 3 3
      components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c
  27. 3 3
      components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h
  28. 12 12
      components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c
  29. 1 1
      components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h
  30. 4 1
      components/drivers/usb/cherryusb/common/usb_dc.h
  31. 19 0
      components/drivers/usb/cherryusb/common/usb_dcache.h
  32. 3 0
      components/drivers/usb/cherryusb/common/usb_hc.h
  33. 2 2
      components/drivers/usb/cherryusb/common/usb_log.h
  34. 9 1
      components/drivers/usb/cherryusb/common/usb_osal.h
  35. 8 0
      components/drivers/usb/cherryusb/common/usb_util.h
  36. 104 10
      components/drivers/usb/cherryusb/core/usbd_core.c
  37. 23 1
      components/drivers/usb/cherryusb/core/usbh_core.c
  38. 1 0
      components/drivers/usb/cherryusb/core/usbh_core.h
  39. 75 3
      components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c
  40. 78 6
      components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c
  41. 142 9
      components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c
  42. 85 0
      components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c
  43. 87 14
      components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c
  44. 138 5
      components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c
  45. 68 0
      components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c
  46. 100 1
      components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c
  47. 6 6
      components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c
  48. 76 6
      components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c
  49. 71 3
      components/drivers/usb/cherryusb/demo/cdc_acm_template.c
  50. 71 3
      components/drivers/usb/cherryusb/demo/cdc_ecm_template.c
  51. 73 5
      components/drivers/usb/cherryusb/demo/cdc_rndis_template.c
  52. 68 0
      components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c
  53. 102 0
      components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c
  54. 100 0
      components/drivers/usb/cherryusb/demo/hid_keyboard_template.c
  55. 100 0
      components/drivers/usb/cherryusb/demo/hid_mouse_template.c
  56. 100 0
      components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c
  57. 120 3
      components/drivers/usb/cherryusb/demo/midi_template.c
  58. 68 0
      components/drivers/usb/cherryusb/demo/msc_ram_template.c
  59. 0 172
      components/drivers/usb/cherryusb/demo/msc_storage_template.c
  60. 14 10
      components/drivers/usb/cherryusb/demo/usb_host.c
  61. 119 0
      components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c
  62. 76 0
      components/drivers/usb/cherryusb/demo/video_static_h264_template.c
  63. 76 0
      components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c
  64. 78 0
      components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c
  65. 118 9
      components/drivers/usb/cherryusb/demo/webusb_hid_template.c
  66. 89 9
      components/drivers/usb/cherryusb/demo/winusb1.0_template.c
  67. 157 30
      components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c
  68. 138 28
      components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c
  69. 1 1
      components/drivers/usb/cherryusb/idf_component.yml
  70. 2 0
      components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c
  71. 27 37
      components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c
  72. 1304 0
      components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c
  73. 43 0
      components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c
  74. 301 0
      components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h
  75. 525 0
      components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c
  76. 450 0
      components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h
  77. 639 0
      components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c
  78. 249 0
      components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h
  79. 2 2
      components/drivers/usb/cherryusb/port/dwc2/README.md
  80. 1 0
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c
  81. 0 2
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c
  82. 31 7
      components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c
  83. 1 1
      components/drivers/usb/cherryusb/port/ehci/README.md
  84. 219 0
      components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c
  85. 45 1
      components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c
  86. 9 3
      components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h
  87. 1 4
      components/drivers/usb/cherryusb/port/fsdev/README.md
  88. 4 12
      components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c
  89. 6 2
      components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h
  90. 5 0
      components/drivers/usb/cherryusb/port/rp2040/README.md
  91. 588 0
      components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c
  92. 824 0
      components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c
  93. 125 0
      components/drivers/usb/cherryusb/port/template/usb_dc.c
  94. 133 0
      components/drivers/usb/cherryusb/port/template/usb_hc.c

+ 3 - 1
components/drivers/usb/cherryusb/Kconfig

@@ -125,7 +125,9 @@ if RT_USING_CHERRYUSB
             config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
                 bool "cdc_acm"
             config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
-                bool "msc"
+                bool "msc_ram"
+            config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
+                bool "msc_blkdev"
             config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
                 bool "hid_keyboard"
             config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE

+ 4 - 4
components/drivers/usb/cherryusb/README.md

@@ -12,7 +12,7 @@
     <a href="./README.md">English</a>
 </p>
 
-CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
+CherryUSB is a tiny and beautiful, high performance and portable USB host and device stack for embedded system with USB IP.
 
 ![CherryUSB](CherryUSB.svg)
 
@@ -103,7 +103,7 @@ CherryUSB Host Stack has the following functions:
 - Automatic loading of supported Class drivers
 - Support blocking transfers and asynchronous transfers
 - Support Composite Device
-- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2 and ehci now)
+- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2/ehci/xhci/rp2040)
 - Support Communication Device Class (CDC_ACM, CDC_ECM)
 - Support Human Interface Device (HID)
 - Support Mass Storage Class (MSC)
@@ -197,12 +197,12 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
 |Artinchip      |  d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest  | Long-term |
 |Espressif      |  esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
 |NXP            |  mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
-|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
+|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
+|Raspberry pi   |  rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
 |AllwinnerTech  |  F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
 |Bekencorp      |  bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
 |Sophgo         |  cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
 |WCH            |  CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
-|Raspberry pi   |  rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
 
 ## Package Support
 

+ 4 - 4
components/drivers/usb/cherryusb/README_zh.md

@@ -12,7 +12,7 @@
     <a href="./README.md">English</a>
 </p>
 
-CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
+CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的高性能 USB 主从协议栈。
 
 ![CherryUSB](CherryUSB.svg)
 
@@ -103,7 +103,7 @@ CherryUSB Host 协议栈当前实现以下功能:
 - 自动加载支持的Class 驱动
 - 支持阻塞式传输和异步传输
 - 支持复合设备
-- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,当前仅支持 dwc2 和 ehci)
+- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,仅支持 dwc2/ehci/xhci/rp2040)
 - 支持 Communication Device Class (CDC_ACM, CDC_ECM)
 - 支持 Human Interface Device (HID)
 - 支持 Mass Storage Class (MSC)
@@ -198,12 +198,12 @@ CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和
 |Artinchip      |  d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest  | Long-term |
 |Espressif      |  esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
 |NXP            |  mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
-|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
+|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
+|Raspberry pi   |  rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
 |AllwinnerTech  |  F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
 |Bekencorp      |  bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
 |Sophgo         |  cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
 |WCH            |  CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
-|Raspberry pi   |  rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
 
 ## 软件包支持
 

+ 9 - 3
components/drivers/usb/cherryusb/SConscript

@@ -1,18 +1,23 @@
 from building import *
 
 cwd = GetCurrentDir()
-path = [cwd + '/common']
+path = [cwd]
+path += [cwd + '/common']
 path += [cwd + '/core']
+path += [cwd + '/class/hub']
 path += [cwd + '/class/cdc']
 path += [cwd + '/class/msc']
 path += [cwd + '/class/hid']
 path += [cwd + '/class/audio']
 path += [cwd + '/class/video']
 path += [cwd + '/class/wireless']
+path += [cwd + '/class/midi']
+path += [cwd + '/class/adb']
 path += [cwd + '/class/dfu']
 path += [cwd + '/class/midi']
 path += [cwd + '/class/vendor/net']
 path += [cwd + '/class/vendor/serial']
+path += [cwd + '/class/vendor/wifi']
 src = []
 
 LIBS    = []
@@ -109,13 +114,15 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
         src += Glob('class/cdc/usbd_cdc_ecm.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_NCM']):
         src += Glob('class/cdc/usbd_cdc_ncm.c')
-    if GetDepend(['RT_CHERRYUSB_USING_DFU']):
+    if GetDepend(['RT_CHERRYUSB_DEVICE_DFU']):
         src += Glob('class/dfu/usbd_dfu.c')
 
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
         src += Glob('demo/cdc_acm_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
         src += Glob('demo/msc_ram_template.c')
+    if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
+        src += Glob('platform/rtthread/usbd_msc_blkdev.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
         src += Glob('demo/hid_mouse_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
@@ -147,7 +154,6 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
 
 # USB HOST
 if GetDepend(['RT_CHERRYUSB_HOST']):
-    path += [cwd + '/class/hub']
     src += Glob('core/usbh_core.c')
     src += Glob('class/hub/usbh_hub.c')
     src += Glob('osal/usb_osal_rtthread.c')

+ 1 - 1
components/drivers/usb/cherryusb/VERSION

@@ -1,5 +1,5 @@
 VERSION_MAJOR = 1
 VERSION_MINOR = 4
-PATCHLEVEL = 2
+PATCHLEVEL = 3
 VERSION_TWEAK = 0
 EXTRAVERSION = 0

+ 6 - 0
components/drivers/usb/cherryusb/cherryusb.cmake

@@ -26,6 +26,7 @@
 # set(CONFIG_CHERRYUSB_HOST_HCD "ehci_xxx")
 
 list(APPEND cherryusb_incs
+${CMAKE_CURRENT_LIST_DIR}
 ${CMAKE_CURRENT_LIST_DIR}/common
 ${CMAKE_CURRENT_LIST_DIR}/core
 ${CMAKE_CURRENT_LIST_DIR}/class/hub
@@ -37,6 +38,7 @@ ${CMAKE_CURRENT_LIST_DIR}/class/video
 ${CMAKE_CURRENT_LIST_DIR}/class/wireless
 ${CMAKE_CURRENT_LIST_DIR}/class/midi
 ${CMAKE_CURRENT_LIST_DIR}/class/adb
+${CMAKE_CURRENT_LIST_DIR}/class/dfu
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
@@ -116,6 +118,8 @@ if(CONFIG_CHERRYUSB_DEVICE)
         elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "aic")
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic.c)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic_ll.c)
+        elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "rp2040")
+        list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_dc_rp2040.c)
         endif()
     endif()
 
@@ -270,6 +274,8 @@ if(CONFIG_CHERRYUSB_HOST)
         elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
+        elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "rp2040")
+        list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
         endif()
     endif()
 

+ 39 - 1
components/drivers/usb/cherryusb/cherryusb_config_template.h

@@ -17,11 +17,13 @@
 /* Enable print with color */
 #define CONFIG_USB_PRINTF_COLOR_ENABLE
 
-/* data align size when use dma */
+/* data align size when use dma or use dcache */
 #ifndef CONFIG_USB_ALIGN_SIZE
 #define CONFIG_USB_ALIGN_SIZE 4
 #endif
 
+//#define CONFIG_USB_DCACHE_ENABLE
+
 /* attribute data into no cache ram */
 #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
 
@@ -46,6 +48,20 @@
 /* Enable test mode */
 // #define CONFIG_USBDEV_TEST_MODE
 
+/* enable advance desc register api */
+// CONFIG_USBDEV_ADVANCE_DESC
+
+/* move ep0 setup handler from isr to thread */
+// #define CONFIG_USBDEV_EP0_THREAD
+
+#ifndef CONFIG_USBDEV_EP0_PRIO
+#define CONFIG_USBDEV_EP0_PRIO 4
+#endif
+
+#ifndef CONFIG_USBDEV_EP0_STACKSIZE
+#define CONFIG_USBDEV_EP0_STACKSIZE 2048
+#endif
+
 #ifndef CONFIG_USBDEV_MSC_MAX_LUN
 #define CONFIG_USBDEV_MSC_MAX_LUN 1
 #endif
@@ -276,4 +292,26 @@
 /* ---------------- MUSB Configuration ---------------- */
 // #define CONFIG_USB_MUSB_SUNXI
 
+/* ================ USB Dcache Configuration ==================*/
+
+#ifdef CONFIG_USB_DCACHE_ENABLE
+/* style 1*/
+// void usb_dcache_clean(uintptr_t addr, uint32_t size);
+// void usb_dcache_invalidate(uintptr_t addr, uint32_t size);
+// void usb_dcache_flush(uintptr_t addr, uint32_t size);
+
+/* style 2*/
+// #define usb_dcache_clean(addr, size)
+// #define usb_dcache_invalidate(addr, size)
+// #define usb_dcache_flush(addr, size)
+#endif
+
+#ifndef usb_phyaddr2ramaddr
+#define usb_phyaddr2ramaddr(addr) (addr)
+#endif
+
+#ifndef usb_ramaddr2phyaddr
+#define usb_ramaddr2phyaddr(addr) (addr)
+#endif
+
 #endif

+ 74 - 0
components/drivers/usb/cherryusb/class/audio/usb_audio.h

@@ -822,7 +822,66 @@ struct audio_cs_ep_ep_general_descriptor {
     0x00,                            /* wLockDelay */                                                                    \
     0x00
 
+#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress, ...) \
+    0x09,                            /* bLength */                                                                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,   /* bDescriptorType */                                                               \
+    bInterfaceNumber,                /* bInterfaceNumber */                                                              \
+    0x00,                            /* bAlternateSetting */                                                             \
+    0x00,                            /* bNumEndpoints */                                                                 \
+    USB_DEVICE_CLASS_AUDIO,          /* bInterfaceClass */                                                               \
+    AUDIO_SUBCLASS_AUDIOSTREAMING,   /* bInterfaceSubClass */                                                            \
+    AUDIO_PROTOCOL_UNDEFINED,        /* bInterfaceProtocol */                                                            \
+    0x00,                            /* iInterface */                                                                    \
+    0x09,                            /* bLength */                                                                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,   /* bDescriptorType */                                                               \
+    bInterfaceNumber,                /* bInterfaceNumber */                                                              \
+    0x01,                            /* bAlternateSetting */                                                             \
+    0x02,                            /* bNumEndpoints */                                                                 \
+    USB_DEVICE_CLASS_AUDIO,          /* bInterfaceClass */                                                               \
+    AUDIO_SUBCLASS_AUDIOSTREAMING,   /* bInterfaceSubClass */                                                            \
+    AUDIO_PROTOCOL_UNDEFINED,        /* bInterfaceProtocol */                                                            \
+    0x00,                            /* iInterface */                                                                    \
+    0x07,                            /* bLength */                                                                       \
+    AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */                                                               \
+    AUDIO_STREAMING_GENERAL,         /* bDescriptorSubtype */                                                            \
+    bTerminalLink,                   /* bTerminalLink : Unit ID of the Output Terminal*/                                 \
+    0x01,                            /* bDelay */                                                                        \
+    WBVAL(AUDIO_FORMAT_PCM),         /* wFormatTag : AUDIO_FORMAT_PCM */                                                 \
+    0x08 + PP_NARG(__VA_ARGS__),     /* bLength */                                                                       \
+    AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */                                                               \
+    AUDIO_STREAMING_FORMAT_TYPE,     /* bDescriptorSubtype */                                                            \
+    AUDIO_FORMAT_TYPE_I,             /* bFormatType */                                                                   \
+    bNrChannels,                     /* bNrChannels */                                                                   \
+    bSubFrameSize,                   /* bSubFrameSize : Bytes per audio subframe */                                      \
+    bBitResolution,                  /* bBitResolution : bits per sample */                                              \
+    (PP_NARG(__VA_ARGS__)/3),        /* bSamFreqType : only one frequency supported */                                   \
+    __VA_ARGS__,                     /* tSamFreq : Audio sampling frequency coded on 3 bytes */                          \
+    0x09,                            /* bLength */                                                                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,    /* bDescriptorType */                                                               \
+    bEndpointAddress,                /* bEndpointAddress : IN endpoint 1 */                                              \
+    0x05,                            /* bmAttributes */                                                                  \
+    WBVAL(wMaxPacketSize),           /* wMaxPacketSize */                                                                \
+    bInterval,                       /* bInterval : one packet per frame */                                              \
+    0x00,                            /* bRefresh */                                                                      \
+    bFeedbackEndpointAddress,        /* bSynchAddress */                                                                 \
+    0x07,                            /* bLength */                                                                       \
+    AUDIO_ENDPOINT_DESCRIPTOR_TYPE,  /* bDescriptorType */                                                               \
+    AUDIO_ENDPOINT_GENERAL,          /* bDescriptor */                                                                   \
+    AUDIO_EP_CONTROL_SAMPLING_FEQ,   /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */                                      \
+    0x00,                            /* bLockDelayUnits */                                                               \
+    0x00,                            /* wLockDelay */                                                                    \
+    0x00,                                                                                                                \
+    0x09,                            /* bLength */                                                                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,    /* bDescriptorType */                                                               \
+    bFeedbackEndpointAddress,        /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */                       \
+    0x11,                            /* bmAttributes: TransferType=Isochronous  SyncType=None  EndpointType=Feedback */  \
+    WBVAL(4),                        /* XXXX wMaxPacketSize in Bytes */                                                  \
+    bInterval,                       /* bInterval */                                                                     \
+    0x03,                            /* bRefresh, 8ms */                                                                 \
+    0x00                             /* bSynchAddress */
+
 #define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
+#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07 + 0x09)
 
 #define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
     0x09,                            /* bLength */                                                                       \
@@ -1281,4 +1340,19 @@ struct audio_v2_control_range3_param_block {
 #define AUDIO_SAMPLE_FREQ_4B(frq)  (uint8_t)(frq), (uint8_t)((frq >> 8)), \
                                   (uint8_t)((frq >> 16)), (uint8_t)((frq >> 24))
 
+/* format 10.14 */
+#define AUDIO_FREQ_TO_FEEDBACK_FS(freq) ((freq << 10) / 1000)
+#define AUDIO_FEEDBACK_TO_BUF_FS(buf, feedback) \
+    buf[0] = ((feedback << 4) & 0xFFU);         \
+    buf[1] = (((feedback << 4) >> 8U) & 0xFFU); \
+    buf[2] = (((feedback << 4) >> 16U) & 0xFFU)
+
+/* format 16.16 */
+#define AUDIO_FREQ_TO_FEEDBACK_HS(freq) ((freq << 13) / 1000)
+#define AUDIO_FEEDBACK_TO_BUF_HS(buf, feedback)                \
+    buf[0] = (((feedback & 0x00001FFFu) << 3) & 0xFFu);        \
+    buf[1] = ((((feedback & 0x00001FFFu) << 3) >> 8) & 0xFFu); \
+    buf[2] = (((feedback & 0x01FFE000u) >> 13) & 0xFFu);       \
+    buf[3] = (((feedback & 0x01FFE000u) >> 21) & 0xFFu)
+
 #endif /* USB_AUDIO_H */

+ 2 - 2
components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c

@@ -231,12 +231,12 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
-void usbh_cdc_ecm_rx_thread(void *argument)
+void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uint32_t g_cdc_ecm_rx_length;
     int ret;
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     USB_LOG_INFO("Create cdc ecm rx thread\r\n");
     // clang-format off
 find_class:

+ 1 - 1
components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h

@@ -41,7 +41,7 @@ void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
 uint8_t *usbh_cdc_ecm_get_eth_txbuf(void);
 int usbh_cdc_ecm_eth_output(uint32_t buflen);
 void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_cdc_ecm_rx_thread(void *argument);
+void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 #ifdef __cplusplus
 }

+ 4 - 4
components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c

@@ -62,12 +62,12 @@ static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
     USB_LOG_RAW("wLength: 0x%02x             \r\n", param->wLength);
     USB_LOG_RAW("bmNtbFormatsSupported: %s     \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
 
-    USB_LOG_RAW("dwNtbInMaxSize: 0x%04x           \r\n", param->dwNtbInMaxSize);
+    USB_LOG_RAW("dwNtbInMaxSize: 0x%08lx           \r\n", param->dwNtbInMaxSize);
     USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
     USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x      \r\n", param->wNdbInPayloadRemainder);
     USB_LOG_RAW("wNdbInAlignment: 0x%02x    \r\n", param->wNdbInAlignment);
 
-    USB_LOG_RAW("dwNtbOutMaxSize: 0x%04x     \r\n", param->dwNtbOutMaxSize);
+    USB_LOG_RAW("dwNtbOutMaxSize: 0x%08lx     \r\n", param->dwNtbOutMaxSize);
     USB_LOG_RAW("wNdbOutDivisor: 0x%02x     \r\n", param->wNdbOutDivisor);
     USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x     \r\n", param->wNdbOutPayloadRemainder);
     USB_LOG_RAW("wNdbOutAlignment: 0x%02x     \r\n", param->wNdbOutAlignment);
@@ -249,7 +249,7 @@ static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
-void usbh_cdc_ncm_rx_thread(void *argument)
+void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uint32_t g_cdc_ncm_rx_length;
     int ret;
@@ -259,7 +259,7 @@ void usbh_cdc_ncm_rx_thread(void *argument)
     uint32_t transfer_size = (16 * 1024);
 #endif
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     USB_LOG_INFO("Create cdc ncm rx thread\r\n");
     // clang-format off
 find_class:

+ 1 - 1
components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h

@@ -45,7 +45,7 @@ void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
 uint8_t *usbh_cdc_ncm_get_eth_txbuf(void);
 int usbh_cdc_ncm_eth_output(uint32_t buflen);
 void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_cdc_ncm_rx_thread(void *argument);
+void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 #ifdef __cplusplus
 }

+ 122 - 36
components/drivers/usb/cherryusb/class/hid/usb_hid.h

@@ -191,11 +191,11 @@
 #define HID_MOUSE_INPUT_REPORT_BUTTON3     (1 << 2)
 #define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7)
 
-#define HID_MOUSE_INPUT_BUTTON_LEFT        (1 << 0)
-#define HID_MOUSE_INPUT_BUTTON_RIGHT       (1 << 1)
-#define HID_MOUSE_INPUT_BUTTON_MIDDLE      (1 << 2)
-#define HID_MOUSE_INPUT_BUTTON_BACKWARD    (1 << 3)
-#define HID_MOUSE_INPUT_BUTTON_FORWARD     (1 << 4)
+#define HID_MOUSE_INPUT_BUTTON_LEFT     (1 << 0)
+#define HID_MOUSE_INPUT_BUTTON_RIGHT    (1 << 1)
+#define HID_MOUSE_INPUT_BUTTON_MIDDLE   (1 << 2)
+#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
+#define HID_MOUSE_INPUT_BUTTON_FORWARD  (1 << 4)
 
 /* Joystick input report (4 bytes) (HID D.1) */
 #define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0)
@@ -241,14 +241,14 @@
 #define HID_DESKTOP_USAGE_UNDEFINED 0x00        /* Undefined */
 #define HID_DESKTOP_USAGE_POINTER   0x01        /* Pointer */
 #define HID_DESKTOP_USAGE_MOUSE     0x02        /* Mouse */
-                                           /* 0x03 Reserved */
+                                                /* 0x03 Reserved */
 #define HID_DESKTOP_USAGE_JOYSTICK  0x04        /* Joystick */
 #define HID_DESKTOP_USAGE_GAMEPAD   0x05        /* Game Pad */
 #define HID_DESKTOP_USAGE_KEYBOARD  0x06        /* Keyboard */
 #define HID_DESKTOP_USAGE_KEYPAD    0x07        /* Keypad */
 #define HID_DESKTOP_USAGE_MULTIAXIS 0x08        /* Multi-axis Controller */
 #define HID_DESKTOP_USAGE_TABLET    0x09        /* Tablet PC System Controls */
-                                           /* 0x0a-2f Reserved */
+                                                /* 0x0a-2f Reserved */
 #define HID_DESKTOP_USAGE_X         0x30        /* X */
 #define HID_DESKTOP_USAGE_Y         0x31        /* Y */
 #define HID_DESKTOP_USAGE_Z         0x32        /* Z */
@@ -264,7 +264,7 @@
 #define HID_DESKTOP_USAGE_MOTION    0x3c        /* Motion Wakeup */
 #define HID_DESKTOP_USAGE_START     0x3d        /* Start */
 #define HID_DESKTOP_USAGE_SELECT    0x3e        /* Select */
-                                           /* 0x3f Reserved */
+                                                /* 0x3f Reserved */
 #define HID_DESKTOP_USAGE_VX         0x40       /* Vx */
 #define HID_DESKTOP_USAGE_VY         0x41       /* Vy */
 #define HID_DESKTOP_USAGE_VZ         0x42       /* Vz */
@@ -274,7 +274,7 @@
 #define HID_DESKTOP_USAGE_VNO        0x46       /* Vno */
 #define HID_DESKTOP_USAGE_FEATURE    0x47       /* Feature Notification */
 #define HID_DESKTOP_USAGE_RESOLUTION 0x48       /* Resolution Multiplier */
-                                           /* 0x49-7f Reserved */
+                                                /* 0x49-7f Reserved */
 #define HID_DESKTOP_USAGE_CONTROL      0x80     /* System Control */
 #define HID_DESKTOP_USAGE_POWERDOWN    0x81     /* System Power Down */
 #define HID_DESKTOP_USAGE_SLEEP        0x82     /* System Sleep */
@@ -295,7 +295,7 @@
 #define HID_DESKTOP_USAGE_DPAD_DOWN    0x91     /* D-pad Down */
 #define HID_DESKTOP_USAGE_DPAD_RIGHT   0x92     /* D-pad Right */
 #define HID_DESKTOP_USAGE_DPAD_LEFT    0x93     /* D-pad Left */
-                                           /* 0x94-9f Reserved */
+                                                /* 0x94-9f Reserved */
 #define HID_DESKTOP_USAGE_DOCK            0xa0  /* System Dock */
 #define HID_DESKTOP_USAGE_UNDOCK          0xa1  /* System Undock */
 #define HID_DESKTOP_USAGE_SETUP           0xa2  /* System Setup */
@@ -305,7 +305,7 @@
 #define HID_DESKTOP_USAGE_APP_DEBUG_BREAK 0xa6  /* Application Debugger Break */
 #define HID_DESKTOP_USAGE_MUTE            0xa7  /* System Speaker Mute */
 #define HID_DESKTOP_USAGE_HIBERNATE       0xa8  /* System Hibernate */
-                                           /* 0xa9-af Reserved */
+                                                /* 0xa9-af Reserved */
 #define HID_DESKTOP_USAGE_DISPLAY_INVERT   0xb0 /* System Display Invert */
 #define HID_DESKTOP_USAGE_DISPALY_INTERNAL 0xb1 /* System Display Internal */
 #define HID_DESKTOP_USAGE_DISPLAY_EXTERNAL 0xb2 /* System Display External */
@@ -314,7 +314,7 @@
 #define HID_DESKTOP_USAGE_DISPLAY_TOGGLE   0xb5 /* System Display Toggle Int/Ext */
 #define HID_DESKTOP_USAGE_DISPLAY_SWAP     0xb6 /* System Display Swap */
 #define HID_DESKTOP_USAGE_                 0xb7 /* System Display LCD Autoscale */
-                                           /* 0xb8-ffff Reserved */
+                                                /* 0xb8-ffff Reserved */
 
 /* Keyboard usage IDs (HuT 10) */
 #define HID_KBD_USAGE_NONE            0x00 /* Reserved (no event indicated) */
@@ -529,16 +529,16 @@
 
 /* HID Report Definitions */
 struct usb_hid_class_subdescriptor {
-    uint8_t bDescriptorType;/* Class descriptor type (See 7.1) */
-    uint16_t wDescriptorLength;/* Size of the report descriptor */
+    uint8_t bDescriptorType;    /* Class descriptor type (See 7.1) */
+    uint16_t wDescriptorLength; /* Size of the report descriptor */
 } __PACKED;
 
 struct usb_hid_descriptor {
-    uint8_t bLength; /* Size of the HID descriptor */
-    uint8_t bDescriptorType;/* HID descriptor type */
-    uint16_t bcdHID;/* HID class specification release */
-    uint8_t bCountryCode;/* Country code */
-    uint8_t bNumDescriptors;/* Number of descriptors (>=1) */
+    uint8_t bLength;         /* Size of the HID descriptor */
+    uint8_t bDescriptorType; /* HID descriptor type */
+    uint16_t bcdHID;         /* HID class specification release */
+    uint8_t bCountryCode;    /* Country code */
+    uint8_t bNumDescriptors; /* Number of descriptors (>=1) */
 
     /*
      * Specification says at least one Class Descriptor needs to
@@ -550,11 +550,10 @@ struct usb_hid_descriptor {
 /* Standard Reports *********************************************************/
 
 /* Keyboard input report (8 bytes) (HID B.1) */
-struct usb_hid_kbd_report
-{
-  uint8_t modifier;  /* Modifier keys. See HID_MODIFER_* definitions */
-  uint8_t reserved;
-  uint8_t key[6];    /* Keycode 1-6 */
+struct usb_hid_kbd_report {
+    uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
+    uint8_t reserved;
+    uint8_t key[6]; /* Keycode 1-6 */
 };
 
 /* Keyboard output report (1 byte) (HID B.1),
@@ -562,22 +561,109 @@ struct usb_hid_kbd_report
  */
 
 /* Mouse input report (HID B.2) */
-struct usb_hid_mouse_report
-{
-  uint8_t buttons;   /* See HID_MOUSE_INPUT_BUTTON_* definitions */
-  int8_t xdisp;     /* X displacement */
-  int8_t ydisp;     /* y displacement */
+struct usb_hid_mouse_report {
+    uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
+    int8_t xdisp;    /* X displacement */
+    int8_t ydisp;    /* y displacement */
                      /* Device specific additional bytes may follow */
-  uint8_t wdisp;     /* Wheel displacement */
+    uint8_t wdisp;   /* Wheel displacement */
 };
 
 /* Joystick input report (1 bytes) (HID D.1) */
-struct usb_hid_js_report
-{
-  int8_t xpos;      /* X position */
-  int8_t ypos;      /* X position */
-  uint8_t buttons;   /* See USBHID_JSIN_* definitions */
-  uint8_t throttle;  /* Throttle */
+struct usb_hid_js_report {
+    int8_t xpos;      /* X position */
+    int8_t ypos;      /* X position */
+    uint8_t buttons;  /* See USBHID_JSIN_* definitions */
+    uint8_t throttle; /* Throttle */
 };
 
+// clang-format off
+#define HID_MOUSE_DESCRIPTOR_LEN (9 + 9 + 7)
+
+#define HID_MOUSE_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
+    0x09,                          /* bLength: Interface Descriptor size */                                         \
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */                                 \
+    bInterfaceNumber,              /* bInterfaceNumber: Number of Interface */                                      \
+    0x00,                          /* bAlternateSetting: Alternate setting */                                       \
+    0x01,                          /* bNumEndpoints */                                                              \
+    0x03,                          /* bInterfaceClass: HID */                                                       \
+    bInterfaceSubClass,            /* bInterfaceSubClass : 1=BOOT, 0=no boot */                                     \
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */                           \
+    0x00,                          /* iInterface: Index of string descriptor */                                     \
+    0x09,                          /* bLength: HID Descriptor size */                                               \
+    HID_DESCRIPTOR_TYPE_HID,       /* bDescriptorType: HID */                                                       \
+    0x11,                          /* bcdHID: HID Class Spec release number */                                      \
+    0x01,                                                                                                           \
+    0x00,                         /* bCountryCode: Hardware target country */                                       \
+    0x01,                         /* bNumDescriptors: Number of HID class descriptors to follow */                  \
+    0x22,                         /* bDescriptorType */                                                             \
+    WBVAL(wItemLength),           /* wItemLength: Total length of Report descriptor */                              \
+    0x07,                         /* bLength: Endpoint Descriptor size */                                           \
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */                                                            \
+    int_ep,                       /* bEndpointAddress: Endpoint Address (IN) */                                     \
+    0x03,                         /* bmAttributes: Interrupt endpoint */                                            \
+    WBVAL(wMaxPacketSize),        /* wMaxPacketSize: x Byte max */                                                  \
+    bInterval                     /* bInterval: Polling Interval */
+
+#define HID_KEYBOARD_DESCRIPTOR_LEN (9 + 9 + 7)
+
+#define HID_KEYBOARD_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
+    0x09,                          /* bLength: Interface Descriptor size */                                         \
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */                                 \
+    bInterfaceNumber,              /* bInterfaceNumber: Number of Interface */                                      \
+    0x00,                          /* bAlternateSetting: Alternate setting */                                       \
+    0x01,                          /* bNumEndpoints */                                                              \
+    0x03,                          /* bInterfaceClass: HID */                                                       \
+    bInterfaceSubClass,            /* bInterfaceSubClass : 1=BOOT, 0=no boot */                                     \
+    0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */                           \
+    0x00,                          /* iInterface: Index of string descriptor */                                     \
+    0x09,                          /* bLength: HID Descriptor size */                                               \
+    HID_DESCRIPTOR_TYPE_HID,       /* bDescriptorType: HID */                                                       \
+    0x11,                          /* bcdHID: HID Class Spec release number */                                      \
+    0x01,                                                                                                           \
+    0x00,                         /* bCountryCode: Hardware target country */                                       \
+    0x01,                         /* bNumDescriptors: Number of HID class descriptors to follow */                  \
+    0x22,                         /* bDescriptorType */                                                             \
+    WBVAL(wItemLength),           /* wItemLength: Total length of Report descriptor */                              \
+    0x07,                         /* bLength: Endpoint Descriptor size */                                           \
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */                                                            \
+    int_ep,                       /* bEndpointAddress: Endpoint Address (IN) */                                     \
+    0x03,                         /* bmAttributes: Interrupt endpoint */                                            \
+    WBVAL(wMaxPacketSize),        /* wMaxPacketSize: x Byte max */                                                  \
+    bInterval                     /* bInterval: Polling Interval */
+
+#define HID_CUSTOM_INOUT_DESCRIPTOR_LEN (9 + 9 + 7 + 7)
+
+#define HID_CUSTOM_INOUT_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, in_ep, out_ep,wMaxPacketSize, bInterval) \
+    0x09,                          /* bLength: Interface Descriptor size */                                         \
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */                                 \
+    bInterfaceNumber,              /* bInterfaceNumber: Number of Interface */                                      \
+    0x00,                          /* bAlternateSetting: Alternate setting */                                       \
+    0x02,                          /* bNumEndpoints */                                                              \
+    0x03,                          /* bInterfaceClass: HID */                                                       \
+    bInterfaceSubClass,            /* bInterfaceSubClass : 1=BOOT, 0=no boot */                                     \
+    0x00,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */                           \
+    0x00,                          /* iInterface: Index of string descriptor */                                     \
+    0x09,                          /* bLength: HID Descriptor size */                                               \
+    HID_DESCRIPTOR_TYPE_HID,       /* bDescriptorType: HID */                                                       \
+    0x11,                          /* bcdHID: HID Class Spec release number */                                      \
+    0x01,                                                                                                           \
+    0x00,                         /* bCountryCode: Hardware target country */                                       \
+    0x01,                         /* bNumDescriptors: Number of HID class descriptors to follow */                  \
+    0x22,                         /* bDescriptorType */                                                             \
+    WBVAL(wItemLength),           /* wItemLength: Total length of Report descriptor */                              \
+    0x07,                         /* bLength: Endpoint Descriptor size */                                           \
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */                                                            \
+    in_ep,                        /* bEndpointAddress: Endpoint Address (IN) */                                     \
+    0x03,                         /* bmAttributes: Interrupt endpoint */                                            \
+    WBVAL(wMaxPacketSize),        /* wMaxPacketSize: x Byte max */                                                  \
+    bInterval,                    /* bInterval: Polling Interval */                                                 \
+    0x07,                         /* bLength: Endpoint Descriptor size */                                           \
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */                                                            \
+    out_ep,                       /* bEndpointAddress: Endpoint Address (IN) */                                     \
+    0x03,                         /* bmAttributes: Interrupt endpoint */                                            \
+    WBVAL(wMaxPacketSize),        /* wMaxPacketSize: x Byte max */                                                  \
+    bInterval                     /* bInterval: Polling Interval */
+// clang-format on
+
 #endif /* USB_HID_H */

+ 2 - 2
components/drivers/usb/cherryusb/class/hub/usbh_hub.c

@@ -648,12 +648,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
     }
 }
 
-static void usbh_hub_thread(void *argument)
+static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     struct usbh_hub *hub;
     int ret = 0;
 
-    struct usbh_bus *bus = (struct usbh_bus *)argument;
+    struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     usb_hc_init(bus);
     while (1) {

+ 3 - 3
components/drivers/usb/cherryusb/class/msc/usbd_msc.c

@@ -60,7 +60,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
 } g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
 
 #ifdef CONFIG_USBDEV_MSC_THREAD
-static void usbdev_msc_thread(void *argument);
+static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 #endif
 
 static void usdb_msc_set_max_lun(uint8_t busid)
@@ -911,11 +911,11 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
 }
 
 #if defined(CONFIG_USBDEV_MSC_THREAD)
-static void usbdev_msc_thread(void *argument)
+static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uintptr_t event;
     int ret;
-    uint8_t busid = (uint8_t)(uint32_t)argument;
+    uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     while (1) {
         ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);

+ 63 - 48
components/drivers/usb/cherryusb/class/msc/usbh_msc.c

@@ -13,8 +13,11 @@
 
 #define DEV_FORMAT "/dev/sd%c"
 
-#define MSC_INQUIRY_TIMEOUT 500
+#ifndef CONFIG_USBHOST_MSC_READY_CHECK_TIMES
+#define CONFIG_USBHOST_MSC_READY_CHECK_TIMES 10
+#endif
 
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_cbw_csw[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
 
 static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
@@ -131,7 +134,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
     /* Send the CBW */
     nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, timeout);
     if (nbytes < 0) {
-        USB_LOG_ERR("cbw transfer error\r\n");
+        USB_LOG_ERR("cbw transfer error: %d\r\n", nbytes);
         goto __err_exit;
     }
 
@@ -150,7 +153,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
         }
 
         if (nbytes < 0) {
-            USB_LOG_ERR("msc data transfer error\r\n");
+            USB_LOG_ERR("msc data transfer error: %d\r\n", nbytes);
             goto __err_exit;
         }
     }
@@ -159,7 +162,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
     memset(csw, 0, USB_SIZEOF_MSC_CSW);
     nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, timeout);
     if (nbytes < 0) {
-        USB_LOG_ERR("csw transfer error\r\n");
+        USB_LOG_ERR("csw transfer error: %d\r\n", nbytes);
         goto __err_exit;
     }
 
@@ -184,14 +187,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
     cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
     cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
@@ -199,7 +202,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
@@ -209,7 +212,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
     cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
     cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
@@ -217,7 +220,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
@@ -227,7 +230,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
     cbw->CB[0] = SCSI_CMD_INQUIRY;
     cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
@@ -235,7 +238,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
@@ -244,7 +247,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
     cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
     cbw->CB[0] = SCSI_CMD_READCAPACITY10;
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
@@ -252,18 +255,18 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
 
-    memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
+    memcpy(g_msc_cbw_csw[msc_class->sdchar - 'a'], message, 31);
 
-    usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
+    usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
 {
     struct usb_endpoint_descriptor *ep_desc;
-    int ret;
     struct usbh_msc_modeswitch_config *config;
+    int ret;
 
     struct usbh_msc *msc_class = usbh_msc_class_alloc();
     if (msc_class == NULL) {
@@ -315,34 +318,6 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
         }
     }
 
-    ret = usbh_msc_scsi_testunitready(msc_class);
-    if (ret < 0) {
-        ret = usbh_msc_scsi_requestsense(msc_class);
-        if (ret < 0) {
-            USB_LOG_ERR("Fail to scsi_testunitready\r\n");
-            return ret;
-        }
-    }
-
-    ret = usbh_msc_scsi_inquiry(msc_class);
-    if (ret < 0) {
-        USB_LOG_ERR("Fail to scsi_inquiry\r\n");
-        return ret;
-    }
-    ret = usbh_msc_scsi_readcapacity10(msc_class);
-    if (ret < 0) {
-        USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
-        return ret;
-    }
-
-    if (msc_class->blocksize > 0) {
-        USB_LOG_INFO("Capacity info:\r\n");
-        USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
-    } else {
-        USB_LOG_ERR("Invalid block size\r\n");
-        return -USB_ERR_RANGE;
-    }
-
     snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
 
     USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
@@ -377,12 +352,52 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
+int usbh_msc_scsi_init(struct usbh_msc *msc_class)
+{
+    int ret;
+    uint16_t cnt;
+
+    cnt = 0;
+    while (usbh_msc_scsi_testunitready(msc_class) < 0) {
+        USB_LOG_WRN("Device not ready, try again...\r\n");
+        ret = usbh_msc_scsi_requestsense(msc_class);
+        if (ret < 0) {
+            USB_LOG_ERR("Fail to scsi_testunitready\r\n");
+        }
+        cnt++;
+        if (cnt > CONFIG_USBHOST_MSC_READY_CHECK_TIMES) {
+            return -USB_ERR_NODEV;
+        }
+    }
+    ret = usbh_msc_scsi_inquiry(msc_class);
+    if (ret < 0) {
+        USB_LOG_ERR("Fail to scsi_inquiry\r\n");
+        return ret;
+    }
+
+    ret = usbh_msc_scsi_readcapacity10(msc_class);
+    if (ret < 0) {
+        USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
+        return ret;
+    }
+
+    if (msc_class->blocksize > 0) {
+        USB_LOG_INFO("Capacity info:\r\n");
+        USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
+    } else {
+        USB_LOG_ERR("Invalid block size\r\n");
+        return -USB_ERR_RANGE;
+    }
+
+    return 0;
+}
+
 int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
 {
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
@@ -393,7 +408,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
     SET_BE32(&cbw->CB[2], start_sector);
     SET_BE16(&cbw->CB[7], nsectors);
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
@@ -401,7 +416,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
     struct CBW *cbw;
 
     /* Construct the CBW */
-    cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
+    cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
     memset(cbw, 0, USB_SIZEOF_MSC_CBW);
     cbw->dSignature = MSC_CBW_Signature;
 
@@ -413,7 +428,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
     SET_BE32(&cbw->CB[2], start_sector);
     SET_BE16(&cbw->CB[7], nsectors);
 
-    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
+    return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
 }
 
 void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)

+ 1 - 0
components/drivers/usb/cherryusb/class/msc/usbh_msc.h

@@ -32,6 +32,7 @@ struct usbh_msc_modeswitch_config {
 };
 
 void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
+int usbh_msc_scsi_init(struct usbh_msc *msc_class);
 int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
 int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
 

+ 2 - 2
components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c

@@ -670,7 +670,7 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class)
     return 0;
 }
 
-void usbh_asix_rx_thread(void *argument)
+void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uint32_t g_asix_rx_length;
     int ret;
@@ -683,7 +683,7 @@ void usbh_asix_rx_thread(void *argument)
     uint32_t transfer_size = (16 * 1024);
 #endif
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     USB_LOG_INFO("Create asix rx thread\r\n");
     // clang-format off
 find_class:

+ 1 - 1
components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h

@@ -168,7 +168,7 @@ void usbh_asix_stop(struct usbh_asix *asix_class);
 uint8_t *usbh_asix_get_eth_txbuf(void);
 int usbh_asix_eth_output(uint32_t buflen);
 void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_asix_rx_thread(void *argument);
+void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 #ifdef __cplusplus
 }

+ 2 - 2
components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c

@@ -2130,7 +2130,7 @@ static int usbh_rtl8152_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
-void usbh_rtl8152_rx_thread(void *argument)
+void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uint32_t g_rtl8152_rx_length;
     int ret;
@@ -2142,7 +2142,7 @@ void usbh_rtl8152_rx_thread(void *argument)
     uint32_t transfer_size = (16 * 1024);
 #endif
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     USB_LOG_INFO("Create rtl8152 rx thread\r\n");
     // clang-format off
 find_class:

+ 1 - 1
components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h

@@ -59,7 +59,7 @@ void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
 uint8_t *usbh_rtl8152_get_eth_txbuf(void);
 int usbh_rtl8152_eth_output(uint32_t buflen);
 void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_rtl8152_rx_thread(void *argument);
+void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 #ifdef __cplusplus
 }

+ 2 - 2
components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c

@@ -347,7 +347,7 @@ static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
-void usbh_bl616_rx_thread(void *argument)
+void usbh_bl616_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
     usb_data_t *usb_hdr;
@@ -356,7 +356,7 @@ void usbh_bl616_rx_thread(void *argument)
     rnm_scan_ind_msg_t *scanmsg;
     uint8_t *data;
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     USB_LOG_INFO("Create bl616 wifi rx thread\r\n");
 
     while (1) {

+ 1 - 1
components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h

@@ -205,7 +205,7 @@ void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t
 uint8_t *usbh_bl616_get_eth_txbuf(void);
 int usbh_bl616_eth_output(uint32_t buflen);
 void usbh_bl616_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_bl616_rx_thread(void *argument);
+void usbh_bl616_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 void usbh_bl616_run(struct usbh_bl616 *bl616_class);
 void usbh_bl616_stop(struct usbh_bl616 *bl616_class);

+ 46 - 10
components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c

@@ -37,14 +37,17 @@ struct usbd_rndis_priv {
 #define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
 #endif
 
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
 
 volatile uint8_t *g_rndis_rx_data_buffer;
 volatile uint32_t g_rndis_rx_data_length;
+volatile uint32_t g_rndis_rx_total_length;
 volatile uint32_t g_rndis_tx_data_length;
 
 /* RNDIS options list */
@@ -447,12 +450,14 @@ static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
     switch (event) {
         case USBD_EVENT_RESET:
             g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
-            break;
-        case USBD_EVENT_CONFIGURED:
             g_rndis_rx_data_length = 0;
             g_rndis_tx_data_length = 0;
+            break;
+        case USBD_EVENT_CONFIGURED:
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
             g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
-            usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+            usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+#endif
             break;
 
         default:
@@ -467,10 +472,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
     (void)busid;
     (void)ep;
 
-    hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
-    g_rndis_rx_data_buffer = g_rndis_rx_buffer;
+    hdr = (rndis_data_packet_t *)g_rndis_rx_data_buffer;
     if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
-        usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+        usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length);
         return;
     }
 
@@ -503,6 +507,34 @@ void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
     //USB_LOG_DBG("len:%d\r\n", nbytes);
 }
 
+int usbd_rndis_start_write(uint8_t *buf, uint32_t len)
+{
+    if (!usb_device_is_configured(0)) {
+        return -USB_ERR_NODEV;
+    }
+
+    if (g_rndis_tx_data_length > 0) {
+        return -USB_ERR_BUSY;
+    }
+
+    g_rndis_tx_data_length = len;
+
+    USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
+    return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, buf, len);
+}
+
+int usbd_rndis_start_read(uint8_t *buf, uint32_t len)
+{
+    if (!usb_device_is_configured(0)) {
+        return -USB_ERR_NODEV;
+    }
+
+    g_rndis_rx_data_buffer = buf;
+    g_rndis_rx_total_length = len;
+    g_rndis_rx_data_length = 0;
+    return usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, buf, len);
+}
+
 #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
 #include <lwip/pbuf.h>
 
@@ -515,15 +547,14 @@ struct pbuf *usbd_rndis_eth_rx(void)
     }
     p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
     if (p == NULL) {
+        usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
         return NULL;
     }
     usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
     p->len = g_rndis_rx_data_length;
 
     USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
-    g_rndis_rx_data_length = 0;
-    usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
-
+    usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
     return p;
 }
 
@@ -594,6 +625,11 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
     return intf;
 }
 
+void usbd_rndis_set_connect(bool connect)
+{
+    g_usbd_rndis.link_status = connect ? NDIS_MEDIA_STATE_CONNECTED : NDIS_MEDIA_STATE_DISCONNECTED;
+}
+
 __WEAK void usbd_rndis_data_recv_done(uint32_t len)
 {
     (void)len;
@@ -602,4 +638,4 @@ __WEAK void usbd_rndis_data_recv_done(uint32_t len)
 __WEAK void usbd_rndis_data_send_done(uint32_t len)
 {
     (void)len;
-}
+}

+ 4 - 0
components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h

@@ -18,8 +18,12 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
                                              const uint8_t in_ep,
                                              const uint8_t int_ep, uint8_t mac[6]);
 
+void usbd_rndis_set_connect(bool connect);
+
 void usbd_rndis_data_recv_done(uint32_t len);
 void usbd_rndis_data_send_done(uint32_t len);
+int usbd_rndis_start_write(uint8_t *buf, uint32_t len);
+int usbd_rndis_start_read(uint8_t *buf, uint32_t len);
 
 #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
 struct pbuf *usbd_rndis_eth_rx(void);

+ 3 - 3
components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c

@@ -189,7 +189,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
     return ret;
 }
 
-void usbh_bluetooth_hci_rx_thread(void *argument)
+void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
     uint32_t ep_mps;
@@ -271,7 +271,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
     return ret;
 }
 
-void usbh_bluetooth_hci_evt_rx_thread(void *argument)
+void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
     uint32_t ep_mps;
@@ -320,7 +320,7 @@ delete :
     // clang-format on
 }
 
-void usbh_bluetooth_hci_acl_rx_thread(void *argument)
+void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
     uint32_t ep_mps;

+ 3 - 3
components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h

@@ -40,10 +40,10 @@ extern "C" {
 int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
 void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
 #ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
-void usbh_bluetooth_hci_rx_thread(void *argument);
+void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 #else
-void usbh_bluetooth_hci_evt_rx_thread(void *argument);
-void usbh_bluetooth_hci_acl_rx_thread(void *argument);
+void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
+void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 #endif
 
 void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);

+ 12 - 12
components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c

@@ -90,8 +90,8 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
 
     rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
     rndis_class->max_transfer_size = resp->MaxTransferSize;
-    USB_LOG_INFO("MaxPacketsPerTransfer:%d\r\n", resp->MaxPacketsPerTransfer);
-    USB_LOG_INFO("MaxTransferSize:%d\r\n", resp->MaxTransferSize);
+    USB_LOG_INFO("MaxPacketsPerTransfer:%ld\r\n", resp->MaxPacketsPerTransfer);
+    USB_LOG_INFO("MaxTransferSize:%ld\r\n", resp->MaxTransferSize);
 
     return ret;
 }
@@ -278,8 +278,8 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
     struct usb_endpoint_descriptor *ep_desc;
     int ret;
     uint32_t *oid_support_list;
-    unsigned int oid = 0;
-    unsigned int oid_num = 0;
+    uint32_t oid = 0;
+    uint32_t oid_num = 0;
     uint32_t data_len;
     uint8_t tmp_buffer[512];
     uint8_t data[32];
@@ -319,7 +319,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
         return ret;
     }
     oid_num = (data_len / 4);
-    USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
+    USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%ld\r\n", oid_num);
 
     oid_support_list = (uint32_t *)tmp_buffer;
 
@@ -380,10 +380,10 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
                 }
                 break;
             default:
-                USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
+                USB_LOG_WRN("Ignore rndis query iod:%08lx\r\n", oid);
                 continue;
         }
-        USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
+        USB_LOG_INFO("rndis query iod:%08lx success\r\n", oid);
     }
 
     uint32_t packet_filter = 0x0f;
@@ -414,7 +414,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
     usbh_rndis_run(rndis_class);
     return ret;
 query_errorout:
-    USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
+    USB_LOG_ERR("rndis query iod:%08lx error\r\n", oid);
     return ret;
 }
 
@@ -448,7 +448,7 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
     return ret;
 }
 
-void usbh_rndis_rx_thread(void *argument)
+void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     uint32_t g_rndis_rx_length;
     int ret;
@@ -461,7 +461,7 @@ void usbh_rndis_rx_thread(void *argument)
     uint32_t transfer_size = (16 * 1024);
 #endif
 
-    (void)argument;
+    (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     USB_LOG_INFO("Create rndis rx thread\r\n");
     // clang-format off
@@ -501,7 +501,7 @@ find_class:
             uint32_t total_len = g_rndis_rx_length;
 
             while (g_rndis_rx_length > 0) {
-                USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
+                USB_LOG_DBG("rxlen:%ld\r\n", g_rndis_rx_length);
 
                 pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
 
@@ -523,7 +523,7 @@ find_class:
                         g_rndis_rx_length = 0;
                     }
                 } else {
-                    USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
+                    USB_LOG_ERR("offset:%ld,remain:%ld,total:%ld\r\n", pmg_offset, g_rndis_rx_length, total_len);
                     g_rndis_rx_length = 0;
                     USB_LOG_ERR("Error rndis packet message\r\n");
                 }

+ 1 - 1
components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h

@@ -46,7 +46,7 @@ void usbh_rndis_stop(struct usbh_rndis *rndis_class);
 uint8_t *usbh_rndis_get_eth_txbuf(void);
 int usbh_rndis_eth_output(uint32_t buflen);
 void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
-void usbh_rndis_rx_thread(void *argument);
+void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 
 #ifdef __cplusplus
 }

+ 4 - 1
components/drivers/usb/cherryusb/common/usb_dc.h

@@ -136,7 +136,7 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
  */
 int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
 
-/* usb dcd irq callback */
+/* usb dcd irq callback, called by user */
 
 /**
  * @brief Usb connect irq callback.
@@ -194,6 +194,9 @@ void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
 void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
 #endif
 
+/* called by user */
+void USBD_IRQHandler(uint8_t busid);
+
 #ifdef __cplusplus
 }
 #endif

+ 19 - 0
components/drivers/usb/cherryusb/common/usb_dcache.h

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_DCACHE_H
+#define USB_DCACHE_H
+
+#ifdef CONFIG_USB_DCACHE_ENABLE
+#if CONFIG_USB_ALIGN_SIZE % 32
+#error "CONFIG_USB_ALIGN_SIZE must be multiple of 32"
+#endif
+#else
+#define usb_dcache_clean(addr, size)
+#define usb_dcache_invalidate(addr, size)
+#define usb_dcache_flush(addr, size)
+#endif
+
+#endif /* USB_DCACHE_H */

+ 3 - 0
components/drivers/usb/cherryusb/common/usb_hc.h

@@ -108,6 +108,9 @@ int usbh_submit_urb(struct usbh_urb *urb);
  */
 int usbh_kill_urb(struct usbh_urb *urb);
 
+/* called by user */
+void USBH_IRQHandler(uint8_t busid);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 2
components/drivers/usb/cherryusb/common/usb_log.h

@@ -86,12 +86,12 @@ void usb_assert(const char *filename, int linenum);
 static inline void usb_hexdump(const void *ptr, uint32_t buflen)
 {
     unsigned char *buf = (unsigned char *)ptr;
-    uint32_t i, j;
+    unsigned int i, j;
 
     (void)buf;
 
     for (i = 0; i < buflen; i += 16) {
-        CONFIG_USB_PRINTF("%08X:", i);
+        CONFIG_USB_PRINTF("%08x:", i);
 
         for (j = 0; j < 16; j++)
             if (i + j < buflen) {

+ 9 - 1
components/drivers/usb/cherryusb/common/usb_osal.h

@@ -10,13 +10,21 @@
 #include <string.h>
 #include <stdbool.h>
 
+#ifdef __INCLUDE_NUTTX_CONFIG_H
+#define CONFIG_USB_OSAL_THREAD_SET_ARGV int argc, char **argv
+#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)strtoul(argv[1], NULL, 16))
+#else
+#define CONFIG_USB_OSAL_THREAD_SET_ARGV void *argument
+#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)argument)
+#endif
+
 #define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
 
 typedef void *usb_osal_thread_t;
 typedef void *usb_osal_sem_t;
 typedef void *usb_osal_mutex_t;
 typedef void *usb_osal_mq_t;
-typedef void (*usb_thread_entry_t)(void *argument);
+typedef void (*usb_thread_entry_t)(CONFIG_USB_OSAL_THREAD_SET_ARGV);
 typedef void (*usb_timer_handler_t)(void *argument);
 struct usb_osal_timer {
     usb_timer_handler_t handler;

+ 8 - 0
components/drivers/usb/cherryusb/common/usb_util.h

@@ -207,4 +207,12 @@
 
 #define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
 
+#ifndef usb_phyaddr2ramaddr
+#define usb_phyaddr2ramaddr(addr) (addr)
+#endif
+
+#ifndef usb_ramaddr2phyaddr
+#define usb_ramaddr2phyaddr(addr) (addr)
+#endif
+
 #endif /* USB_UTIL_H */

+ 104 - 10
components/drivers/usb/cherryusb/core/usbd_core.c

@@ -4,6 +4,17 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 #include "usbd_core.h"
+#ifdef CONFIG_USBDEV_EP0_THREAD
+#include "usb_osal.h"
+
+#define USB_EP0_STATE_SETUP 0
+#define USB_EP0_STATE_IN    1
+#define USB_EP0_STATE_OUT   2
+#endif
+
+#undef USB_DBG_TAG
+#define USB_DBG_TAG "usbd_core"
+#include "usb_log.h"
 
 /* general descriptor field offsets */
 #define DESC_bLength         0 /** Length offset */
@@ -62,6 +73,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
 #endif
 #ifdef CONFIG_USBDEV_TEST_MODE
     bool test_req;
+#endif
+#ifdef CONFIG_USBDEV_EP0_THREAD
+    usb_osal_mq_t usbd_ep0_mq;
+    usb_osal_thread_t usbd_ep0_thread;
 #endif
     struct usbd_interface *intf[16];
     uint8_t intf_altsetting[16];
@@ -431,8 +446,8 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t
         }
 
         /* skip to next descriptor */
-        p += p[DESC_bLength];
         current_desc_len += p[DESC_bLength];
+        p += p[DESC_bLength];
         if (current_desc_len >= desc_len && desc_len) {
             break;
         }
@@ -497,7 +512,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
 
                     if (alt_setting == 0) {
                         ret = usbd_reset_endpoint(busid, ep_desc);
-                        goto find_end;
                     } else if (cur_alt_setting == alt_setting) {
                         ret = usbd_set_endpoint(busid, ep_desc);
                     } else {
@@ -511,14 +525,13 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
         }
 
         /* skip to next descriptor */
-        p += p[DESC_bLength];
         current_desc_len += p[DESC_bLength];
+        p += p[DESC_bLength];
         if (current_desc_len >= desc_len && desc_len) {
             break;
         }
     }
 
-find_end:
     usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
 
     return ret;
@@ -685,8 +698,8 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
                     }
 
                     /* skip to next descriptor */
-                    p += p[DESC_bLength];
                     current_desc_len += p[DESC_bLength];
+                    p += p[DESC_bLength];
                     if (current_desc_len >= desc_len && desc_len) {
                         break;
                     }
@@ -1125,12 +1138,10 @@ void usbd_event_reset_handler(uint8_t busid)
     g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESET);
 }
 
-void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
+static void __usbd_event_ep0_setup_complete_handler(uint8_t busid, struct usb_setup_packet *setup)
 {
-    struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
     uint8_t *buf;
 
-    memcpy(setup, psetup, 8);
 #ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
     usbd_print_setup(setup);
 #endif
@@ -1195,7 +1206,20 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
     }
 }
 
-void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
+void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
+{
+    struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
+
+    memcpy(setup, psetup, 8);
+
+#ifdef CONFIG_USBDEV_EP0_THREAD
+    usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_SETUP);
+#else
+    __usbd_event_ep0_setup_complete_handler(busid, setup);
+#endif
+}
+
+static void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
     struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
 
@@ -1236,11 +1260,12 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
     }
 }
 
-void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
+static void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
     struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
 
     (void)ep;
+    (void)setup;
 
     if (nbytes > 0) {
         g_usbd_core[busid].ep0_data_buf += nbytes;
@@ -1249,6 +1274,9 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
         USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core[busid].ep0_data_buf_residue);
 
         if (g_usbd_core[busid].ep0_data_buf_residue == 0) {
+#ifdef CONFIG_USBDEV_EP0_THREAD
+            usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_OUT);
+#else
             /* Received all, send data to handler */
             g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data;
             if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) {
@@ -1258,6 +1286,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
 
             /*Send status to host*/
             usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0);
+#endif
         } else {
             /* Start reading the remain data */
             usbd_ep_start_read(busid, USB_CONTROL_OUT_EP0, g_usbd_core[busid].ep0_data_buf, g_usbd_core[busid].ep0_data_buf_residue);
@@ -1396,6 +1425,47 @@ int usbd_send_remote_wakeup(uint8_t busid)
     }
 }
 
+#ifdef CONFIG_USBDEV_EP0_THREAD
+static void usbdev_ep0_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
+{
+    uintptr_t event;
+    int ret;
+    uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
+    struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
+
+    while (1) {
+        ret = usb_osal_mq_recv(g_usbd_core[busid].usbd_ep0_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
+        if (ret < 0) {
+            continue;
+        }
+        USB_LOG_DBG("event:%d\r\n", event);
+
+        switch (event) {
+            case USB_EP0_STATE_SETUP:
+                __usbd_event_ep0_setup_complete_handler(busid, setup);
+                break;
+            case USB_EP0_STATE_IN:
+                // do nothing
+                break;
+            case USB_EP0_STATE_OUT:
+                /* Received all, send data to handler */
+                g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data;
+                if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) {
+                    usbd_ep_set_stall(busid, USB_CONTROL_IN_EP0);
+                    continue;
+                }
+
+                /*Send status to host*/
+                usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+#endif
+
 int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
 {
     int ret;
@@ -1410,6 +1480,21 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin
     bus = &g_usbdev_bus[busid];
     bus->reg_base = reg_base;
 
+#ifdef CONFIG_USBDEV_EP0_THREAD
+    g_usbd_core[busid].usbd_ep0_mq = usb_osal_mq_create(1);
+    if (g_usbd_core[busid].usbd_ep0_mq == NULL) {
+        USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_mq\r\n");
+        while (1) {
+        }
+    }
+    g_usbd_core[busid].usbd_ep0_thread = usb_osal_thread_create("usbd_ep0", CONFIG_USBDEV_EP0_STACKSIZE, CONFIG_USBDEV_EP0_PRIO, usbdev_ep0_thread, (void *)(uint32_t)busid);
+    if (g_usbd_core[busid].usbd_ep0_thread == NULL) {
+        USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_thread\r\n");
+        while (1) {
+        }
+    }
+#endif
+
     g_usbd_core[busid].event_handler = event_handler;
     ret = usb_dc_init(busid);
     usbd_class_event_notify_handler(busid, USBD_EVENT_INIT, NULL);
@@ -1429,5 +1514,14 @@ int usbd_deinitialize(uint8_t busid)
     usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
     usb_dc_deinit(busid);
     g_usbd_core[busid].intf_offset = 0;
+#ifdef CONFIG_USBDEV_EP0_THREAD
+    if (g_usbd_core[busid].usbd_ep0_mq) {
+        usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq);
+    }
+    if (g_usbd_core[busid].usbd_ep0_thread) {
+        usb_osal_thread_delete(g_usbd_core[busid].usbd_ep0_thread);
+    }
+#endif
+
     return 0;
 }

+ 23 - 1
components/drivers/usb/cherryusb/core/usbh_core.c

@@ -324,6 +324,17 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport)
     }
 }
 
+static void usbh_print_setup(struct usb_setup_packet *setup)
+{
+    USB_LOG_DBG("Setup: "
+                "bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
+                setup->bmRequestType,
+                setup->bRequest,
+                setup->wValue,
+                setup->wIndex,
+                setup->wLength);
+}
+
 static int usbh_get_default_mps(int speed)
 {
     switch (speed) {
@@ -674,10 +685,16 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
     struct usbh_urb *urb;
     int ret;
 
+    if (!hport || !setup) {
+        return -USB_ERR_INVAL;
+    }
+
     urb = &hport->ep0_urb;
 
     usb_osal_mutex_take(hport->mutex);
 
+    usbh_print_setup(setup);
+
     usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
     ret = usbh_submit_urb(urb);
     if (ret == 0) {
@@ -841,7 +858,11 @@ static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t
 
     if (hub->index == hub_index) {
         hport = &hub->child[hub_port - 1];
-        return hport;
+        if (hport->connected) {
+            return hport;
+        } else {
+            return NULL;
+        }
     } else {
         for (uint8_t port = 0; port < hub->nports; port++) {
             hport = &hub->child[port];
@@ -865,6 +886,7 @@ static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t
     }
     return NULL;
 }
+
 void *usbh_find_class_instance(const char *devname)
 {
     usb_slist_t *bus_list;

+ 1 - 0
components/drivers/usb/cherryusb/core/usbh_core.h

@@ -21,6 +21,7 @@
 #include "usb_osal.h"
 #include "usbh_hub.h"
 #include "usb_memcpy.h"
+#include "usb_dcache.h"
 #include "usb_version.h"
 
 #ifdef __cplusplus

+ 75 - 3
components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c

@@ -108,6 +108,70 @@ struct usb_msosv1_descriptor msosv1_desc = {
     .comp_id_property = WINUSB_IFx_WCIDProperties,
 };
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryADB",                  /* Product */
+    "CherryADB2024",              /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor msc_bootuf2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback,
+    .msosv1_descriptor = &msosv1_desc
+};
+#else
 /*!< global descriptor */
 static const uint8_t adb_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
@@ -171,15 +235,16 @@ static const uint8_t adb_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -222,7 +287,14 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base)
         }
     }
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &adb_descriptor);
+#else
     usbd_desc_register(busid, adb_descriptor);
+#endif
+#ifndef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_msosv1_desc_register(busid, &msosv1_desc);
+#endif
     usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }

+ 78 - 6
components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c

@@ -68,6 +68,73 @@
                       AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \
                       AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
+    AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
+    AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL),
+    AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID),
+    AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ))
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UAC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor audio_v1_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t audio_v1_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -125,12 +192,12 @@ const uint8_t audio_v1_descriptor[] = {
     '2', 0x00,                  /* wcChar0 */
     '0', 0x00,                  /* wcChar1 */
     '2', 0x00,                  /* wcChar2 */
-    '1', 0x00,                  /* wcChar3 */
-    '0', 0x00,                  /* wcChar4 */
-    '3', 0x00,                  /* wcChar5 */
-    '1', 0x00,                  /* wcChar6 */
-    '0', 0x00,                  /* wcChar7 */
-    '0', 0x00,                  /* wcChar8 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
     '0' + IN_CHANNEL_NUM, 0x00, /* wcChar9 */
 #ifdef CONFIG_USB_HS
     ///////////////////////////////////////
@@ -149,6 +216,7 @@ const uint8_t audio_v1_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 volatile bool tx_flag = 0;
 volatile bool ep_tx_busy_flag = false;
@@ -214,7 +282,11 @@ struct audio_entity_info audio_entity_table[] = {
 
 void audio_v1_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &audio_v1_descriptor);
+#else
     usbd_desc_register(busid, audio_v1_descriptor);
+#endif
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
     usbd_add_endpoint(busid, &audio_in_ep);

+ 142 - 9
components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c

@@ -6,19 +6,24 @@
 #include "usbd_core.h"
 #include "usbd_audio.h"
 
+#define USING_FEEDBACK 0
+
 #define USBD_VID           0xffff
 #define USBD_PID           0xffff
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
 #ifdef CONFIG_USB_HS
-#define EP_INTERVAL 0x04
+#define EP_INTERVAL               0x04
+#define FEEDBACK_ENDP_PACKET_SIZE 0x04
 #else
-#define EP_INTERVAL 0x01
+#define EP_INTERVAL               0x01
+#define FEEDBACK_ENDP_PACKET_SIZE 0x03
 #endif
 
 #define AUDIO_IN_EP  0x81
 #define AUDIO_OUT_EP 0x02
+#define AUDIO_OUT_FEEDBACK_EP 0x83
 
 #define AUDIO_IN_FU_ID  0x02
 #define AUDIO_OUT_FU_ID 0x05
@@ -38,6 +43,7 @@
 /* 16bit(2 Bytes) 双声道(Mono:2) */
 #define AUDIO_IN_PACKET ((uint32_t)((AUDIO_MIC_FREQ * AUDIO_MIC_FRAME_SIZE_BYTE * 2) / 1000))
 
+#if USING_FEEDBACK == 0
 #define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 +                                       \
                                                   AUDIO_AC_DESCRIPTOR_INIT_LEN(2) +         \
                                                   AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
@@ -48,6 +54,18 @@
                                                   AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
                                                   AUDIO_AS_DESCRIPTOR_INIT_LEN(1) +         \
                                                   AUDIO_AS_DESCRIPTOR_INIT_LEN(1))
+#else
+#define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 +                                       \
+                                                  AUDIO_AC_DESCRIPTOR_INIT_LEN(2) +         \
+                                                  AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
+                                                  AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
+                                                  AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
+                                                  AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
+                                                  AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
+                                                  AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
+                                                  AUDIO_AS_DESCRIPTOR_INIT_LEN(1) +         \
+                                                  AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT_LEN(1))
+#endif
 
 #define AUDIO_AC_SIZ (AUDIO_SIZEOF_AC_HEADER_DESC(2) +          \
                       AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
@@ -57,6 +75,84 @@
                       AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
                       AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
+    AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
+    AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
+    AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
+    AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
+    AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
+    AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
+#if USING_FEEDBACK == 0
+    AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
+                             EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
+#else
+    AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, AUDIO_OUT_PACKET,
+                             EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
+#endif
+    AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
+                             EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ))
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UAC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor audio_v1_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t audio_v1_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -67,8 +163,13 @@ const uint8_t audio_v1_descriptor[] = {
     AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
     AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
     AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
+#if USING_FEEDBACK == 0
     AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
+#else
+    AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, AUDIO_OUT_PACKET,
+                             EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
+#endif
     AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
     ///////////////////////////////////////
@@ -120,13 +221,17 @@ const uint8_t audio_v1_descriptor[] = {
     '2', 0x00,                  /* wcChar0 */
     '0', 0x00,                  /* wcChar1 */
     '2', 0x00,                  /* wcChar2 */
-    '1', 0x00,                  /* wcChar3 */
-    '0', 0x00,                  /* wcChar4 */
-    '3', 0x00,                  /* wcChar5 */
-    '1', 0x00,                  /* wcChar6 */
-    '0', 0x00,                  /* wcChar7 */
-    '0', 0x00,                  /* wcChar8 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+#if USING_FEEDBACK == 0
     '1', 0x00,                  /* wcChar9 */
+#else
+    '2', 0x00,                  /* wcChar9 */
+#endif
 #ifdef CONFIG_USB_HS
     ///////////////////////////////////////
     /// device qualifier descriptor
@@ -144,9 +249,11 @@ const uint8_t audio_v1_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
 
 volatile bool tx_flag = 0;
 volatile bool rx_flag = 0;
@@ -183,6 +290,9 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
         rx_flag = 1;
         /* setup first out ep read transfer */
         usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
+        uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
+        AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value); /* uac1 can only use 10.14 */
+        usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
         printf("OPEN1\r\n");
     } else {
         tx_flag = 1;
@@ -215,6 +325,16 @@ void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
     ep_tx_busy_flag = false;
 }
 
+#if USING_FEEDBACK == 1
+void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
+    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
+    AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
+    usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
+}
+#endif
+
 static struct usbd_endpoint audio_in_ep = {
     .ep_cb = usbd_audio_in_callback,
     .ep_addr = AUDIO_IN_EP
@@ -225,6 +345,13 @@ static struct usbd_endpoint audio_out_ep = {
     .ep_addr = AUDIO_OUT_EP
 };
 
+#if USING_FEEDBACK == 1
+static struct usbd_endpoint audio_out_feedback_ep = {
+    .ep_cb = usbd_audio_iso_out_feedback_callback,
+    .ep_addr = AUDIO_OUT_FEEDBACK_EP
+};
+#endif
+
 struct usbd_interface intf0;
 struct usbd_interface intf1;
 struct usbd_interface intf2;
@@ -240,13 +367,19 @@ struct audio_entity_info audio_entity_table[] = {
 
 void audio_v1_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &audio_v1_descriptor);
+#else
     usbd_desc_register(busid, audio_v1_descriptor);
+#endif
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 2));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
     usbd_add_endpoint(busid, &audio_in_ep);
     usbd_add_endpoint(busid, &audio_out_ep);
-
+#if USING_FEEDBACK == 1
+    usbd_add_endpoint(busid, &audio_out_feedback_ep);
+#endif
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
 

+ 85 - 0
components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c

@@ -72,6 +72,74 @@
                       AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
                       AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
+    AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
+    AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_INTERM_MIC, 0x01, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
+    AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, INPUT_CTRL),
+    AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x03, 0x01, 0x0000),
+    AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x04, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UAC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor audio_v2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t audio_v2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -154,6 +222,7 @@ const uint8_t audio_v2_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static const uint8_t mic_default_sampling_freq_table[] = {
     AUDIO_SAMPLE_FREQ_NUM(1),
@@ -162,7 +231,10 @@ static const uint8_t mic_default_sampling_freq_table[] = {
     AUDIO_SAMPLE_FREQ_4B(0x00)
 };
 
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
+
 volatile bool tx_flag = 0;
+volatile bool ep_tx_busy_flag = false;
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -210,6 +282,7 @@ void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sam
 
 void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
+    ep_tx_busy_flag = false;
 }
 
 static struct usbd_endpoint audio_in_ep = {
@@ -231,7 +304,11 @@ struct audio_entity_info audio_entity_table[] = {
 
 void audio_v2_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &audio_v2_descriptor);
+#else
     usbd_desc_register(busid, audio_v2_descriptor);
+#endif
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
     usbd_add_endpoint(busid, &audio_in_ep);
@@ -242,5 +319,13 @@ void audio_v2_init(uint8_t busid, uintptr_t reg_base)
 void audio_v2_test(uint8_t busid)
 {
     if (tx_flag) {
+        memset(write_buffer, 'a', AUDIO_IN_PACKET);
+        ep_tx_busy_flag = true;
+        usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
+        while (ep_tx_busy_flag) {
+            if (tx_flag == false) {
+                break;
+            }
+        }
     }
 }

+ 87 - 14
components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c

@@ -114,6 +114,79 @@
                       AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) +  \
                       AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
+    AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
+    AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
+    AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
+    AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
+    AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x05, 0x03, 0x03),
+    AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
+    AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
+    AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
+    AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
+    AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UAC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor audio_v2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 uint8_t audio_v2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -201,6 +274,7 @@ uint8_t audio_v2_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static const uint8_t speaker_default_sampling_freq_table[] = {
     AUDIO_SAMPLE_FREQ_NUM(5),
@@ -233,6 +307,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
 
 volatile bool tx_flag = 0;
 volatile bool rx_flag = 0;
+volatile bool ep_tx_busy_flag = false;
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -293,20 +368,6 @@ void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sam
     }
 }
 
-void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
-{
-    uint16_t packet_size = 0;
-    if (ep == AUDIO_OUT_EP) {
-        packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
-        audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
-        audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
-    } else if (ep == AUDIO_IN_EP) {
-        packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
-        audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
-        audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
-    }
-}
-
 void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
     USB_LOG_RAW("actual out len:%d\r\n", nbytes);
@@ -348,7 +409,11 @@ struct audio_entity_info audio_entity_table[] = {
 
 void audio_v2_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &audio_v2_descriptor);
+#else
     usbd_desc_register(busid, audio_v2_descriptor);
+#endif
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
@@ -361,6 +426,14 @@ void audio_v2_init(uint8_t busid, uintptr_t reg_base)
 void audio_v2_test(uint8_t busid)
 {
     if (tx_flag) {
+        memset(write_buffer, 'a', AUDIO_IN_PACKET);
+        ep_tx_busy_flag = true;
+        usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
+        while (ep_tx_busy_flag) {
+            if (tx_flag == false) {
+                break;
+            }
+        }
     }
     if (rx_flag) {
     }

+ 138 - 5
components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c

@@ -6,18 +6,23 @@
 #include "usbd_core.h"
 #include "usbd_audio.h"
 
+#define USING_FEEDBACK 0
+
 #define USBD_VID           0xffff
 #define USBD_PID           0xffff
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
 #ifdef CONFIG_USB_HS
-#define EP_INTERVAL 0x04
+#define EP_INTERVAL               0x04
+#define FEEDBACK_ENDP_PACKET_SIZE 0x04
 #else
-#define EP_INTERVAL 0x01
+#define EP_INTERVAL               0x01
+#define FEEDBACK_ENDP_PACKET_SIZE 0x03
 #endif
 
-#define AUDIO_OUT_EP 0x01
+#define AUDIO_OUT_EP          0x01
+#define AUDIO_OUT_FEEDBACK_EP 0x82
 
 #define AUDIO_OUT_CLOCK_ID 0x01
 #define AUDIO_OUT_FU_ID    0x03
@@ -58,6 +63,7 @@
 
 #define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
 
+#if USING_FEEDBACK == 0
 #define USB_AUDIO_CONFIG_DESC_SIZ (9 +                                                     \
                                    AUDIO_V2_AC_DESCRIPTOR_INIT_LEN +                       \
                                    AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
@@ -65,6 +71,15 @@
                                    AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
                                    AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
                                    AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
+#else
+#define USB_AUDIO_CONFIG_DESC_SIZ (9 +                                                     \
+                                   AUDIO_V2_AC_DESCRIPTOR_INIT_LEN +                       \
+                                   AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
+                                   AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
+                                   AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
+                                   AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
+                                   AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN)
+#endif
 
 #define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC +                        \
                       AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
@@ -72,6 +87,78 @@
                       AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
                       AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
+    AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
+    AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
+    AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
+    AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
+#if USING_FEEDBACK == 0
+    AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
+#else
+    AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
+#endif
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UAC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor audio_v2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t audio_v2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -80,7 +167,11 @@ const uint8_t audio_v2_descriptor[] = {
     AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
     AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
     AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
+#if USING_FEEDBACK == 0
     AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
+#else
+    AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
+#endif
     ///////////////////////////////////////
     /// string0 descriptor
     ///////////////////////////////////////
@@ -136,7 +227,11 @@ const uint8_t audio_v2_descriptor[] = {
     '1', 0x00,                  /* wcChar6 */
     '0', 0x00,                  /* wcChar7 */
     '0', 0x00,                  /* wcChar8 */
-    '3', 0x00,                  /* wcChar9 */
+#if USING_FEEDBACK == 0
+    '3', 0x00, /* wcChar9 */
+#else
+    '4', 0x00, /* wcChar9 */
+#endif
 #ifdef CONFIG_USB_HS
     ///////////////////////////////////////
     /// device qualifier descriptor
@@ -154,6 +249,7 @@ const uint8_t audio_v2_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static const uint8_t default_sampling_freq_table[] = {
     AUDIO_SAMPLE_FREQ_NUM(5),
@@ -175,6 +271,7 @@ static const uint8_t default_sampling_freq_table[] = {
 };
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
 
 volatile bool rx_flag = 0;
 
@@ -208,6 +305,14 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
     rx_flag = 1;
     /* setup first out ep read transfer */
     usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
+#ifdef CONFIG_USB_HS
+    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
+    AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
+#else
+    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
+    AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
+#endif
+    usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
     USB_LOG_RAW("OPEN\r\n");
 }
 
@@ -230,11 +335,33 @@ void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
     usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
 }
 
+#if USING_FEEDBACK == 1
+void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
+#ifdef CONFIG_USB_HS
+    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
+    AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
+#else
+    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
+    AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
+#endif
+    usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
+}
+#endif
+
 static struct usbd_endpoint audio_out_ep = {
     .ep_cb = usbd_audio_iso_out_callback,
     .ep_addr = AUDIO_OUT_EP
 };
 
+#if USING_FEEDBACK == 1
+static struct usbd_endpoint audio_out_feedback_ep = {
+    .ep_cb = usbd_audio_iso_out_feedback_callback,
+    .ep_addr = AUDIO_OUT_FEEDBACK_EP
+};
+#endif
+
 struct usbd_interface intf0;
 struct usbd_interface intf1;
 
@@ -249,11 +376,17 @@ struct audio_entity_info audio_entity_table[] = {
 
 void audio_v2_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &audio_v2_descriptor);
+#else
     usbd_desc_register(busid, audio_v2_descriptor);
+#endif
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
     usbd_add_endpoint(busid, &audio_out_ep);
-
+#if USING_FEEDBACK == 1
+    usbd_add_endpoint(busid, &audio_out_feedback_ep);
+#endif
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
 

+ 68 - 0
components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c

@@ -23,6 +23,69 @@
 #define MSC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UF2 DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor msc_bootuf2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t msc_bootuf2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -100,6 +163,7 @@ const uint8_t msc_bootuf2_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -151,7 +215,11 @@ static struct usbd_interface intf0;
 void msc_bootuf2_init(uint8_t busid, uintptr_t reg_base)
 {
     boot2uf2_flash_init();
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &msc_bootuf2_descriptor);
+#else
     usbd_desc_register(busid, msc_bootuf2_descriptor);
+#endif
     usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
 
     usbd_initialize(busid, reg_base, usbd_event_handler);

+ 100 - 1
components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c

@@ -43,6 +43,101 @@
 #define MSC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
+    MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x03,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                       /* bCountryCode: Hardware target country */
+    0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                       /* bDescriptorType */
+    HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB CDC MSC HID DEMO", /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor cdc_acm_hid_msc_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t cdc_acm_hid_msc_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -152,6 +247,7 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /*!< hid mouse report descriptor */
 static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@@ -303,8 +399,11 @@ struct usbd_interface intf3;
 
 void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &cdc_acm_hid_msc_descriptor);
+#else
     usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
-
+#endif
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
     usbd_add_endpoint(busid, &cdc_out_ep);

+ 6 - 6
components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c

@@ -54,9 +54,9 @@ static const uint8_t device_quality_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
@@ -169,9 +169,9 @@ static const uint8_t cdc_msc_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,

+ 76 - 6
components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c

@@ -37,8 +37,74 @@
 #define CDC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
+    CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, CDC_MAX_MPS, 0x02),
+    CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, CDC_MAX_MPS, 0x02),
+    CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, CDC_MAX_MPS, 0x02)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB CDC MULTI DEMO",   /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor cdc_multi_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
-static const uint8_t cdc_descriptor[] = {
+static const uint8_t cdc_multi_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
@@ -109,15 +175,16 @@ static const uint8_t cdc_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[4][2048];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048];
@@ -225,8 +292,11 @@ struct usbd_interface intf7;
 
 void cdc_acm_multi_init(uint8_t busid, uintptr_t reg_base)
 {
-    usbd_desc_register(busid, cdc_descriptor);
-
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &cdc_multi_descriptor);
+#else
+    usbd_desc_register(busid, cdc_multi_descriptor);
+#endif
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
     usbd_add_endpoint(busid, &cdc_out_ep1);

+ 71 - 3
components/drivers/usb/cherryusb/demo/cdc_acm_template.c

@@ -25,6 +25,69 @@
 #define CDC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB CDC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor cdc_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
 static const uint8_t cdc_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
@@ -94,15 +157,16 @@ static const uint8_t cdc_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@@ -181,7 +245,11 @@ void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
     memcpy(&write_buffer[0], data, 10);
     memset(&write_buffer[10], 'a', 2038);
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &cdc_descriptor);
+#else
     usbd_desc_register(busid, cdc_descriptor);
+#endif
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
     usbd_add_endpoint(busid, &cdc_out_ep);

+ 71 - 3
components/drivers/usb/cherryusb/demo/cdc_ecm_template.c

@@ -34,6 +34,69 @@
 /* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
 #define CDC_ECM_MAC_STRING_INDEX      4
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_ECM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, CDC_ECM_ETH_STATISTICS_BITMAP, CONFIG_CDC_ECM_ETH_MAX_SEGSZE, 0, 0, CDC_ECM_MAC_STRING_INDEX)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB CDC ECM DEMO",     /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor cdc_ecm_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
 static const uint8_t cdc_ecm_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
@@ -124,15 +187,16 @@ static const uint8_t cdc_ecm_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
@@ -277,7 +341,11 @@ void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
 {
     cdc_ecm_lwip_init();
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &cdc_ecm_descriptor);
+#else
     usbd_desc_register(busid, cdc_ecm_descriptor);
+#endif
     usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
     usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
     usbd_initialize(busid, reg_base, usbd_event_handler);

+ 73 - 5
components/drivers/usb/cherryusb/demo/cdc_rndis_template.c

@@ -29,8 +29,71 @@
 #define CDC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB RNDIS DEMO",       /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor cdc_rndis_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
-static const uint8_t cdc_descriptor[] = {
+static const uint8_t cdc_rndis_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
     CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
@@ -100,15 +163,16 @@ static const uint8_t cdc_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 /*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
@@ -315,7 +379,11 @@ void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
 #else
     rndis_lwip_init();
 #endif
-    usbd_desc_register(busid, cdc_descriptor);
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &cdc_rndis_descriptor);
+#else
+    usbd_desc_register(busid, cdc_rndis_descriptor);
+#endif
     usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
     usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
     usbd_initialize(busid, reg_base, usbd_event_handler);

+ 68 - 0
components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c

@@ -15,6 +15,69 @@
 
 #define USB_CONFIG_SIZE (9 + 9 + 9)
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    DFU_DESCRIPTOR_INIT()
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB DFU DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor dfu_flash_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t dfu_flash_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -141,6 +204,7 @@ const uint8_t dfu_flash_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -171,7 +235,11 @@ struct usbd_interface intf0;
 
 void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &dfu_flash_descriptor);
+#else
     usbd_desc_register(busid, dfu_flash_descriptor);
+#endif
     usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }

+ 102 - 0
components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c

@@ -39,6 +39,103 @@
 /*!< custom hid report descriptor size */
 #define HID_CUSTOM_REPORT_DESC_SIZE 38
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    /************** Descriptor of Custom interface *****************/
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x02,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x00,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Custom HID ********************/
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                        /* bCountryCode: Hardware target country */
+    0x01,                        /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                        /* bDescriptorType */
+    HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Custom in endpoint ********************/
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HIDRAW_IN_EP,                 /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    WBVAL(HIDRAW_IN_EP_SIZE),     /* wMaxPacketSize: 4 Byte max */
+    HIDRAW_IN_INTERVAL,           /* bInterval: Polling Interval */
+    /******************** Descriptor of Custom out endpoint ********************/
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HIDRAW_OUT_EP,                /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    WBVAL(HIDRAW_OUT_EP_SIZE),    /* wMaxPacketSize: 4 Byte max */
+    HIDRAW_OUT_EP_INTERVAL,       /* bInterval: Polling Interval */
+    /* 73 */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB HID DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
 static const uint8_t hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@@ -151,6 +248,7 @@ static const uint8_t hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /*!< custom hid report descriptor */
 static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
@@ -274,7 +372,11 @@ struct usbd_interface intf0;
 
 void hid_custom_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &hid_descriptor);
+#else
     usbd_desc_register(busid, hid_descriptor);
+#endif
     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
     usbd_add_endpoint(busid, &custom_in_ep);
     usbd_add_endpoint(busid, &custom_out_ep);

+ 100 - 0
components/drivers/usb/cherryusb/demo/hid_keyboard_template.c

@@ -18,6 +18,101 @@
 #define USB_HID_CONFIG_DESC_SIZ       34
 #define HID_KEYBOARD_REPORT_DESC_SIZE 63
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                          /* bCountryCode: Hardware target country */
+    0x01,                          /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                          /* bDescriptorType */
+    HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB HID DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 static const uint8_t hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -127,6 +222,7 @@ static const uint8_t hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /* USB HID device Configuration Descriptor */
 static uint8_t hid_desc[9] __ALIGN_END = {
@@ -223,7 +319,11 @@ struct usbd_interface intf0;
 
 void hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &hid_descriptor);
+#else
     usbd_desc_register(busid, hid_descriptor);
+#endif
     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
     usbd_add_endpoint(busid, &hid_in_ep);
 

+ 100 - 0
components/drivers/usb/cherryusb/demo/hid_mouse_template.c

@@ -21,6 +21,101 @@
 /*!< report descriptor size */
 #define HID_MOUSE_REPORT_DESC_SIZE 74
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                       /* bCountryCode: Hardware target country */
+    0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                       /* bDescriptorType */
+    HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB HID DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
 const uint8_t hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@@ -131,6 +226,7 @@ const uint8_t hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /*!< hid mouse report descriptor */
 static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@@ -241,7 +337,11 @@ struct usbd_interface intf0;
 
 void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &hid_descriptor);
+#else
     usbd_desc_register(busid, hid_descriptor);
+#endif
     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
     usbd_add_endpoint(busid, &hid_in_ep);
 

+ 100 - 0
components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c

@@ -21,6 +21,101 @@
 /*!< report descriptor size */
 #define HID_MOUSE_REPORT_DESC_SIZE 74
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_REMOTE_WAKEUP | USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
+
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                       /* bCountryCode: Hardware target country */
+    0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                       /* bDescriptorType */
+    HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB HID DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 /*!< global descriptor */
 const uint8_t hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@@ -131,6 +226,7 @@ const uint8_t hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /*!< hid mouse report descriptor */
 static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@@ -241,7 +337,11 @@ static struct usbd_interface intf0;
 
 void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &hid_descriptor);
+#else
     usbd_desc_register(busid, hid_descriptor);
+#endif
     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
     usbd_add_endpoint(busid, &hid_in_ep);
 

+ 120 - 3
components/drivers/usb/cherryusb/demo/midi_template.c

@@ -22,6 +22,118 @@
 #define MIDI_EP_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    // Standard AC Interface Descriptor
+    0x09,
+    0x04,
+    0x00,
+    0x00,
+    0x00,
+    0x01,
+    0x01,
+    0x00,
+    0x00,
+    // Class-specific AC Interface Descriptor
+    0x09,
+    0x24,
+    0x01,
+    0x00,
+    0x01,
+    0x09,
+    0x00,
+    0x01,
+    0x01,
+    // MIDIStreaming Interface Descriptors
+    0x09,
+    0x04,
+    0x01,
+    0x00,
+    0x02,
+    0x01,
+    0x03,
+    0x00,
+    0x00,
+    // Class-Specific MS Interface Header Descriptor
+    0x07,
+    0x24,
+    0x01,
+    0x00,
+    0x01,
+    WBVAL(65),
+
+    // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x01),
+    // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x02),
+    // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x03, 0x02),
+    // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
+    MIDI_JACK_DESCRIPTOR_INIT(0x01),
+    // OUT endpoint descriptor
+    0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
+    0x05, 0x25, 0x01, 0x01, 0x01,
+
+    // IN endpoint descriptor
+    0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
+    0x05, 0x25, 0x01, 0x01, 0x03
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB MIDI DEMO",        /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor midi_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t midi_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -141,15 +253,16 @@ const uint8_t midi_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[MIDI_EP_MPS];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[MIDI_EP_MPS];
@@ -204,7 +317,11 @@ struct usbd_endpoint midi_in_ep = {
 
 void midi_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &midi_descriptor);
+#else
     usbd_desc_register(busid, midi_descriptor);
+#endif
     usbd_add_interface(busid, &intf0);
     usbd_add_interface(busid, &intf1);
     usbd_add_endpoint(busid, &midi_out_ep);

+ 68 - 0
components/drivers/usb/cherryusb/demo/msc_ram_template.c

@@ -22,6 +22,69 @@
 #define MSC_MAX_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB MSC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor msc_ram_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t msc_ram_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -99,6 +162,7 @@ const uint8_t msc_ram_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static void usbd_event_handler(uint8_t busid, uint8_t event)
 {
@@ -158,7 +222,11 @@ static struct usbd_interface intf0;
 
 void msc_ram_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &msc_ram_descriptor);
+#else
     usbd_desc_register(busid, msc_ram_descriptor);
+#endif
     usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
 
     usbd_initialize(busid, reg_base, usbd_event_handler);

+ 0 - 172
components/drivers/usb/cherryusb/demo/msc_storage_template.c

@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "usbd_core.h"
-#include "usbd_msc.h"
-
-#ifdef __RT_THREAD_H__
-
-#define MSC_IN_EP  0x81
-#define MSC_OUT_EP 0x02
-
-#define USBD_VID           0xFFFF
-#define USBD_PID           0xFFFF
-#define USBD_MAX_POWER     100
-#define USBD_LANGID_STRING 1033
-
-#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
-
-#ifdef CONFIG_USB_HS
-#define MSC_MAX_MPS 512
-#else
-#define MSC_MAX_MPS 64
-#endif
-
-
-const uint8_t msc_storage_descriptor[] = {
-    USB_DEVICE_DESCRIPTOR_INIT(USB_1_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
-    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
-    MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
-    ///////////////////////////////////////
-    /// string0 descriptor
-    ///////////////////////////////////////
-    USB_LANGID_INIT(USBD_LANGID_STRING),
-    ///////////////////////////////////////
-    /// string1 descriptor
-    ///////////////////////////////////////
-    0x14,                       /* bLength */
-    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
-    'C', 0x00,                  /* wcChar0 */
-    'h', 0x00,                  /* wcChar1 */
-    'e', 0x00,                  /* wcChar2 */
-    'r', 0x00,                  /* wcChar3 */
-    'r', 0x00,                  /* wcChar4 */
-    'y', 0x00,                  /* wcChar5 */
-    'U', 0x00,                  /* wcChar6 */
-    'S', 0x00,                  /* wcChar7 */
-    'B', 0x00,                  /* wcChar8 */
-    ///////////////////////////////////////
-    /// string2 descriptor
-    ///////////////////////////////////////
-    0x26,                       /* bLength */
-    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
-    'C', 0x00,                  /* wcChar0 */
-    'h', 0x00,                  /* wcChar1 */
-    'e', 0x00,                  /* wcChar2 */
-    'r', 0x00,                  /* wcChar3 */
-    'r', 0x00,                  /* wcChar4 */
-    'y', 0x00,                  /* wcChar5 */
-    'U', 0x00,                  /* wcChar6 */
-    'S', 0x00,                  /* wcChar7 */
-    'B', 0x00,                  /* wcChar8 */
-    ' ', 0x00,                  /* wcChar9 */
-    'M', 0x00,                  /* wcChar10 */
-    'S', 0x00,                  /* wcChar11 */
-    'C', 0x00,                  /* wcChar12 */
-    ' ', 0x00,                  /* wcChar13 */
-    'D', 0x00,                  /* wcChar14 */
-    'E', 0x00,                  /* wcChar15 */
-    'M', 0x00,                  /* wcChar16 */
-    'O', 0x00,                  /* wcChar17 */
-    ///////////////////////////////////////
-    /// string3 descriptor
-    ///////////////////////////////////////
-    0x16,                       /* bLength */
-    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
-    '2', 0x00,                  /* wcChar0 */
-    '0', 0x00,                  /* wcChar1 */
-    '2', 0x00,                  /* wcChar2 */
-    '2', 0x00,                  /* wcChar3 */
-    '1', 0x00,                  /* wcChar4 */
-    '2', 0x00,                  /* wcChar5 */
-    '3', 0x00,                  /* wcChar6 */
-    '4', 0x00,                  /* wcChar7 */
-    '5', 0x00,                  /* wcChar8 */
-    '6', 0x00,                  /* wcChar9 */
-#ifdef CONFIG_USB_HS
-    ///////////////////////////////////////
-    /// device qualifier descriptor
-    ///////////////////////////////////////
-    0x0a,
-    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
-    0x00,
-    0x02,
-    0x00,
-    0x00,
-    0x00,
-    0x40,
-    0x00,
-    0x00,
-#endif
-    0x00
-};
-
-struct usbd_interface intf0;
-
-/* assume the block device is 512M */
-#define BLOCK_DEV_NAME      "sd0"
-#define BLOCK_SIZE          512U
-#define BLOCK_COUNT         0x1024U * 0x1024U
-static rt_device_t blk_dev = RT_NULL;
-
-static void usbd_event_handler(uint8_t busid, uint8_t event)
-{
-    switch (event) {
-        case USBD_EVENT_RESET:
-            break;
-        case USBD_EVENT_CONNECTED:
-            break;
-        case USBD_EVENT_DISCONNECTED:
-            break;
-        case USBD_EVENT_RESUME:
-            break;
-        case USBD_EVENT_SUSPEND:
-            break;
-        case USBD_EVENT_CONFIGURED:
-            break;
-        case USBD_EVENT_SET_REMOTE_WAKEUP:
-            break;
-        case USBD_EVENT_CLR_REMOTE_WAKEUP:
-            break;
-
-        default:
-            break;
-    }
-}
-
-void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
-{
-    *block_num = BLOCK_COUNT;
-    *block_size = BLOCK_SIZE;
-}
-
-int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
-{
-    rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
-    return 0;
-}
-
-int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
-{
-    rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
-    return 0;
-}
-
-void msc_storage_init(uint8_t busid, uintptr_t reg_base)
-{
-    rt_err_t res;
-
-    blk_dev = rt_device_find(BLOCK_DEV_NAME);
-    RT_ASSERT(blk_dev);
-
-    res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
-    RT_ASSERT(res == RT_EOK);
-
-    usbd_desc_register(busid, msc_storage_descriptor);
-    usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
-
-    usbd_initialize(busid, reg_base, usbd_event_handler);
-}
-#endif

+ 14 - 10
components/drivers/usb/cherryusb/demo/usb_host.c

@@ -58,10 +58,10 @@ void usbh_cdc_acm_callback(void *arg, int nbytes)
     }
 }
 
-static void usbh_cdc_acm_thread(void *argument)
+static void usbh_cdc_acm_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
-    struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)argument;
+    struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     /* test with only one buffer, if you have more cdc acm class, modify by yourself */
 #if TEST_USBH_CDC_SPEED
@@ -133,10 +133,10 @@ void usbh_hid_callback(void *arg, int nbytes)
     }
 }
 
-static void usbh_hid_thread(void *argument)
+static void usbh_hid_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
-    struct usbh_hid *hid_class = (struct usbh_hid *)argument;
+    struct usbh_hid *hid_class = (struct usbh_hid *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     ;
 
     /* test with only one buffer, if you have more hid class, modify by yourself */
@@ -222,13 +222,18 @@ unmount:
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t partition_table[512];
 
-static void usbh_msc_thread(void *argument)
+static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     int ret;
-    struct usbh_msc *msc_class = (struct usbh_msc *)argument;
+    struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     /* test with only one buffer, if you have more msc class, modify by yourself */
-#if 1
+#if TEST_USBH_MSC_FATFS == 0
+    ret = usbh_msc_scsi_init(msc_class);
+    if (ret < 0) {
+        USB_LOG_RAW("scsi_init error,ret:%d\r\n", ret);
+        goto delete;
+    }
     /* get the partition table */
     ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
     if (ret < 0) {
@@ -242,11 +247,10 @@ static void usbh_msc_thread(void *argument)
         USB_LOG_RAW("%02x ", partition_table[i]);
     }
     USB_LOG_RAW("\r\n");
-#endif
-
-#if TEST_USBH_MSC_FATFS
+#else
     usb_msc_fatfs_test();
 #endif
+
     // clang-format off
 delete:
     usb_osal_thread_delete(NULL);

+ 119 - 0
components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c

@@ -103,6 +103,120 @@
 
 #define HID_KEYBOARD_REPORT_DESC_SIZE 63
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
+    VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
+    VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
+    VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
+    /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
+    USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
+    AUDIO_AC_DESCRIPTOR_INIT(0x02, 0x03, AUDIO_AC_SIZ, 0x00, 0x03, 0x04),
+    AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
+    AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
+    AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
+    AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
+    AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
+    AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
+    AUDIO_AS_DESCRIPTOR_INIT(0x03, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
+                             EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
+    AUDIO_AS_DESCRIPTOR_INIT(0x04, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
+                             EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x05,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                          /* bCountryCode: Hardware target country */
+    0x01,                          /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                          /* bDescriptorType */
+    HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UVC UAC HID DEMO", /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor video_audio_hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t video_audio_hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -231,6 +345,7 @@ const uint8_t video_audio_hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
@@ -422,7 +537,11 @@ struct audio_entity_info audio_entity_table[] = {
 
 void composite_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &video_audio_hid_descriptor);
+#else
     usbd_desc_register(busid, video_audio_hid_descriptor);
+#endif
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_endpoint(busid, &video_in_ep);

+ 76 - 0
components/drivers/usb/cherryusb/demo/video_static_h264_template.c

@@ -50,6 +50,77 @@
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
+    VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
+    VIDEO_VS_FORMAT_H264_DESCRIPTOR_INIT(0x01, 0x01),
+    VIDEO_VS_FRAME_H264_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
+    /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
+    USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UVC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor video_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t video_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -136,6 +207,7 @@ const uint8_t video_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 volatile bool tx_flag = 0;
 volatile bool iso_tx_busy = false;
@@ -198,7 +270,11 @@ struct usbd_interface intf1;
 
 void video_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &video_descriptor);
+#else
     usbd_desc_register(busid, video_descriptor);
+#endif
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_endpoint(busid, &video_in_ep);

+ 76 - 0
components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c

@@ -50,6 +50,77 @@
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
+    VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
+    VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
+    VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
+    /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
+    USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UVC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor video_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t video_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -136,6 +207,7 @@ const uint8_t video_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 volatile bool tx_flag = 0;
 volatile bool iso_tx_busy = false;
@@ -198,7 +270,11 @@ struct usbd_interface intf1;
 
 void video_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &video_descriptor);
+#else
     usbd_desc_register(busid, video_descriptor);
+#endif
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_endpoint(busid, &video_in_ep);

+ 78 - 0
components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c

@@ -51,6 +51,79 @@
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
+    VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
+    VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(0x01, 0x01, VIDEO_GUID_YUY2),
+    VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
+    VIDEO_VS_COLOR_MATCHING_DESCRIPTOR_INIT(),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
+    /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
+    USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
+
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB UVC DEMO",         /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor video_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+#else
 const uint8_t video_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -138,6 +211,7 @@ const uint8_t video_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 volatile bool tx_flag = 0;
 volatile bool iso_tx_busy = false;
@@ -200,7 +274,11 @@ struct usbd_interface intf1;
 
 void video_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &video_descriptor);
+#else
     usbd_desc_register(busid, video_descriptor);
+#endif
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
     usbd_add_endpoint(busid, &video_in_ep);

+ 118 - 9
components/drivers/usb/cherryusb/demo/webusb_hid_template.c

@@ -149,6 +149,105 @@ struct usb_bos_descriptor bos_desc = {
     .string_len = USBD_BOS_WTOTALLENGTH
 };
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                          /* bCountryCode: Hardware target country */
+    0x01,                          /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                          /* bDescriptorType */
+    HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+    USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB WEBUSB HID DEMO",  /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor webusb_hid_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback,
+    .msosv2_descriptor = &msosv2_desc,
+    .webusb_url_descriptor = &webusb_url_desc,
+    .bos_descriptor = &bos_desc
+};
+#else
 static const uint8_t webusb_hid_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -207,7 +306,7 @@ static const uint8_t webusb_hid_descriptor[] = {
     ///////////////////////////////////////
     /// string2 descriptor
     ///////////////////////////////////////
-    0x26,                       /* bLength */
+    0x2C,                       /* bLength */
     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
     'C', 0x00,                  /* wcChar0 */
     'h', 0x00,                  /* wcChar1 */
@@ -219,14 +318,17 @@ static const uint8_t webusb_hid_descriptor[] = {
     'S', 0x00,                  /* wcChar7 */
     'B', 0x00,                  /* wcChar8 */
     ' ', 0x00,                  /* wcChar9 */
-    'H', 0x00,                  /* wcChar10 */
-    'I', 0x00,                  /* wcChar11 */
-    'D', 0x00,                  /* wcChar12 */
-    ' ', 0x00,                  /* wcChar13 */
-    'D', 0x00,                  /* wcChar14 */
-    'E', 0x00,                  /* wcChar15 */
-    'M', 0x00,                  /* wcChar16 */
-    'O', 0x00,                  /* wcChar17 */
+    'W', 0x00,                  /* wcChar10 */
+    'E', 0x00,                  /* wcChar11 */
+    'B', 0x00,                  /* wcChar12 */
+    'U', 0x00,                  /* wcChar13 */
+    'S', 0x00,                  /* wcChar14 */
+    'B', 0x00,                  /* wcChar15 */
+    ' ', 0x00,                  /* wcChar16 */
+    'D', 0x00,                  /* wcChar17 */
+    'E', 0x00,                  /* wcChar18 */
+    'M', 0x00,                  /* wcChar19 */
+    'O', 0x00,                  /* wcChar20 */
     ///////////////////////////////////////
     /// string3 descriptor
     ///////////////////////////////////////
@@ -259,6 +361,7 @@ static const uint8_t webusb_hid_descriptor[] = {
 #endif
     0x00
 };
+#endif
 
 /* USB HID device Configuration Descriptor */
 static uint8_t hid_desc[9] __ALIGN_END = {
@@ -355,10 +458,16 @@ static struct usbd_interface intf0;
 
 void webusb_hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &webusb_hid_descriptor);
+#else
     usbd_desc_register(busid, webusb_hid_descriptor);
+#endif
+#ifndef CONFIG_USBDEV_ADVANCE_DESC
     usbd_bos_desc_register(busid, &bos_desc);
     usbd_msosv2_desc_register(busid, &msosv2_desc);
     usbd_webusb_desc_register(busid, &webusb_url_desc);
+#endif
     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
     usbd_add_endpoint(busid, &hid_in_ep);
 

+ 89 - 9
components/drivers/usb/cherryusb/demo/winusb1.0_template.c

@@ -188,6 +188,79 @@ struct usb_msosv1_descriptor msosv1_desc = {
 #define WINUSB_EP_MPS 64
 #endif
 
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x04),
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, 0x02, WINUSB_EP_MPS, 0x00),
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, 0x02, WINUSB_EP_MPS, 0x00),
+#if DOUBLE_WINUSB == 1
+    USB_INTERFACE_DESCRIPTOR_INIT(0x01, 0x00, 0x02, 0xff, 0xff, 0x00, 0x05),
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP2, 0x02, WINUSB_EP_MPS, 0x00),
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP2, 0x02, WINUSB_EP_MPS, 0x00),
+#endif
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB WINUSB DEMO",      /* Product */
+    "2022123456",                 /* Serial Number */
+    "CherryUSB WINUSB DEMO 1",    /* STRING4 */
+    "CherryUSB WINUSB DEMO 2",    /* STRING5 */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 5) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor winusb_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback,
+    .msosv1_descriptor = &msosv1_desc
+};
+#else
 const uint8_t winusb_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@@ -252,12 +325,12 @@ const uint8_t winusb_descriptor[] = {
     '0', 0x00,                  /* wcChar1 */
     '2', 0x00,                  /* wcChar2 */
     '1', 0x00,                  /* wcChar3 */
-    '0', 0x00,                  /* wcChar4 */
-    '3', 0x00,                  /* wcChar5 */
-    '1', 0x00,                  /* wcChar6 */
-    '0', 0x00,                  /* wcChar7 */
-    '0', 0x00,                  /* wcChar8 */
-    '0', 0x00,                  /* wcChar9 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+    '6', 0x00,                  /* wcChar9 */
     ///////////////////////////////////////
     /// string4 descriptor
     ///////////////////////////////////////
@@ -322,15 +395,16 @@ const uint8_t winusb_descriptor[] = {
     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
     0x00,
     0x02,
-    0x02,
-    0x02,
-    0x01,
+    0x00,
+    0x00,
+    0x00,
     0x40,
     0x00,
     0x00,
 #endif
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@@ -446,8 +520,14 @@ struct usbd_interface intf1;
 
 void winusb_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &winusb_descriptor);
+#else
     usbd_desc_register(busid, winusb_descriptor);
+#endif
+#ifndef CONFIG_USBDEV_ADVANCE_DESC
     usbd_msosv1_desc_register(busid, &msosv1_desc);
+#endif
     usbd_add_interface(busid, &intf0);
     usbd_add_endpoint(busid, &winusb_out_ep1);
     usbd_add_endpoint(busid, &winusb_in_ep1);

+ 157 - 30
components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c

@@ -145,6 +145,89 @@ __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
 #endif
 };
 
+struct usb_msosv2_descriptor msosv2_desc = {
+    .vendor_code = USBD_WINUSB_VENDOR_CODE,
+    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
+    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
+};
+
+struct usb_bos_descriptor bos_desc = {
+    .string = USBD_BinaryObjectStoreDescriptor,
+    .string_len = USBD_BOS_WTOTALLENGTH
+};
+
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    /* Configuration 0 */
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    /* Interface 0 */
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
+    /* Endpoint OUT 2 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /* Endpoint IN 1 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00)
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x10,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB WINUSB DEMO",      /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor winusbv2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback,
+    .msosv2_descriptor = &msosv2_desc,
+    .bos_descriptor = &bos_desc
+};
+#else
 const uint8_t winusbv2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
     /* Configuration 0 */
@@ -170,7 +253,9 @@ const uint8_t winusbv2_descriptor[] = {
     'U', 0x00,                  /* wcChar6 */
     'S', 0x00,                  /* wcChar7 */
     'B', 0x00,                  /* wcChar8 */
-    /* String 2 (Product) */
+    ///////////////////////////////////////
+    /// string2 descriptor
+    ///////////////////////////////////////
     0x2C,                       /* bLength */
     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
     'C', 0x00,                  /* wcChar0 */
@@ -194,21 +279,21 @@ const uint8_t winusbv2_descriptor[] = {
     'E', 0x00,                  /* wcChar18 */
     'M', 0x00,                  /* wcChar19 */
     'O', 0x00,                  /* wcChar20 */
-    /* String 3 (Serial Number) */
-    0x1A,                       // bLength
-    USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
-    '0', 0,                     // wcChar0
-    '1', 0,                     // wcChar1
-    '2', 0,                     // wcChar2
-    '3', 0,                     // wcChar3
-    '4', 0,                     // wcChar4
-    '5', 0,                     // wcChar5
-    'A', 0,                     // wcChar6
-    'B', 0,                     // wcChar7
-    'C', 0,                     // wcChar8
-    'D', 0,                     // wcChar9
-    'E', 0,                     // wcChar10
-    'F', 0,                     // wcChar11
+    ///////////////////////////////////////
+    /// string3 descriptor
+    ///////////////////////////////////////
+    0x16,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    '2', 0x00,                  /* wcChar0 */
+    '0', 0x00,                  /* wcChar1 */
+    '2', 0x00,                  /* wcChar2 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+    '6', 0x00,                  /* wcChar9 */
 #ifdef CONFIG_USB_HS
     /* Device Qualifier */
     0x0a,
@@ -225,6 +310,7 @@ const uint8_t winusbv2_descriptor[] = {
     /* End */
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@@ -248,6 +334,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
             ep_tx_busy_flag = false;
             /* setup first out ep read transfer */
             usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
+            usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
             break;
         case USBD_EVENT_SET_REMOTE_WAKEUP:
             break;
@@ -283,6 +370,30 @@ void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
     }
 }
 
+void usbd_cdc_acm_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual out len:%d\r\n", nbytes);
+    // for (int i = 0; i < 100; i++) {
+    //     printf("%02x ", read_buffer[i]);
+    // }
+    // printf("\r\n");
+    usbd_ep_start_write(busid, CDC_IN_EP, read_buffer, nbytes);
+    /* setup next out ep read transfer */
+    usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
+}
+
+void usbd_cdc_acm_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual in len:%d\r\n", nbytes);
+
+    if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
+        /* send zlp */
+        usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
+    } else {
+        ep_tx_busy_flag = false;
+    }
+}
+
 struct usbd_endpoint winusb_out_ep1 = {
     .ep_addr = WINUSB_OUT_EP,
     .ep_cb = usbd_winusb_out
@@ -295,35 +406,29 @@ struct usbd_endpoint winusb_in_ep1 = {
 
 static struct usbd_endpoint cdc_out_ep = {
     .ep_addr = CDC_OUT_EP,
-    .ep_cb = NULL
+    .ep_cb = usbd_cdc_acm_out
 };
 
 static struct usbd_endpoint cdc_in_ep = {
     .ep_addr = CDC_IN_EP,
-    .ep_cb = NULL
+    .ep_cb = usbd_cdc_acm_in
 };
 
 struct usbd_interface winusb_intf;
 struct usbd_interface intf1;
 struct usbd_interface intf2;
 
-struct usb_msosv2_descriptor msosv2_desc = {
-    .vendor_code = USBD_WINUSB_VENDOR_CODE,
-    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
-    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
-};
-
-struct usb_bos_descriptor bos_desc = {
-    .string = USBD_BinaryObjectStoreDescriptor,
-    .string_len = USBD_BOS_WTOTALLENGTH
-};
-
 void winusbv2_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &winusbv2_descriptor);
+#else
     usbd_desc_register(busid, winusbv2_descriptor);
+#endif
+#ifndef CONFIG_USBDEV_ADVANCE_DESC
     usbd_bos_desc_register(busid, &bos_desc);
     usbd_msosv2_desc_register(busid, &msosv2_desc);
-
+#endif
     /*!< winusb */
     usbd_add_interface(busid, &winusb_intf);
     usbd_add_endpoint(busid, &winusb_out_ep1);
@@ -336,4 +441,26 @@ void winusbv2_init(uint8_t busid, uintptr_t reg_base)
     usbd_add_endpoint(busid, &cdc_in_ep);
 
     usbd_initialize(busid, reg_base, usbd_event_handler);
+}
+
+volatile uint8_t dtr_enable = 0;
+
+void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
+{
+    if (dtr) {
+        dtr_enable = 1;
+    } else {
+        dtr_enable = 0;
+    }
+}
+
+void cdc_acm_data_send_with_dtr_test(uint8_t busid)
+{
+    if (dtr_enable) {
+        memset(&write_buffer[10], 'a', 2038);
+        ep_tx_busy_flag = true;
+        usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
+        while (ep_tx_busy_flag) {
+        }
+    }
 }

+ 138 - 28
components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c

@@ -151,6 +151,119 @@ __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
 #endif
 };
 
+struct usb_msosv2_descriptor msosv2_desc = {
+    .vendor_code = USBD_WINUSB_VENDOR_CODE,
+    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
+    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
+};
+
+struct usb_bos_descriptor bos_desc = {
+    .string = USBD_BinaryObjectStoreDescriptor,
+    .string_len = USBD_BOS_WTOTALLENGTH
+};
+
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    /* Configuration 0 */
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    /* Interface 0 */
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
+    /* Endpoint OUT 2 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /* Endpoint IN 1 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x01,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                       /* bCountryCode: Hardware target country */
+    0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                       /* bDescriptorType */
+    HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x10,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 }, /* Langid */
+    "CherryUSB",                  /* Manufacturer */
+    "CherryUSB WINUSB DEMO",      /* Product */
+    "2022123456",                 /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index > 3) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor winusbv2_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback,
+    .msosv2_descriptor = &msosv2_desc,
+    .bos_descriptor = &bos_desc
+};
+#else
 const uint8_t winusbv2_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
     /* Configuration 0 */
@@ -206,7 +319,9 @@ const uint8_t winusbv2_descriptor[] = {
     'U', 0x00,                  /* wcChar6 */
     'S', 0x00,                  /* wcChar7 */
     'B', 0x00,                  /* wcChar8 */
-    /* String 2 (Product) */
+    ///////////////////////////////////////
+    /// string2 descriptor
+    ///////////////////////////////////////
     0x2C,                       /* bLength */
     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
     'C', 0x00,                  /* wcChar0 */
@@ -230,21 +345,21 @@ const uint8_t winusbv2_descriptor[] = {
     'E', 0x00,                  /* wcChar18 */
     'M', 0x00,                  /* wcChar19 */
     'O', 0x00,                  /* wcChar20 */
-    /* String 3 (Serial Number) */
-    0x1A,                       // bLength
-    USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
-    '0', 0,                     // wcChar0
-    '1', 0,                     // wcChar1
-    '2', 0,                     // wcChar2
-    '3', 0,                     // wcChar3
-    '4', 0,                     // wcChar4
-    '5', 0,                     // wcChar5
-    'A', 0,                     // wcChar6
-    'B', 0,                     // wcChar7
-    'C', 0,                     // wcChar8
-    'D', 0,                     // wcChar9
-    'E', 0,                     // wcChar10
-    'F', 0,                     // wcChar11
+    ///////////////////////////////////////
+    /// string3 descriptor
+    ///////////////////////////////////////
+    0x16,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    '2', 0x00,                  /* wcChar0 */
+    '0', 0x00,                  /* wcChar1 */
+    '2', 0x00,                  /* wcChar2 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+    '6', 0x00,                  /* wcChar9 */
 #ifdef CONFIG_USB_HS
     /* Device Qualifier */
     0x0a,
@@ -261,6 +376,7 @@ const uint8_t winusbv2_descriptor[] = {
     /* End */
     0x00
 };
+#endif
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@@ -411,23 +527,17 @@ static struct usbd_endpoint hid_in_ep = {
 struct usbd_interface winusb_intf;
 struct usbd_interface intf1;
 
-struct usb_msosv2_descriptor msosv2_desc = {
-    .vendor_code = USBD_WINUSB_VENDOR_CODE,
-    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
-    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
-};
-
-struct usb_bos_descriptor bos_desc = {
-    .string = USBD_BinaryObjectStoreDescriptor,
-    .string_len = USBD_BOS_WTOTALLENGTH
-};
-
 void winusbv2_init(uint8_t busid, uintptr_t reg_base)
 {
+#ifdef CONFIG_USBDEV_ADVANCE_DESC
+    usbd_desc_register(busid, &winusbv2_descriptor);
+#else
     usbd_desc_register(busid, winusbv2_descriptor);
+#endif
+#ifndef CONFIG_USBDEV_ADVANCE_DESC
     usbd_bos_desc_register(busid, &bos_desc);
     usbd_msosv2_desc_register(busid, &msosv2_desc);
-
+#endif
     /*!< winusb */
     usbd_add_interface(busid, &winusb_intf);
     usbd_add_endpoint(busid, &winusb_out_ep1);

+ 1 - 1
components/drivers/usb/cherryusb/idf_component.yml

@@ -1,4 +1,4 @@
-version: "1.4.2"
+version: "1.4.3"
 description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
 tags:
   - usb

+ 2 - 0
components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c

@@ -26,6 +26,8 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
 void usb_osal_thread_delete(usb_osal_thread_t thread)
 {
     if (thread == NULL) {
+        rt_thread_t self = rt_thread_self();
+        rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
         return;
     }
 

+ 27 - 37
components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c

@@ -42,6 +42,12 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t msc_sector[512];
 
 static rt_err_t rt_udisk_init(rt_device_t dev)
 {
+    struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
+
+    if (usbh_msc_scsi_init(msc_class) < 0) {
+        return -RT_ERROR;
+    }
+
     return RT_EOK;
 }
 
@@ -157,39 +163,35 @@ const static struct rt_device_ops udisk_device_ops = {
 };
 #endif
 
-int udisk_init(struct usbh_msc *msc_class)
+static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
-    rt_err_t ret = 0;
-    rt_uint8_t i;
-    struct dfs_partition part0;
-    struct rt_device *dev;
+    struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
     char name[CONFIG_USBHOST_DEV_NAMELEN];
     char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
-
-    dev = rt_malloc(sizeof(struct rt_device));
-    memset(dev, 0, sizeof(struct rt_device));
+    int ret;
 
     snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
     snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
 
-    ret = usbh_msc_scsi_read10(msc_class, 0, msc_sector, 1);
-    if (ret != RT_EOK) {
-        rt_kprintf("usb mass_storage read failed\n");
-        rt_free(dev);
-        return ret;
+    ret = dfs_mount(name, mount_point, "elm", 0, 0);
+    if (ret == 0) {
+        rt_kprintf("udisk: %s mount successfully\n", name);
+    } else {
+        rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
     }
 
-    for (i = 0; i < 4; i++) {
-        /* Get the first partition */
-        ret = dfs_filesystem_get_partition(&part0, msc_sector, i);
-        if (ret == RT_EOK) {
-            rt_kprintf("Found partition %d: type = %d, offet=0x%x, size=0x%x\n",
-                       i, part0.type, part0.offset, part0.size);
-            break;
-        } else {
-            break;
-        }
-    }
+    usb_osal_thread_delete(NULL);
+}
+
+void usbh_msc_run(struct usbh_msc *msc_class)
+{
+    struct rt_device *dev;
+    char name[CONFIG_USBHOST_DEV_NAMELEN];
+
+    dev = rt_malloc(sizeof(struct rt_device));
+    memset(dev, 0, sizeof(struct rt_device));
+
+    snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
 
     dev->type = RT_Device_Class_Block;
 #ifdef RT_USING_DEVICE_OPS
@@ -204,19 +206,7 @@ int udisk_init(struct usbh_msc *msc_class)
 
     rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
 
-    ret = dfs_mount(name, mount_point, "elm", 0, 0);
-    if (ret == 0) {
-        rt_kprintf("udisk: %s mount successfully\n", name);
-    } else {
-        rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
-    }
-
-    return ret;
-}
-
-void usbh_msc_run(struct usbh_msc *msc_class)
-{
-    udisk_init(msc_class);
+    usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
 }
 
 void usbh_msc_stop(struct usbh_msc *msc_class)

+ 1304 - 0
components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c

@@ -0,0 +1,1304 @@
+/*
+ * Copyright (c) 2023, Artinchip Technology Co., Ltd
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <rtconfig.h>
+#include "usbd_core.h"
+#include "usb_dc_aic_reg.h"
+
+// clang-format off
+#ifndef   __UNALIGNED_UINT32_WRITE
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wpacked"
+  #pragma GCC diagnostic ignored "-Wattributes"
+  __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+  #pragma GCC diagnostic pop
+  #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef   __UNALIGNED_UINT32_READ
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wpacked"
+  #pragma GCC diagnostic ignored "-Wattributes"
+  __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+  #pragma GCC diagnostic pop
+  #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+// clang-format on
+
+#define FS_PORT 0
+#define HS_PORT 1
+
+#ifndef CONFIG_USB_AIC_DC_PORT
+#error "please select CONFIG_USB_AIC_DC_PORT with FS_PORT or HS_PORT"
+#endif
+
+#ifndef USB_BASE
+#define USB_BASE CONFIG_USB_AIC_DC_BASE
+#endif
+
+#ifdef LPKG_CHERRYUSB_DEVICE_HID_IO_TEMPLATE
+#define USB_RAM_SIZE 1024 /* define with maximum value*/
+#else
+#define USB_RAM_SIZE 512  /* define with maximum value*/
+#endif
+
+#ifndef USB_NUM_BIDIR_ENDPOINTS
+#define USB_NUM_BIDIR_ENDPOINTS 5 /* define with minimum value*/
+#endif
+
+#define AIC_UDC_REG      ((AIC_UDC_RegDef *)(USB_BASE))
+#define AIC_EP_FIFO(i)  *(__IO uint32_t *)(USB_BASE + AIC_EP_FIFO_BASE + ((i)*AIC_EP_FIFO_SIZE))
+
+static uint8_t g_aic_udc_ibuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE);
+static uint8_t g_aic_udc_obuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE);
+
+/* Endpoint state */
+struct aic_ep_state {
+    uint16_t ep_mps;    /* Endpoint max packet size */
+    uint8_t ep_type;    /* Endpoint type */
+    uint8_t ep_stalled; /* Endpoint stall flag */
+    uint8_t *xfer_buf;
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    uint8_t *xfer_align_buf;
+    uint32_t xfer_align_len;
+#endif
+    uint32_t xfer_len;
+    uint32_t actual_xfer_len;
+};
+
+extern uint32_t usbd_clk;
+
+/* Driver state */
+/*USB_NOCACHE_RAM_SECTION*/ struct aic_udc {
+    USB_MEM_ALIGNX struct usb_setup_packet setup;
+    USB_MEM_ALIGNX struct aic_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS];  /*!< IN endpoint parameters*/
+    struct aic_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
+    uint32_t tx_fifo_map;
+} g_aic_udc;
+
+uint8_t rst_allow = 0;
+uint8_t ep0_ctrl_stage = 0; /* 1 = setup stage, 2 = data stage, 3 = status stage */
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+void aic_udc_dcache_clean(uintptr_t addr, uint32_t len)
+{
+    aicos_dcache_clean_range((size_t *)addr, len);
+}
+
+void aic_udc_dcache_invalidate(uintptr_t addr, uint32_t len)
+{
+    aicos_dcache_invalid_range((size_t *)addr, len);
+}
+
+void aic_udc_dcache_clean_invalidate(uintptr_t addr, uint32_t len)
+{
+    aicos_dcache_clean_invalid_range((size_t *)addr, len);
+}
+
+static int aic_udc_ep_buf_alloc(struct aic_ep_state *ep, uint32_t len,
+                                uint8_t *sbuf)
+{
+    ep->xfer_len = len;
+    if (len % CACHE_LINE_SIZE)
+        ep->xfer_align_len = ALIGN_UP(len, CACHE_LINE_SIZE);
+    else
+        ep->xfer_align_len = len;
+
+    if (ep->xfer_align_len > USB_RAM_SIZE) {
+        ep->xfer_align_buf = aicos_malloc_align(0, ep->xfer_align_len,
+                                                CACHE_LINE_SIZE);
+        if (!ep->xfer_align_buf) {
+            USB_LOG_ERR("alloc error.\r\n");
+            return -5;
+        }
+    } else {
+        ep->xfer_align_buf = sbuf;
+    }
+
+    return 0;
+}
+
+static void aic_udc_ep_buf_free(struct aic_ep_state *ep, uint8_t *sbuf)
+{
+    if (!ep->xfer_align_buf)
+        return;
+
+    /* Whether the buf is allocated dynamically */
+    if (ep->xfer_align_buf != sbuf)
+        aicos_free_align(0, ep->xfer_align_buf);
+
+    ep->xfer_align_buf = NULL;
+    ep->xfer_align_len = 0;
+}
+
+static int aic_udc_ibuf_alloc(struct aic_ep_state *ep, uint32_t len)
+{
+    return aic_udc_ep_buf_alloc(ep, len, g_aic_udc_ibuf);
+}
+
+static int aic_udc_obuf_alloc(struct aic_ep_state *ep, uint32_t len)
+{
+    return aic_udc_ep_buf_alloc(ep, len, g_aic_udc_obuf);
+}
+
+static void aic_udc_ibuf_free(struct aic_ep_state *ep)
+{
+    aic_udc_ep_buf_free(ep, g_aic_udc_ibuf);
+}
+
+static void aic_udc_obuf_free(struct aic_ep_state *ep)
+{
+    aic_udc_ep_buf_free(ep, g_aic_udc_obuf);
+}
+#else
+#define aic_udc_dcache_clean(addr, len)
+#define aic_udc_dcache_invalidate(addr, len)
+#define aic_udc_dcache_clean_invalidate(addr, len)
+#endif
+
+static void aic_set_dma_nextep(void)
+{
+    uint32_t i;
+
+    /* dma to set the next-endpoint pointer. */
+    for (i = 0; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
+        uint32_t next = ((i + 1) % USB_NUM_BIDIR_ENDPOINTS) << DEPCTL_NEXT_EP_BIT;
+
+        AIC_UDC_REG->inepcfg[i] &= ~DEPCTL_NEXT_EP_MASK;
+        AIC_UDC_REG->inepcfg[i] |= next;
+    }
+}
+
+static inline int aic_reset(void)
+{
+    uint32_t count = 0U;
+
+    /* Wait for AHB master IDLE state. */
+    do {
+        if (++count > 200000U) {
+            return -1;
+        }
+    } while ((AIC_UDC_REG->ahbbasic & AHBBASIC_AHBIDLE) == 0U);
+
+    /* Core Soft Reset */
+    count = 0U;
+    AIC_UDC_REG->usbdevinit |= USBDEVINIT_CSFTRST;
+
+    do {
+        if (++count > 200000U) {
+            return -1;
+        }
+    } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_CSFTRST) == USBDEVINIT_CSFTRST);
+
+    return 0;
+}
+
+static inline int aic_core_init(void)
+{
+    int ret;
+    uint32_t usb_gusbcfg =
+        0 << 19     /* ULPI Clock SuspendM */
+        | 0 << 18   /* ULPI Phy Auto Resume */
+        | 0 << 15   /* PHY Low Power Clock sel */
+        | 0x5 << 10 /* USB Turnaround time (0x5 for HS phy) */
+        | 0 << 7    /* ULPI DDR sel 0:single 8bit, 1:double 4bit */
+        /*| 0 << 6   0: high speed utmi+, 1: full speed serial*/
+#ifdef FPGA_BOARD_ARTINCHIP
+        | 1 << 4    /* 0: utmi+, 1:ulpi*/
+#else
+        | 0 << 4    /* 0: utmi+, 1:ulpi*/
+#endif
+        | 0 << 3    /* UTMI+ PHY  0:8bit, 1:16bit (ULPI PHY set 8bit) */
+        | 0x7 << 0; /* HS/FS timeout calibration**/
+
+    /* Reset after a PHY select */
+    ret = aic_reset();
+
+    /* Activate the USB Transceiver */
+    AIC_UDC_REG->usbphyif = usb_gusbcfg;
+
+    aic_set_dma_nextep();
+
+    return ret;
+}
+
+static inline int aic_flush_rxfifo(void)
+{
+    uint32_t count = 0;
+
+    AIC_UDC_REG->usbdevinit |= USBDEVINIT_RXFFLSH;
+
+    do {
+        if (++count > 200000U) {
+            return -1;
+        }
+    } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_RXFFLSH) == USBDEVINIT_RXFFLSH);
+
+    return 0;
+}
+
+static inline int aic_flush_txfifo(uint32_t num)
+{
+    uint32_t count = 0U;
+
+    AIC_UDC_REG->usbdevinit |= USBDEVINIT_TXFNUM(num & USBDEVINIT_TXFNUM_LIMIT);
+
+    do {
+        if (++count > 200000U) {
+            return -1;
+        }
+    } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_TXFFLSH) == USBDEVINIT_TXFFLSH);
+
+    return 0;
+}
+
+static void aic_set_turnaroundtime(uint32_t hclk, uint8_t speed)
+{
+    uint32_t UsbTrd;
+
+    /* The USBTRD is configured according to the tables below, depending on AHB frequency
+  used by application. In the low AHB frequency range it is used to stretch enough the USB response
+  time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access
+  latency to the Data FIFO */
+    if (speed == USB_ENUM_SPEED_FULL) {
+        if ((hclk >= 14200000U) && (hclk < 15000000U)) {
+            /* hclk Clock Range between 14.2-15 MHz */
+            UsbTrd = 0xFU;
+        } else if ((hclk >= 15000000U) && (hclk < 16000000U)) {
+            /* hclk Clock Range between 15-16 MHz */
+            UsbTrd = 0xEU;
+        } else if ((hclk >= 16000000U) && (hclk < 17200000U)) {
+            /* hclk Clock Range between 16-17.2 MHz */
+            UsbTrd = 0xDU;
+        } else if ((hclk >= 17200000U) && (hclk < 18500000U)) {
+            /* hclk Clock Range between 17.2-18.5 MHz */
+            UsbTrd = 0xCU;
+        } else if ((hclk >= 18500000U) && (hclk < 20000000U)) {
+            /* hclk Clock Range between 18.5-20 MHz */
+            UsbTrd = 0xBU;
+        } else if ((hclk >= 20000000U) && (hclk < 21800000U)) {
+            /* hclk Clock Range between 20-21.8 MHz */
+            UsbTrd = 0xAU;
+        } else if ((hclk >= 21800000U) && (hclk < 24000000U)) {
+            /* hclk Clock Range between 21.8-24 MHz */
+            UsbTrd = 0x9U;
+        } else if ((hclk >= 24000000U) && (hclk < 27700000U)) {
+            /* hclk Clock Range between 24-27.7 MHz */
+            UsbTrd = 0x8U;
+        } else if ((hclk >= 27700000U) && (hclk < 32000000U)) {
+            /* hclk Clock Range between 27.7-32 MHz */
+            UsbTrd = 0x7U;
+        } else {/* if(hclk >= 32000000) */
+            /* hclk Clock Range between 32-200 MHz */
+            UsbTrd = 0x6U;
+        }
+    } else if (speed == USB_ENUM_SPEED_HIGH) {
+        UsbTrd = USBPHYIF_HS_TRDT_VALUE;
+    } else {
+        UsbTrd = USBPHYIF_DEFAULT_TRDT_VALUE;
+    }
+
+    AIC_UDC_REG->usbphyif |= USBPHYIF_TOUTCAL_LIMIT;
+
+    AIC_UDC_REG->usbphyif &= ~USBPHYIF_USBTRDTIM_MASK;
+    AIC_UDC_REG->usbphyif |= (uint32_t)((UsbTrd << USBPHYIF_USBTRDTIM_SHIFT)
+                                        & USBPHYIF_USBTRDTIM_MASK);
+}
+
+#if 0
+static void aic_set_txfifo(uint8_t fifo, uint16_t size)
+{
+    uint8_t i;
+    uint32_t Tx_Offset;
+
+    /*  TXn min size = 16 words. (n  : Transmit FIFO index)
+      When a TxFIFO is not used, the Configuration should be as follows:
+          case 1 :  n > m    and Txn is not used    (n,m  : Transmit FIFO indexes)
+         --> Txm can use the space allocated for Txn.
+         case2  :  n < m    and Txn is not used    (n,m  : Transmit FIFO indexes)
+         --> Txn should be configured with the minimum space of 16 words
+     The FIFO is used optimally when used TxFIFOs are allocated in the top
+         of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
+     When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
+
+    Tx_Offset = AIC_UDC_REG->rxfifosiz;
+
+    if (fifo == 0U) {
+        AIC_UDC_REG->nptxfifosiz = ((uint32_t)size << 16) | Tx_Offset;
+    } else {
+        Tx_Offset += (AIC_UDC_REG->nptxfifosiz) >> 16;
+        for (i = 0U; i < (fifo - 1U); i++) {
+            Tx_Offset += (AIC_UDC_REG->txfifosiz[i] >> 16);
+        }
+
+        /* Multiply Tx_Size by 2 to get higher performance */
+        AIC_UDC_REG->txfifosiz[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
+    }
+}
+#endif
+
+static uint8_t aic_get_devspeed(void)
+{
+    uint8_t speed;
+    uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK;
+
+    if (DevEnumSpeed == USB_HIGH_30_60MHZ) {
+        speed = USB_ENUM_SPEED_HIGH;
+    } else if (DevEnumSpeed == USB_FULL_30_60MHZ) {
+        speed = USB_ENUM_SPEED_FULL;
+    } else {
+        speed = 0xFU;
+    }
+
+    return speed;
+}
+
+static void aic_ep0_start_read_setup(uint8_t *psetup)
+{
+    g_aic_udc.out_ep[0].xfer_buf = psetup;
+    g_aic_udc.out_ep[0].xfer_len = 8;
+    ep0_ctrl_stage = 1;
+
+    aic_udc_dcache_invalidate((uintptr_t)psetup, CACHE_LINE_SIZE);
+
+    AIC_UDC_REG->outeptsfsiz[0] = 0U;
+    AIC_UDC_REG->outeptsfsiz[0] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19));
+    AIC_UDC_REG->outeptsfsiz[0] |= (3U * 8U);
+    AIC_UDC_REG->outeptsfsiz[0] |= DXEPTSIZ_MULCNT_MASK;
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    AIC_UDC_REG->outepdmaaddr[0] = (uint32_t)(uintptr_t)psetup;
+#endif
+
+    /* EP enable */
+    AIC_UDC_REG->outepcfg[0] |= DEPCTL_CNAK | DEPCTL_EPENA | DEPCTL_USBACTEP;
+}
+
+void aic_ep_write(uint8_t ep_idx, uint8_t *src, uint16_t len)
+{
+    uint32_t *pSrc = (uint32_t *)src;
+    uint32_t count32b, i;
+
+    count32b = ((uint32_t)len + 3U) / 4U;
+    for (i = 0U; i < count32b; i++) {
+        AIC_EP_FIFO(ep_idx) = __UNALIGNED_UINT32_READ(pSrc);
+        pSrc++;
+    }
+}
+
+void aic_ep_read(uint8_t *dest, uint16_t len)
+{
+    uint32_t *pDest = (uint32_t *)dest;
+    uint32_t i;
+    uint32_t count32b = ((uint32_t)len + 3U) / 4U;
+
+    for (i = 0U; i < count32b; i++) {
+        __UNALIGNED_UINT32_WRITE(pDest, AIC_EP_FIFO(0U));
+        pDest++;
+    }
+}
+
+#ifndef CONFIG_USB_AIC_DMA_ENABLE
+static void aic_tx_fifo_empty_procecss(uint8_t ep_idx)
+{
+    uint32_t len;
+    //uint32_t len32b;
+
+    len = g_aic_udc.in_ep[ep_idx].xfer_len - g_aic_udc.in_ep[ep_idx].actual_xfer_len;
+    if (len > g_aic_udc.in_ep[ep_idx].ep_mps) {
+        len = g_aic_udc.in_ep[ep_idx].ep_mps;
+    }
+
+    //len32b = (len + 3U) / 4U;
+
+    while (/*((AIC_UDC_REG->ineptxsts[ep_idx] & INEPTXSTS_IN_EP_TXFIFO_STS) >= len32b) &&*/
+           (g_aic_udc.in_ep[ep_idx].actual_xfer_len < g_aic_udc.in_ep[ep_idx].xfer_len) && (g_aic_udc.in_ep[ep_idx].xfer_len != 0U)) {
+        /* Write the FIFO */
+        len = g_aic_udc.in_ep[ep_idx].xfer_len - g_aic_udc.in_ep[ep_idx].actual_xfer_len;
+        if (len > g_aic_udc.in_ep[ep_idx].ep_mps) {
+            len = g_aic_udc.in_ep[ep_idx].ep_mps;
+        }
+
+        aic_ep_write(ep_idx, g_aic_udc.in_ep[ep_idx].xfer_buf, len);
+        g_aic_udc.in_ep[ep_idx].xfer_buf += len;
+        g_aic_udc.in_ep[ep_idx].actual_xfer_len += len;
+    }
+}
+#endif
+
+/**
+  * @brief  aic_get_glb_intstatus: return the global USB interrupt status
+  * @retval status
+  */
+static inline uint32_t aic_get_glb_intstatus(void)
+{
+    uint32_t tmpreg;
+
+    tmpreg = AIC_UDC_REG->usbintsts;
+    tmpreg &= AIC_UDC_REG->usbintmsk;
+
+    return tmpreg;
+}
+
+/**
+  * @brief  aic_get_outeps_intstatus: return the USB device OUT endpoints interrupt status
+  * @retval status
+  */
+static inline uint32_t aic_get_outeps_intstatus(void)
+{
+    uint32_t tmpreg;
+
+    tmpreg = AIC_UDC_REG->usbepint;
+    tmpreg &= AIC_UDC_REG->usbepintmsk;
+
+    return ((tmpreg & 0xffff0000U) >> 16);
+}
+
+/**
+  * @brief  aic_get_ineps_intstatus: return the USB device IN endpoints interrupt status
+  * @retval status
+  */
+static inline uint32_t aic_get_ineps_intstatus(void)
+{
+    uint32_t tmpreg;
+
+    tmpreg = AIC_UDC_REG->usbepint;
+    tmpreg &= AIC_UDC_REG->usbepintmsk;
+
+    return ((tmpreg & 0xFFFFU));
+}
+
+/**
+  * @brief  Returns Device OUT EP Interrupt register
+  * @param  epnum  endpoint number
+  *          This parameter can be a value from 0 to 15
+  * @retval Device OUT EP Interrupt register
+  */
+static inline uint32_t aic_get_outep_intstatus(uint8_t epnum)
+{
+    uint32_t tmpreg;
+
+    tmpreg = AIC_UDC_REG->outepint[epnum];
+    tmpreg &= AIC_UDC_REG->outepintmsk;
+
+    return tmpreg;
+}
+
+/**
+  * @brief  Returns Device IN EP Interrupt register
+  * @param  epnum  endpoint number
+  *          This parameter can be a value from 0 to 15
+  * @retval Device IN EP Interrupt register
+  */
+static inline uint32_t aic_get_inep_intstatus(uint8_t epnum)
+{
+    uint32_t tmpreg;
+
+    tmpreg = AIC_UDC_REG->inepint[epnum];
+    tmpreg &= AIC_UDC_REG->inepintmsk;
+
+    return tmpreg;
+}
+
+__WEAK void usb_dc_low_level_init(void)
+{
+}
+
+__WEAK void usb_dc_low_level_deinit(void)
+{
+}
+
+int usb_dc_rst(void)
+{
+    for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
+        if (i == 0U) {
+            AIC_UDC_REG->inepcfg[i] = DEPCTL_SNAK;
+            AIC_UDC_REG->outepcfg[i] = DEPCTL_SNAK;
+        } else {
+            usbd_ep_close(i);
+            usbd_ep_close(i | 0x80);
+        }
+        AIC_UDC_REG->ineptsfsiz[i] = 0U;
+        AIC_UDC_REG->inepint[i] = 0xFBFFU;
+        AIC_UDC_REG->outeptsfsiz[i] = 0U;
+        AIC_UDC_REG->outepint[i] = 0xFBFFU;
+    }
+
+    AIC_UDC_REG->usbepintmsk |= 0x10001U;
+    AIC_UDC_REG->outepintmsk = CTRL_OUT_EP_SETUP_PHASE_DONE | TRANSFER_DONE;
+    AIC_UDC_REG->inepintmsk = TRANSFER_DONE;
+#ifndef CONFIG_USB_AIC_DMA_ENABLE
+    AIC_UDC_REG->inepintmsk |= INTKN_TXFEMP;
+#endif
+
+    aic_flush_txfifo(0x10U);
+    aic_flush_rxfifo();
+
+    aic_set_dma_nextep();
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
+        aic_udc_obuf_free(&g_aic_udc.out_ep[i]);
+        aic_udc_ibuf_free(&g_aic_udc.in_ep[i]);
+    }
+#endif
+
+    memset(&g_aic_udc, 0, sizeof(struct aic_udc));
+    usbd_event_reset_handler(0);
+    /* Start reading setup */
+    aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup);
+
+    return 0;
+}
+
+int usb_dc_init(uint8_t busid)
+{
+    int ret;
+    uint32_t base = 0;
+
+    memset(&g_aic_udc, 0, sizeof(struct aic_udc));
+
+    usb_dc_low_level_init();
+
+    /* Disconnect */
+    AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON;
+    /* Disable Interrupt */
+    AIC_UDC_REG->usbdevinit &= ~USBDEVINIT_GLBL_INTR_EN;
+
+    ret = aic_core_init();
+
+    for (uint8_t i = 0U; i < 2U; i++) {
+        AIC_UDC_REG->txfifosiz[i] = 0U;
+    }
+
+    /* Device mode configuration */
+    AIC_UDC_REG->usbdevconf |= PERIOD_FRAME_INTERVAL_80;
+
+#if defined(CONFIG_USB_HS)
+    /* Set Core speed to High speed mode */
+    AIC_UDC_REG->usbdevconf |= DEV_SPEED_HIGH_SPEED_20;
+#else
+
+    AIC_UDC_REG->usbdevconf |= DEV_SPEED_FULL_SPEED_20;
+#endif
+
+    ret = aic_flush_txfifo(0x10U);
+    ret = aic_flush_rxfifo();
+
+    /* Clear all pending Device Interrupts */
+    AIC_UDC_REG->inepintmsk = 0U;
+    AIC_UDC_REG->outepintmsk = 0U;
+    AIC_UDC_REG->usbepintmsk = 0U;
+
+    /* Disable all interrupts. */
+    AIC_UDC_REG->usbintmsk = 0U;
+    /* Clear any pending interrupts */
+    AIC_UDC_REG->usbintsts = 0xBFFFFFFFU;
+
+    /* Enable interrupts matching to the Device mode ONLY */
+    AIC_UDC_REG->usbintmsk = INT_RESET | INT_ENUMDONE |
+                             INT_OUT_EP | INT_IN_EP |
+                             INT_INCOMP_ISO_IN_INT | INT_INCOMP_ISO_OUT_INT;
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    AIC_UDC_REG->usbdevinit |= (USBDEVINIT_HBSTLEN_INCR4 << USBDEVINIT_HBSTLEN_SHIFT);
+    AIC_UDC_REG->usbdevinit |= USBDEVINIT_DMA_EN;
+#else
+    AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY;
+#endif
+
+    /* Assign FIFO */
+    base = 0;
+    AIC_UDC_REG->rxfifosiz = AIC_RX_FIFO_SIZE;
+    base += AIC_RX_FIFO_SIZE;
+    AIC_UDC_REG->nptxfifosiz = (AIC_NP_TX_FIFO_SIZE << 16) | base;
+    base += AIC_NP_TX_FIFO_SIZE;
+    AIC_UDC_REG->txfifosiz[0] = (AIC_PERIOD_TX_FIFO1_SIZE << 16) | base;
+    base += AIC_PERIOD_TX_FIFO1_SIZE;
+    AIC_UDC_REG->txfifosiz[1] = (AIC_PERIOD_TX_FIFO2_SIZE << 16) | base;
+
+    usb_dc_rst();
+
+    /* Enable Interrupt */
+    AIC_UDC_REG->usbdevinit |= USBDEVINIT_GLBL_INTR_EN;
+    /* Connect */
+    AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_SFTDISCON;
+
+    return ret;
+}
+
+int usb_dc_deinit(uint8_t busid)
+{
+    /* Clear Pending interrupt */
+    for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
+        AIC_UDC_REG->outepint[i] = 0xFB7FU;
+        AIC_UDC_REG->inepint[i] = 0xFB7FU;
+    }
+
+    /* Clear interrupt masks */
+    AIC_UDC_REG->inepintmsk = 0U;
+    AIC_UDC_REG->outepintmsk = 0U;
+    AIC_UDC_REG->usbepintmsk = 0U;
+
+    /* Flush the FIFO */
+    aic_flush_txfifo(0x10U);
+    aic_flush_rxfifo();
+
+    AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON;
+
+    usb_dc_low_level_deinit();
+    return 0;
+}
+
+int usbd_set_address(uint8_t busid, const uint8_t addr)
+{
+    AIC_UDC_REG->usbdevconf &= ~(DEVICE_ADDRESS_MASK);
+    AIC_UDC_REG->usbdevconf |= ((uint32_t)addr << 4) & DEVICE_ADDRESS_MASK;
+
+    rst_allow = 1;
+    return 0;
+}
+
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
+uint8_t usbd_get_port_speed(uint8_t busid)
+{
+    uint8_t speed;
+    uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK;
+
+    if (DevEnumSpeed == USB_HIGH_30_60MHZ) {
+        speed = USB_SPEED_HIGH;
+    } else if (DevEnumSpeed == USB_FULL_30_60MHZ) {
+        speed = USB_SPEED_FULL;
+    } else {
+        speed = USB_SPEED_FULL;
+    }
+
+    return speed;
+}
+
+int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
+    uint16_t ep_mps;
+    uint8_t tx_fifo_num = 0;
+    uint32_t i;
+
+    if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
+        USB_LOG_ERR("Ep addr %d overflow\r\n", ep->bEndpointAddress);
+        return -1;
+    }
+
+    if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
+        g_aic_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_aic_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+
+        AIC_UDC_REG->usbepintmsk |= DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx));
+
+        ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        if (ep_idx == 0) {
+            switch (ep_mps) {
+                case 8:
+                    ep_mps = DEPCTL0_MPS_8;
+                    break;
+                case 16:
+                    ep_mps = DEPCTL0_MPS_16;
+                    break;
+                case 32:
+                    ep_mps = DEPCTL0_MPS_32;
+                    break;
+                case 64:
+                    ep_mps = DEPCTL0_MPS_64;
+                    break;
+            }
+        }
+
+        AIC_UDC_REG->outepcfg[ep_idx] |= (ep_mps & DEPCTL_MPS_MASK) |
+                                          ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) |
+                                          DEPCTL_SETD0PID |
+                                          DEPCTL_USBACTEP;
+    } else {
+        g_aic_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_aic_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+
+        AIC_UDC_REG->usbepintmsk |= DAINT_IN_MASK & (uint32_t)(1UL << ep_idx);
+
+        /* Period IN EP alloc fifo num */
+        if (( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) ||
+            ( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
+            for (i=1; i<=2; i++) {
+                if (g_aic_udc.tx_fifo_map & (1<<i))
+                    continue;
+                g_aic_udc.tx_fifo_map |= (1 << i);
+                tx_fifo_num = i;
+                break;
+            }
+
+            if (tx_fifo_num == 0)
+                return -1;
+
+            aic_flush_txfifo(tx_fifo_num);
+        }
+
+        AIC_UDC_REG->inepcfg[ep_idx] |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & DEPCTL_MPS_MASK) |
+                                         ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) |
+                                         (tx_fifo_num << 22) |
+                                         DEPCTL_SETD0PID |
+                                         DEPCTL_USBACTEP;
+    }
+    return 0;
+}
+
+int usbd_ep_close(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    uint8_t tx_fifo_num = 0;
+    int i = 0;
+    #define DIS_EP_TIMOUT 100
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) {
+            /* (1) Wait for global nak to take effect */
+            if (!(AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF))
+                AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGOUTNAK;
+
+            for (i = 0; i < DIS_EP_TIMOUT; i++) {
+                if (AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF)
+                    break;
+                aic_udelay(1);
+            }
+
+            if (i == DIS_EP_TIMOUT)
+                USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__);
+
+            /* (2) Disable ep */
+            AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SNAK;
+            AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_EPDIS;
+
+            for (i = 0; i < DIS_EP_TIMOUT; i++) {
+                if (AIC_UDC_REG->outepint[ep_idx] & EPDISBLD)
+                    break;
+                aic_udelay(1);
+            }
+
+            if (i == DIS_EP_TIMOUT)
+                USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__);
+
+            /* Clear EPDISBLD interrupt */
+            AIC_UDC_REG->outepint[ep_idx] |= EPDISBLD;
+
+            /* (3) Remove global NAKs */
+            AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGOUTNAK;
+        }
+
+        AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx)));
+        AIC_UDC_REG->outepcfg[ep_idx] = 0;
+    } else {
+        tx_fifo_num = (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_TXFIFONUM_MASK) >> DEPCTL_TXFIFONUM_SHIFT;
+
+        if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) {
+            if (tx_fifo_num) {
+                /* (1) Wait for Nak effect */
+                AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK;
+
+                for (i = 0; i < DIS_EP_TIMOUT; i++) {
+                    if (AIC_UDC_REG->inepint[ep_idx] & INEP_NAKEFF)
+                        break;
+                    aic_udelay(1);
+                }
+
+                if (i == DIS_EP_TIMOUT)
+                    USB_LOG_ERR("%s: timeout INEPINT.NAKEFF\n", __func__);
+            } else {
+                /* (1) Wait for Nak effect */
+                AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGNPINNAK;
+
+                for (i = 0; i < DIS_EP_TIMOUT; i++) {
+                    if (AIC_UDC_REG->usbintsts & INT_GINNAKEFF)
+                        break;
+                    aic_udelay(1);
+                }
+
+                if (i == DIS_EP_TIMOUT)
+                    USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__);
+            }
+
+            /* (2) Disable ep */
+            AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK;
+            AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_EPDIS;
+
+            for (i = 0; i < DIS_EP_TIMOUT; i++) {
+                if (AIC_UDC_REG->inepint[ep_idx] & EPDISBLD)
+                    break;
+                aic_udelay(1);
+            }
+
+            if (i == DIS_EP_TIMOUT)
+                USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__);
+
+            /* Clear EPDISBLD interrupt */
+            AIC_UDC_REG->inepint[ep_idx] |= EPDISBLD;
+
+            /* (3) Clear Global In NP NAK in Shared FIFO for non periodic ep */
+            if (!tx_fifo_num)
+                AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK;
+        }
+
+        AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << ep_idx));
+        AIC_UDC_REG->inepcfg[ep_idx] = 0;
+
+        /* Flush TX FIFO */
+        aic_flush_txfifo(tx_fifo_num);
+
+        /* Period IN EP free fifo num */
+        if (tx_fifo_num > 0)
+            g_aic_udc.tx_fifo_map &= ~(1<<tx_fifo_num);
+    }
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        aic_udc_obuf_free(&g_aic_udc.out_ep[ep_idx]);
+    } else {
+        aic_udc_ibuf_free(&g_aic_udc.in_ep[ep_idx]);
+    }
+#endif
+
+    return 0;
+}
+
+int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (((AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) {
+            AIC_UDC_REG->outepcfg[ep_idx] &= ~(DEPCTL_EPDIS);
+        }
+        AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_STALL;
+    } else {
+        if (((AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) {
+            AIC_UDC_REG->inepcfg[ep_idx] &= ~(DEPCTL_EPDIS);
+        }
+        AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_STALL;
+    }
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    if (ep_idx == 0) {
+        aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup);
+    }
+#endif
+    return 0;
+}
+
+int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_STALL;
+        if ((g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
+            (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
+            AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */
+        }
+    } else {
+        AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_STALL;
+        if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
+            (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
+            AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */
+        }
+    }
+
+    return 0;
+}
+
+int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
+{
+    if (USB_EP_DIR_IS_OUT(ep)) {
+    } else {
+    }
+    return 0;
+}
+
+int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    uint32_t pktcnt = 0;
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) {
+        return -2;
+    }
+    if (ep_idx && !(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_MPS_MASK)) {
+        return -3;
+    }
+    if ((uint32_t)(uintptr_t)data & 0x03) {
+        return -4;
+    }
+
+    g_aic_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_aic_udc.in_ep[ep_idx].xfer_len = data_len;
+    g_aic_udc.in_ep[ep_idx].actual_xfer_len = 0;
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    if ((ep_idx != 0) && (data_len > 0) &&
+        ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) ||
+         (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) {
+
+        if (g_aic_udc.in_ep[ep_idx].xfer_align_len != data_len) {
+            int ret = 0;
+
+            aic_udc_ibuf_free(&g_aic_udc.in_ep[ep_idx]);
+            ret = aic_udc_ibuf_alloc(&g_aic_udc.in_ep[ep_idx], data_len);
+            if (ret)
+                return ret;
+        }
+        memcpy(g_aic_udc.in_ep[ep_idx].xfer_align_buf, data, data_len);
+        data = g_aic_udc.in_ep[ep_idx].xfer_align_buf;
+    } else {
+        aic_udc_ibuf_free(&g_aic_udc.in_ep[ep_idx]);
+    }
+
+    if (data_len>0)
+        aic_udc_dcache_clean((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE));
+#endif
+
+    AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK);
+    AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK);
+    AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK);
+
+    if (data_len == 0) {
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19));
+        AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA);
+        return 0;
+    }
+
+    if (ep_idx == 0) {
+        if (data_len > g_aic_udc.in_ep[ep_idx].ep_mps) {
+            data_len = g_aic_udc.in_ep[ep_idx].ep_mps;
+        }
+        g_aic_udc.in_ep[ep_idx].xfer_len = data_len;
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19));
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len);
+    } else {
+        pktcnt = (uint16_t)((data_len + g_aic_udc.in_ep[ep_idx].ep_mps - 1U) / g_aic_udc.in_ep[ep_idx].ep_mps);
+
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19));
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len);
+    }
+
+    if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) ||
+        (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT)) {
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1<<DXEPTSIZ_MULCNT_SHIFT);
+    }
+
+    if (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+        if ((AIC_UDC_REG->usblinests & (1U << 8)) == 0U) {
+            AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID;
+            AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID;
+        } else {
+            AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID;
+            AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID;
+        }
+        AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK);
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT);
+    } else if (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
+        AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK);
+        AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT);
+    }
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    AIC_UDC_REG->inepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data;
+#endif
+
+    AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA);
+
+    return 0;
+}
+
+int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    uint32_t pktcnt = 0;
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) {
+        return -2;
+    }
+    if (ep_idx && !(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_MPS_MASK)) {
+        return -3;
+    }
+    if (((uint32_t)(uintptr_t)data) & 0x03) {
+        return -4;
+    }
+
+    g_aic_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_aic_udc.out_ep[ep_idx].xfer_len = data_len;
+    g_aic_udc.out_ep[ep_idx].actual_xfer_len = 0;
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    if ((ep_idx != 0) && (data_len > 0) &&
+        ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) ||
+         (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) {
+
+        if (g_aic_udc.out_ep[ep_idx].xfer_align_len != data_len) {
+            int ret = 0;
+
+            aic_udc_obuf_free(&g_aic_udc.out_ep[ep_idx]);
+            ret = aic_udc_obuf_alloc(&g_aic_udc.out_ep[ep_idx], data_len);
+            if (ret)
+                return ret;
+        }
+        data = g_aic_udc.out_ep[ep_idx].xfer_align_buf;
+    } else {
+        aic_udc_obuf_free(&g_aic_udc.out_ep[ep_idx]);
+    }
+
+    if (data_len > 0)
+        aic_udc_dcache_invalidate((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE));
+#endif
+
+    AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK);
+    AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK);
+    if (data_len == 0) {
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1 << 19));
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & g_aic_udc.out_ep[ep_idx].ep_mps);
+        AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA);
+        return 0;
+    }
+
+    if (ep_idx == 0) {
+        if (data_len > g_aic_udc.out_ep[ep_idx].ep_mps) {
+            data_len = g_aic_udc.out_ep[ep_idx].ep_mps;
+        }
+        g_aic_udc.out_ep[ep_idx].xfer_len = data_len;
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19));
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len);
+    } else {
+        pktcnt = (uint16_t)((data_len + g_aic_udc.out_ep[ep_idx].ep_mps - 1U) / g_aic_udc.out_ep[ep_idx].ep_mps);
+
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19));
+        AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len);
+    }
+
+#ifdef CONFIG_USB_AIC_DMA_ENABLE
+    AIC_UDC_REG->outepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data;
+#endif
+    if (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+        if ((AIC_UDC_REG->usblinests & (1U << 8)) == 0U) {
+            AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID;
+            AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID;
+        } else {
+            AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID;
+            AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID;
+        }
+    }
+    AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA);
+    return 0;
+}
+
+void USBD_IRQHandler(void)
+{
+    uint32_t gint_status, ep_idx, ep_intr, epint, daintmask;
+    gint_status = aic_get_glb_intstatus();
+
+    /* Avoid spurious interrupt */
+    if (gint_status == 0) {
+        return;
+    }
+
+#ifndef CONFIG_USB_AIC_DMA_ENABLE
+    uint32_t temp;
+    uint32_t read_count;
+
+    /* Handle RxQLevel Interrupt */
+    if (gint_status & INT_RX_FIFO_NOT_EMPTY) {
+        AIC_UDC_REG->usbintmsk &= ~(INT_RX_FIFO_NOT_EMPTY);
+
+        temp = AIC_UDC_REG->rxfifosts_pop;
+        ep_idx = temp & RXFIFOSTS_EPNUM_MASK;
+
+        if ((temp & RXFIFOSTS_PKTSTS_MASK)  == PKTSTS_OUT_DATA_PKT_REC) {
+            read_count = (temp & RXFIFOSTS_BCNT_MASK) >> 4;
+            if (read_count != 0) {
+                aic_ep_read(g_aic_udc.out_ep[ep_idx].xfer_buf, read_count);
+                g_aic_udc.out_ep[ep_idx].xfer_buf += read_count;
+            }
+        } else if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_SETUP_DATA_PKT_REC) {
+            read_count = (temp & RXFIFOSTS_BCNT_MASK) >> 4;
+            aic_ep_read((uint8_t *)&g_aic_udc.setup, read_count);
+        } else {
+            /* ... */
+        }
+        AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY;
+    }
+#endif
+    if (gint_status & INT_OUT_EP) {
+        ep_idx = 0;
+        ep_intr = aic_get_outeps_intstatus();
+        while (ep_intr != 0U) {
+            if ((ep_intr & 0x1U) != 0U) {
+                epint = aic_get_outep_intstatus(ep_idx);
+                uint32_t DoepintReg = AIC_UDC_REG->outepint[ep_idx];
+                AIC_UDC_REG->outepint[ep_idx] = DoepintReg;
+
+                struct aic_ep_state *ep = &g_aic_udc.out_ep[ep_idx];
+                if ((epint & TRANSFER_DONE) == TRANSFER_DONE) {
+                    #ifdef CONFIG_USB_AIC_DMA_ENABLE
+                    if (ep->xfer_align_buf)
+                        memcpy(ep->xfer_buf, ep->xfer_align_buf, ep->xfer_len);
+                    #endif
+                    if ((ep_idx == 0)) {
+                        if (ep0_ctrl_stage == 1) {
+                            ep0_ctrl_stage = 2;
+                            usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup);
+                        } else {
+                            if (ep->xfer_len == 0) {
+                                /* Out status, start reading setup */
+                                aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup);
+                            } else {
+                                ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK);
+                                ep->xfer_len = 0;
+                                usbd_event_ep_out_complete_handler(0, 0x00, ep->actual_xfer_len);
+                            }
+                        }
+                    } else {
+                        ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK);
+                        ep->xfer_len = 0;
+                        usbd_event_ep_out_complete_handler(0, ep_idx, ep->actual_xfer_len);
+                    }
+                }
+
+                if ((epint & CTRL_OUT_EP_SETUP_PHASE_DONE) == CTRL_OUT_EP_SETUP_PHASE_DONE) {
+                    if (ep0_ctrl_stage == 1) {
+                        ep0_ctrl_stage = 2;
+                        usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup);
+                    }
+                }
+            }
+            ep_intr >>= 1U;
+            ep_idx++;
+        }
+    }
+
+#ifndef CONFIG_USB_AIC_DMA_ENABLE
+    if (gint_status & INT_NP_TX_FIFO_EMPTY) {
+        AIC_UDC_REG->usbintmsk &= ~(INT_NP_TX_FIFO_EMPTY);
+        aic_tx_fifo_empty_procecss(0);
+    }
+#endif
+
+    if (gint_status & INT_IN_EP) {
+        ep_idx = 0U;
+        ep_intr = aic_get_ineps_intstatus();
+        while (ep_intr != 0U) {
+            if ((ep_intr & 0x1U) != 0U) {
+                epint = aic_get_inep_intstatus(ep_idx);
+                uint32_t DiepintReg = AIC_UDC_REG->inepint[ep_idx];
+                AIC_UDC_REG->inepint[ep_idx] = DiepintReg;
+
+                if ((epint & TRANSFER_DONE) == TRANSFER_DONE) {
+                    if (ep_idx == 0) {
+                        g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK);
+                        g_aic_udc.in_ep[ep_idx].xfer_len = 0;
+                        usbd_event_ep_in_complete_handler(0, 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len);
+
+                        if (g_aic_udc.setup.wLength && ((g_aic_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
+                            /* In status, start reading setup */
+                            aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup);
+                        } else if (g_aic_udc.setup.wLength == 0) {
+                            /* In status, start reading setup */
+                            aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup);
+                        }
+                    } else {
+                        g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK);
+                        g_aic_udc.in_ep[ep_idx].xfer_len = 0;
+                        usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len);
+                    }
+                }
+
+                #ifndef CONFIG_USB_AIC_DMA_ENABLE
+                if ((epint & INTKN_TXFEMP) == INTKN_TXFEMP) {
+                    aic_tx_fifo_empty_procecss(ep_idx);
+                }
+                #endif
+            }
+            ep_intr >>= 1U;
+            ep_idx++;
+        }
+    }
+    if (gint_status & INT_RESET) {
+        AIC_UDC_REG->usbintsts |= INT_RESET;
+        AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_RMTWKUPSIG;
+
+        usb_dc_rst();
+    }
+
+    if (gint_status & INT_ENUMDONE) {
+        AIC_UDC_REG->usbintsts |= INT_ENUMDONE;
+        aic_set_turnaroundtime(usbd_clk, aic_get_devspeed());
+
+        AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK;
+    }
+    if (gint_status & INT_INCOMP_ISO_OUT_INT) {
+        daintmask = AIC_UDC_REG->usbepintmsk;
+        daintmask >>= 16;
+
+        for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
+            if ((BIT(ep_idx) & ~daintmask) || (g_aic_udc.out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
+                continue;
+            if (!(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_USBACTEP))
+                continue;
+
+            if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) {
+                AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID;
+                AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID;
+            } else {
+                AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID;
+                AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID;
+            }
+        }
+
+        AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_OUT_INT;
+    }
+
+    if (gint_status & INT_INCOMP_ISO_IN_INT) {
+        daintmask = AIC_UDC_REG->usbepintmsk;
+        daintmask >>= 16;
+
+        for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
+            if (((BIT(ep_idx) & ~daintmask)) || (g_aic_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
+                continue;
+
+            if (!(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_USBACTEP))
+                continue;
+
+            if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) {
+                AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID;
+                AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID;
+            } else {
+                AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID;
+                AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID;
+            }
+        }
+        AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_IN_INT;
+    }
+
+    if (gint_status & INT_SOF) {
+        AIC_UDC_REG->usbintsts |= INT_SOF;
+    }
+    if (gint_status & INT_SUSPEND) {
+        AIC_UDC_REG->usbintsts |= INT_SUSPEND;
+    }
+    if (gint_status & INT_RESUME) {
+        AIC_UDC_REG->usbintsts |= INT_RESUME;
+    }
+}

+ 43 - 0
components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c

@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Artinchip Technology Co., Ltd
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <aic_core.h>
+#include <aic_hal.h>
+#include <hal_syscfg.h>
+#include "usbd_core.h"
+#include "usb_dc_aic_reg.h"
+
+extern irqreturn_t USBD_IRQHandler(int irq, void * data);
+
+uint32_t usbd_clk;
+
+void usb_dc_low_level_init(void)
+{
+    /* set usb0 phy switch: Host/Device */
+#ifdef AIC_USING_USB0_DEVICE
+    syscfg_usb_phy0_sw_host(0);
+#endif
+    /* set pin-mux */
+
+    /* enable clock */
+    hal_clk_enable(CONFIG_USB_AIC_DC_PHY_CLK);
+    hal_clk_enable(CONFIG_USB_AIC_DC_CLK);
+    aicos_udelay(300);
+    hal_reset_assert(CONFIG_USB_AIC_DC_PHY_RESET);
+    hal_reset_assert(CONFIG_USB_AIC_DC_RESET);
+    aicos_udelay(300);
+    hal_reset_deassert(CONFIG_USB_AIC_DC_PHY_RESET);
+    hal_reset_deassert(CONFIG_USB_AIC_DC_RESET);
+    aicos_udelay(300);
+
+    usbd_clk = hal_clk_get_freq(CONFIG_USB_AIC_DC_CLK);
+
+    /* register interrupt callback */
+    aicos_request_irq(CONFIG_USB_AIC_DC_IRQ_NUM, USBD_IRQHandler,
+                      0, "usb_device", NULL);
+    aicos_irq_enable(CONFIG_USB_AIC_DC_IRQ_NUM);
+}
+

+ 301 - 0
components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h

@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2022, Artinchip Technology Co., Ltd
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __USB_DC_AIC_REG_H__
+#define __USB_DC_AIC_REG_H__
+
+#define __IO volatile               /*!< Defines 'read / write' permissions */
+
+typedef struct {
+    __IO uint32_t ahbbasic;         /* 0x0000: AHBBASIC */
+    __IO uint32_t usbdevinit;       /* 0x0004: USBDEVINIT */
+    __IO uint32_t usbphyif;         /* 0x0008: USBPHYIF */
+    __IO uint32_t usbulpiphy;       /* 0x000C: USBULPIPHY */
+    __IO uint32_t usbintsts;        /* 0x0010: USBINTSTS */
+    __IO uint32_t usbintmsk;        /* 0x0014: USBINTMSK */
+    __IO uint32_t rxfifosiz;        /* 0x0018: RXFIFOSIZ */
+    __IO uint32_t rxfifosts_pop;    /* 0x001C: RXFIFOSTS pop */
+    __IO uint32_t nptxfifosiz;      /* 0x0020: NPTXFIFOSIZ */
+    __IO uint32_t nptxfifosts;      /* 0x0024: NPTXFIFOSTS */
+    __IO uint32_t txfifosiz[2];     /* 0x0028 - 0x002C: TXFIFOSIZ() */
+    __IO uint32_t rxfifosts_dbg;    /* 0x0030: RXFIFOSTS_DBG */
+    uint8_t  res0[0x1cc];
+    __IO uint32_t usbdevconf;       /* 0x0200: USBDEVCONF */
+    __IO uint32_t usbdevfunc;       /* 0x0204: USBDEVFUNC */
+    __IO uint32_t usblinests;       /* 0x0208: USBLINESTS */
+    __IO uint32_t inepintmsk;       /* 0x020C: INEPINTMSK */
+    __IO uint32_t outepintmsk;      /* 0x0210: OUTEPINTMSK */
+    __IO uint32_t usbepint;         /* 0x0214: USBEPINT */
+    __IO uint32_t usbepintmsk;      /* 0x0218: USBEPINTMSK */
+    uint8_t  res1[4];
+    __IO uint32_t inepcfg[5];       /* 0x0220 - 0x0230: INEPCFG() */
+    uint8_t  res2[0xc];
+    __IO uint32_t outepcfg[5];      /* 0x0240 - 0x0250: OUTEPCFG() */
+    uint8_t  res3[0xc];
+    __IO uint32_t inepint[5];       /* 0x0260 - 0x0270: INEPINT() */
+    uint8_t  res4[0xc];
+    __IO uint32_t outepint[5];      /* 0x0280 - 0x0290: OUTEPINT() */
+    uint8_t  res5[0xc];
+    __IO uint32_t ineptsfsiz[5];    /* 0x02A0 - 0x02B0: INEPTSFSIZ() */
+    uint8_t  res6[0xc];
+    __IO uint32_t outeptsfsiz[5];   /* 0x02C0 - 0x02D0: OUTEPTSFSIZ() */
+    uint8_t  res7[0x2c];
+    __IO uint32_t inepdmaaddr[5];   /* 0x0300 - 0x0310: INEPDMAADDR() */
+    uint8_t  res8[0xc];
+    __IO uint32_t outepdmaaddr[5];  /* 0x0320 - 0x0330: OUTEPDMAADDR() */
+    uint8_t  res9[0xc];
+    __IO uint32_t ineptxsts[5];     /* 0x0340 - 0x0350: INEPTXSTS() */
+    uint8_t  res10[0xc];
+    __IO uint32_t dtknqr1;          /* 0x0360: DTKNQR1 */
+    __IO uint32_t dtknqr2;          /* 0x0364: DTKNQR2 */
+    __IO uint32_t dtknqr3;          /* 0x0368: DTKNQR3 */
+    __IO uint32_t dtknqr4;          /* 0x036C: DTKNQR4 */
+}AIC_UDC_RegDef;
+
+/*===================================================================== */
+/*definitions related to CSR setting */
+
+/* AHBBASIC */
+#define AHBBASIC_NOTI_ALL_DMA_WRIT      (1 << 8)
+#define AHBBASIC_REM_MEM_SUPP           (1 << 7)
+#define AHBBASIC_INV_DESC_ENDIANNESS    (1 << 6)
+#define AHBBASIC_AHB_SINGLE             (1 << 5)
+#define AHBBASIC_TXENDDELAY             (1 << 3)
+#define AHBBASIC_AHBIDLE                (1 << 2)
+#define AHBBASIC_DMAREQ                 (1 << 1)
+
+/* USBDEVINIT */
+#define USBDEVINIT_HBSTLEN_MASK         (0xf << 12)
+#define USBDEVINIT_HBSTLEN_SHIFT        12
+#define USBDEVINIT_HBSTLEN_SINGLE       0
+#define USBDEVINIT_HBSTLEN_INCR         1
+#define USBDEVINIT_HBSTLEN_INCR4        3
+#define USBDEVINIT_HBSTLEN_INCR8        5
+#define USBDEVINIT_HBSTLEN_INCR16       7
+#define USBDEVINIT_DMA_EN               (1 << 11)
+#define USBDEVINIT_NP_TXF_EMP_LVL       (1 << 10)
+#define USBDEVINIT_GLBL_INTR_EN         (1 << 9)
+#define USBDEVINIT_CTRL_MASK            (USBDEVINIT_NP_TXF_EMP_LVL | \
+                                         USBDEVINIT_DMA_EN | \
+                                         USBDEVINIT_GLBL_INTR_EN)
+#define USBDEVINIT_IN_TKNQ_FLSH         (1 << 8)
+#define USBDEVINIT_TXFNUM_MASK          (0x1f << 3)
+#define USBDEVINIT_TXFNUM_SHIFT         3
+#define USBDEVINIT_TXFNUM_LIMIT         0x1f
+#define USBDEVINIT_TXFNUM(_x)           ((_x) << 3)
+#define USBDEVINIT_TXFFLSH              (1 << 2)
+#define USBDEVINIT_RXFFLSH              (1 << 1)
+#define USBDEVINIT_CSFTRST              (1 << 0)
+
+/* USBPHYIF */
+#define USBPHYIF_ULPI_CLK_SUSP_M        (1 << 19)
+#define USBPHYIF_ULPI_AUTO_RES          (1 << 18)
+#define USBPHYIF_PHY_LP_CLK_SEL         (1 << 15)
+#define USBPHYIF_USBTRDTIM_MASK         (0xf << 10)
+#define USBPHYIF_USBTRDTIM_SHIFT        10
+#ifndef USBPHYIF_HS_TRDT_VALUE
+#define USBPHYIF_HS_TRDT_VALUE          9U
+#endif /* USBD_HS_TRDT_VALUE */
+#ifndef USBPHYIF_FS_TRDT_VALUE
+#define USBPHYIF_FS_TRDT_VALUE          5U
+#define USBPHYIF_DEFAULT_TRDT_VALUE     9U
+#endif /* USBD_HS_TRDT_VALUE */
+#define USBPHYIF_DDRSEL                 (1 << 7)
+#define USBPHYIF_ULPI_UTMI_SEL          (1 << 4)
+#define USBPHYIF_PHYIF16                (1 << 3)
+#define USBPHYIF_PHYIF8                 (0 << 3)
+#define USBPHYIF_TOUTCAL_MASK           (0x7 << 0)
+#define USBPHYIF_TOUTCAL_SHIFT          0
+#define USBPHYIF_TOUTCAL_LIMIT          0x7
+#define USBPHYIF_TOUTCAL(_x)            ((_x) << 0)
+
+/* USBINTSTS/USBINTMSK interrupt register */
+#define INT_RESUME                      (1u << 31)
+#define INT_INCOMP_ISO_OUT_INT          (0x1 << 21)
+#define INT_INCOMP_ISO_IN_INT           (0x1 << 20)
+#define INT_OUT_EP                      (0x1 << 19)
+#define INT_IN_EP                       (0x1 << 18)
+#define INT_ENUMDONE                    (0x1 << 13)
+#define INT_RESET                       (0x1 << 12)
+#define INT_SUSPEND                     (0x1 << 11)
+#define INT_EARLY_SUSPEND               (0x1 << 10)
+#define INT_GOUTNAKEFF                  (0x1 << 7)
+#define INT_GINNAKEFF                   (0x1 << 6)
+#define INT_NP_TX_FIFO_EMPTY            (0x1 << 5)
+#define INT_RX_FIFO_NOT_EMPTY           (0x1 << 4)
+#define INT_SOF                         (0x1 << 3)
+
+#define FULL_SPEED_CONTROL_PKT_SIZE     8
+#define FULL_SPEED_BULK_PKT_SIZE        64
+
+#define HIGH_SPEED_CONTROL_PKT_SIZE     64
+#define HIGH_SPEED_BULK_PKT_SIZE        512
+
+#define RX_FIFO_SIZE                    (1024)
+#define NPTX_FIFO_SIZE                  (1024)
+#define PTX_FIFO_SIZE                   (384)
+
+/* fifo size configure */
+#define EPS_NUM                         5
+#define PERIOD_IN_EP_NUM                2
+#define TOTAL_FIFO_SIZE                 0x3f6
+#define AIC_RX_FIFO_SIZE                0x119
+#define AIC_NP_TX_FIFO_SIZE             0x100
+#define AIC_PERIOD_TX_FIFO1_SIZE        0x100
+#define AIC_PERIOD_TX_FIFO2_SIZE        0xDD
+
+#define DEPCTL_TXFNUM_0                 (0x0 << 22)
+#define DEPCTL_TXFNUM_1                 (0x1 << 22)
+#define DEPCTL_TXFNUM_2                 (0x2 << 22)
+#define DEPCTL_TXFNUM_3                 (0x3 << 22)
+#define DEPCTL_TXFNUM_4                 (0x4 << 22)
+
+/* RXFIFOSTS */
+#define RXFIFOSTS_EPNUM_MASK            (0xFU << 0)
+#define RXFIFOSTS_BCNT_MASK             (0x7FFU << 4)
+#define RXFIFOSTS_DPID_MASK             (0x3U << 15)
+#define RXFIFOSTS_PKTSTS_SHIFT          (17)
+#define RXFIFOSTS_PKTSTS_MASK           (0xFU << RXFIFOSTS_PKTSTS_SHIFT)
+#define PKTSTS_GLOBAL_OUT_NAK           (0x1 << RXFIFOSTS_PKTSTS_SHIFT)
+#define PKTSTS_OUT_DATA_PKT_REC         (0x2 << RXFIFOSTS_PKTSTS_SHIFT)
+#define PKTSTS_OUT_TRANSFER_COMP        (0x3 << RXFIFOSTS_PKTSTS_SHIFT)
+#define PKTSTS_SETUP_TRANSACTION_COMP   (0x4 << RXFIFOSTS_PKTSTS_SHIFT)
+#define PKTSTS_SETUP_DATA_PKT_REC       (0x6 << RXFIFOSTS_PKTSTS_SHIFT)
+#define RXFIFOSTS_FN_MASK               (0xFU << 21)
+
+/* USBDEVCONF */
+#define DEV_SPEED_HIGH_SPEED_20         (0x0 << 0)
+#define DEV_SPEED_FULL_SPEED_20         (0x1 << 0)
+#define DEV_SPEED_LOW_SPEED_11          (0x2 << 0)
+#define DEV_SPEED_FULL_SPEED_11         (0x3 << 0)
+#define EP_MISS_CNT(x)                  (x << 18)
+#define DEVICE_ADDRESS_MASK             (0x7F << 4)
+#define DEVICE_ADDRESS(x)               (x << 4)
+#define PERIOD_FRAME_INTERVAL_80        (0 << 11)
+#define PERIOD_FRAME_INTERVAL_85        (1 << 11)
+#define PERIOD_FRAME_INTERVAL_90        (2 << 11)
+#define PERIOD_FRAME_INTERVAL_95        (3 << 11)
+
+/* USBDEVFUNC */
+#define NORMAL_OPERATION                (0x1 << 0)
+#define SOFT_DISCONNECT                 (0x1 << 1)
+#define USBDEVFUNC_SERVICE_INTERVAL_SUPPORTED (1 << 19)
+#define USBDEVFUNC_PWRONPRGDONE         (1 << 11)
+#define USBDEVFUNC_CGOUTNAK             (1 << 10)
+#define USBDEVFUNC_SGOUTNAK             (1 << 9)
+#define USBDEVFUNC_CGNPINNAK            (1 << 8)
+#define USBDEVFUNC_SGNPINNAK            (1 << 7)
+#define USBDEVFUNC_TSTCTL_MASK          (0x7 << 4)
+#define USBDEVFUNC_TSTCTL_SHIFT         (4)
+#define USBDEVFUNC_GOUTNAKSTS           (1 << 3)
+#define USBDEVFUNC_GNPINNAKSTS          (1 << 2)
+#define USBDEVFUNC_SFTDISCON            (1 << 1)
+#define USBDEVFUNC_RMTWKUPSIG           (1 << 0)
+
+/* USBLINESTS: Enumeration speed */
+#define USB_ENUM_SPEED_SHIFT            1
+#define USB_ENUM_SPEED_MASK             (0x3 << USB_ENUM_SPEED_SHIFT)
+#define USB_ENUM_SPEED_HIGH             0
+#define USB_ENUM_SPEED_FULL             1
+#define USB_HIGH_30_60MHZ               (0x0 << USB_ENUM_SPEED_SHIFT)
+#define USB_FULL_30_60MHZ               (0x1 << USB_ENUM_SPEED_SHIFT)
+#define USB_LOW_6MHZ                    (0x2 << USB_ENUM_SPEED_SHIFT)
+#define USB_FULL_48MHZ                  (0x3 << USB_ENUM_SPEED_SHIFT)
+
+/* USBEPINT endpoint interrupt register */
+#define DAINT_OUT_BIT                   (16)
+#define DAINT_IN_MASK                   (0xFFFF)
+#define DAINT_OUT_MASK                  (0xFFFFU << DAINT_OUT_BIT)
+
+/* INEPCFG()/OUTEPCFG()
+ * devicecontrol IN/OUT endpoint 0 control register
+ */
+#define DEPCTL_EPENA                    (1u << 31)
+#define DEPCTL_EPDIS                    (0x1 << 30)
+#define DEPCTL_SETD1PID                 (0x1 << 29)
+#define DEPCTL_SETD0PID                 (0x1 << 28)
+#define DEPCTL_SNAK                     (0x1 << 27)
+#define DEPCTL_CNAK                     (0x1 << 26)
+#define DEPCTL_TXFIFONUM_SHIFT          22
+#define DEPCTL_TXFIFONUM_MASK           (0xF << 22)
+#define DEPCTL_STALL                    (0x1 << 21)
+#define DEPCTL_TYPE_BIT                 (18)
+#define DEPCTL_TYPE_MASK                (0x3 << 18)
+#define DEPCTL_CTRL_TYPE                (0x0 << 18)
+#define DEPCTL_ISO_TYPE                 (0x1 << 18)
+#define DEPCTL_BULK_TYPE                (0x2 << 18)
+#define DEPCTL_INTR_TYPE                (0x3 << 18)
+#define DEPCTL_USBACTEP                 (0x1 << 15)
+#define DEPCTL_NEXT_EP_BIT              (11)
+#define DEPCTL_NEXT_EP_MASK             (0xFU << DEPCTL_NEXT_EP_BIT)
+#define DEPCTL_MPS_BIT                  (0)
+#define DEPCTL_MPS_MASK                 (0x7FF)
+
+#define DEPCTL0_MPS_64                  (0x0 << 0)
+#define DEPCTL0_MPS_32                  (0x1 << 0)
+#define DEPCTL0_MPS_16                  (0x2 << 0)
+#define DEPCTL0_MPS_8                   (0x3 << 0)
+#define DEPCTL_MPS_BULK_512             (512 << 0)
+#define DEPCTL_MPS_INT_MPS_16           (16 << 0)
+
+#define DIEPCTL0_NEXT_EP_BIT            (11)
+
+/* INEPINT/OUTEPINT device IN/OUT endpoint interrupt register */
+#define TXFIFO_EMP_INT                  (0x1 << 7)
+#define INEP_NAKEFF                     (0x1 << 6)
+#define BACK2BACK_SETUP_RECEIVED        (0x1 << 6)
+#define INTKNEPMIS                      (0x1 << 5)
+#define INTKN_TXFEMP                    (0x1 << 4)
+#define NON_ISO_IN_EP_TIMEOUT           (0x1 << 3)
+#define CTRL_OUT_EP_SETUP_PHASE_DONE    (0x1 << 3)
+#define AHB_ERROR                       (0x1 << 2)
+#define EPDISBLD                        (0x1 << 1)
+#define TRANSFER_DONE                   (0x1 << 0)
+
+/* Masks definitions */
+#define GINTMSK_INIT                    (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\
+                                        | INT_RESET | INT_SUSPEND)
+#define DOEPMSK_INIT                    (CTRL_OUT_EP_SETUP_PHASE_DONE |\
+                                        AHB_ERROR | TRANSFER_DONE)
+#define DIEPMSK_INIT                    (NON_ISO_IN_EP_TIMEOUT | AHB_ERROR | TRANSFER_DONE)
+#define GAHBCFG_INIT                    (USBDEVINIT_DMA_EN | USBDEVINIT_GLBL_INTR_EN\
+                                        | (USBDEVINIT_HBSTLEN_INCR4 <<\
+                                        USBDEVINIT_HBSTLEN_SHIFT))
+
+/* INEPTSFSIZ/OUTEPTSFSIZ */
+#define DXEPTSIZ_MULCNT_SHIFT           29
+#define DXEPTSIZ_MULCNT_MASK            (0x3U << DXEPTSIZ_MULCNT_SHIFT)
+#define DXEPTSIZ_PKT_CNT_SHIFT          19
+#define DXEPTSIZ_PKT_CNT_MASK           (0x3FFU << DXEPTSIZ_PKT_CNT_SHIFT)
+#define DXEPTSIZ_XFER_SIZE_SHIFT        0
+#define DXEPTSIZ_XFER_SIZE_MASK         (0x7FFFFU << DXEPTSIZ_XFER_SIZE_SHIFT)
+
+/* Device Endpoint X Transfer Size Register INEPTSFSIZ() */
+#define DIEPT_SIZ_PKT_CNT(x)            (x << 19)
+#define DIEPT_SIZ_XFER_SIZE(x)          (x << 0)
+
+/* Device OUT Endpoint X Transfer Size Register OUTEPTSFSIZ() */
+#define DOEPT_SIZ_PKT_CNT(x)            (x << 19)
+#define DOEPT_SIZ_XFER_SIZE(x)          (x << 0)
+#define DOEPT_SIZ_XFER_SIZE_MAX_EP0     (0x7F << 0)
+#define DOEPT_SIZ_XFER_SIZE_MAX_EP      (0x7FFF << 0)
+
+/* Device Endpoint-N Control Register INEPCFG()/OUTEPCFG() */
+#define DIEPCTL_TX_FIFO_NUM(x)          (x << 22)
+#define DIEPCTL_TX_FIFO_NUM_MASK        (~DIEPCTL_TX_FIFO_NUM(0xF))
+
+/* Device ALL Endpoints Interrupt Register (USBEPINT) */
+#define DAINT_IN_EP_INT(x)              (x << 0)
+#define DAINT_OUT_EP_INT(x)             (x << 16)
+
+#define AIC_EP_FIFO_BASE                0x1000UL
+#define AIC_EP_FIFO_SIZE                0x1000UL
+
+/* In EPn Txfifo Status (INEPTXSTS) */
+#define INEPTXSTS_IN_EP_TXFIFO_STS      (0xFFFFU << 0)
+
+
+#endif

+ 525 - 0
components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c

@@ -0,0 +1,525 @@
+#include "usbd_core.h"
+#include "ch585_usbhs_reg.h"
+
+/**
+ * @brief   Related register macro
+ */
+#define USB_BASE        0x40009000u
+#define CH585_USBHS_DEV ((USBHSD_TypeDef *)USB_BASE)
+
+#ifndef USBD_IRQHandler
+#define USBD_IRQHandler USB2_DEVICE_IRQHandler //use actual usb irq name instead
+#endif
+
+#define R16_PIN_CONFIG (*((PUINT16V)0x4000101A))
+#define R32_PIN_CONFIG (*((PUINT32V)0x40001018)) // RW, I/O pin configuration
+#define RB_PIN_USB2_EN 0x20
+
+#define USB_SET_RX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&CH585_USBHS_DEV->UEP1_RX_DMA) + 4 * (ep_idx - 1)) = addr)
+#define USB_SET_TX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&CH585_USBHS_DEV->UEP1_TX_DMA) + 4 * (ep_idx - 1)) = addr)
+
+#define USB_SET_MAX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_MAX_LEN) + 4 * ep_idx) = len)
+#define USB_SET_TX_LEN(ep_idx, len)  (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx) = len)
+#define USB_GET_TX_LEN(ep_idx)       (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx))
+#define USB_SET_TX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_CTRL) + 4 * ep_idx) = val)
+#define USB_GET_TX_CTRL(ep_idx)      (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_CTRL) + 4 * ep_idx))
+#define USB_SET_RX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_RX_CTRL) + 4 * ep_idx) = val)
+#define USB_GET_RX_CTRL(ep_idx)      (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_RX_CTRL) + 4 * ep_idx))
+#define EPn_SET_TX_NAK(ep_idx)       USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_NAK)
+#define EPn_SET_TX_VALID(ep_idx)     USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK)
+#define EPn_SET_RX_NAK(ep_idx)       USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK)
+#define EPn_SET_RX_VALID(ep_idx)     USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK)
+#define EPn_GET_RX_LEN(ep_idx)       (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->USB_EP0_RX_LEN) + 4 * ep_idx))
+#define EPn_SET_TX_LEN(ep_idx, len)  (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx) = len)
+#define EPn_CLEAR_TX_DONE(ep_idx)    USB_SET_TX_CTRL(ep_idx, USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_DONE)
+#define EPn_CLEAR_RX_DONE(ep_idx)    USB_SET_RX_CTRL(ep_idx, USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_DONE)
+#define EPn_SET_TX_ISO_VALID(ep_idx)
+#define EPn_SET_RX_ISO_VALID(ep_idx)
+
+/* ep nums */
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 8
+#endif
+
+/**
+ * @brief   Endpoint information structure
+ */
+typedef struct _usbd_ep_info {
+    uint8_t mps;       /* Maximum packet length of endpoint */
+    uint8_t eptype;    /* Endpoint Type */
+    uint8_t ep_enable; /* Endpoint enable */
+    uint8_t *xfer_buf;
+    uint32_t xfer_len;
+    uint32_t actual_xfer_len;
+} usbd_ep_info;
+
+/* ch58x usb */
+static struct _ch58x_core_prvi {
+    uint8_t address; /* Address */
+    usbd_ep_info ep_in[CONFIG_USBDEV_EP_NUM];
+    usbd_ep_info ep_out[CONFIG_USBDEV_EP_NUM];
+    struct usb_setup_packet setup;
+} usb_dc_cfg;
+
+__WEAK void usb_dc_low_level_init(void)
+{
+}
+
+__WEAK void usb_dc_low_level_deinit(void)
+{
+}
+
+/**
+ * @brief            USB initialization
+ * @pre              None
+ * @param[in]        None
+ * @retval           >=0 success otherwise failure
+ */
+int usb_dc_init(uint8_t busid)
+{
+    R8_USBHS_PLL_CTRL = USBHS_PLL_EN;
+    R16_PIN_CONFIG |= RB_PIN_USB2_EN;
+    CH585_USBHS_DEV->CONTROL = USBHS_UD_RST_LINK | USBHS_UD_PHY_SUSPENDM;
+    CH585_USBHS_DEV->INT_EN = USBHS_UDIE_BUS_RST | USBHS_UDIE_SUSPEND | USBHS_UDIE_BUS_SLEEP | USBHS_UDIE_LPM_ACT | USBHS_UDIE_TRANSFER | USBHS_UDIE_LINK_RDY;
+    /* Enable all end points */
+    CH585_USBHS_DEV->UEP_TX_EN = 0xffff;
+    CH585_USBHS_DEV->UEP_RX_EN = 0xffff;
+
+    CH585_USBHS_DEV->BASE_MODE = USBHS_UD_SPEED_HIGH;
+    CH585_USBHS_DEV->CONTROL = USBHS_UD_DEV_EN | USBHS_UD_DMA_EN | USBHS_UD_LPM_EN | USBHS_UD_PHY_SUSPENDM;
+
+    CH585_USBHS_DEV->UEP_T_TOG_AUTO = 0xfe;
+    CH585_USBHS_DEV->UEP_R_TOG_AUTO = 0xfe;
+    usb_dc_low_level_init();
+    return 0;
+}
+
+int usb_dc_deinit(uint8_t busid)
+{
+    R8_USBHS_PLL_CTRL &= ~USBHS_PLL_EN;
+    R32_PIN_CONFIG &= ~RB_PIN_USB2_EN;
+
+    CH585_USBHS_DEV->CONTROL |= USBHS_UD_RST_SIE;
+    CH585_USBHS_DEV->CONTROL &= ~USBHS_UD_RST_SIE;
+    usb_dc_low_level_deinit();
+    return 0;
+}
+
+/**
+ * @brief            Set address
+ * @pre              None
+ * @param[in]        address :8-bit valid address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_set_address(uint8_t busid, const uint8_t address)
+{
+    if (address == 0) {
+        CH585_USBHS_DEV->DEV_AD = (CH585_USBHS_DEV->DEV_AD & 0x80) | address;
+    }
+    usb_dc_cfg.address = address;
+    return 0;
+}
+
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
+uint8_t usbd_get_port_speed(uint8_t busid)
+{
+    return USB_SPEED_HIGH;
+}
+
+/**
+ * @brief            Open endpoint
+ * @pre              None
+ * @param[in]        ep_cfg : Endpoint configuration structure pointer
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
+{
+    uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
+    if (epid > (CONFIG_USBDEV_EP_NUM - 1)) {
+        /**
+         * If you use ch58x, you can change the CONFIG_USBDEV_EP_NUM set to 8
+         */
+        USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
+        return -1;
+    }
+
+    uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+    USB_SET_MAX_LEN(epid, mps);
+
+    if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
+        usb_dc_cfg.ep_in[epid].ep_enable = true;
+        usb_dc_cfg.ep_in[epid].mps = mps;
+        usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        USB_SET_TX_CTRL(epid, USBHS_UEP_T_RES_NAK);
+        EPn_CLEAR_TX_DONE(epid);
+    } else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
+        usb_dc_cfg.ep_out[epid].ep_enable = true;
+        usb_dc_cfg.ep_out[epid].mps = mps;
+        usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        USB_SET_RX_CTRL(epid, USBHS_UEP_R_RES_NAK);
+    }
+
+    return 0;
+}
+
+/**
+ * @brief            Close endpoint
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_close(uint8_t busid, const uint8_t ep)
+{
+    uint8_t epid = USB_EP_GET_IDX(ep);
+    if (USB_EP_DIR_IS_IN(ep)) {
+        usb_dc_cfg.ep_in[epid].ep_enable = false;
+    } else if (USB_EP_DIR_IS_OUT(ep)) {
+        usb_dc_cfg.ep_out[epid].ep_enable = false;
+    }
+    return 0;
+}
+
+/**
+ * @brief            Endpoint setting stall
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (ep_idx == 0) {
+            CH585_USBHS_DEV->UEP0_RX_CTRL = USBHS_UEP_R_RES_STALL;
+        } else {
+            USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_STALL);
+        }
+    } else {
+        if (ep_idx == 0) {
+            CH585_USBHS_DEV->UEP0_TX_CTRL = USBHS_UEP_T_RES_STALL;
+        } else {
+            USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_STALL);
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief            Endpoint clear stall
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        USB_SET_RX_CTRL(ep_idx, USBHS_UEP_R_RES_ACK | USBHS_UEP_R_TOG_DATA0);
+    } else {
+        USB_SET_TX_CTRL(ep_idx, USBHS_UEP_T_RES_NAK | USBHS_UEP_T_TOG_DATA0);
+    }
+    return 0;
+}
+
+/**
+ * @brief            Check endpoint status
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @param[out]       stalled : Outgoing endpoint status
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
+{
+    if (USB_EP_DIR_IS_OUT(ep)) {
+    } else {
+    }
+    return 0;
+}
+
+/**
+ * @brief Setup in ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with tx dma.
+ *
+ * This function is called to write data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is transmitted
+ * out.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      Pointer to data to write
+ * @param[in]  data_len  Length of the data requested to write. This may
+ *                       be zero for a zero length status packet.
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
+        return -2;
+    }
+    if ((uint32_t)data & 0x03) {
+        return -3;
+    }
+
+    usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
+    usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
+    usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
+
+    if (ep_idx == 0) {
+        if (data_len == 0) {
+            USB_SET_TX_LEN(ep_idx, 0);
+        } else {
+            data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
+            USB_SET_TX_LEN(ep_idx, data_len);
+            CH585_USBHS_DEV->UEP0_DMA = (uint32_t)data;
+        }
+    } else {
+        if (data_len == 0) {
+            USB_SET_TX_LEN(ep_idx, 0);
+        } else {
+            data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
+            USB_SET_TX_LEN(ep_idx, data_len);
+            USB_SET_TX_DMA(ep_idx, (uint32_t)data);
+        }
+    }
+
+    EPn_SET_TX_VALID(ep_idx);
+    return 0;
+}
+
+/**
+ * @brief Setup out ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with rx dma.
+ *
+ * This function is called to read data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is received
+ * in.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      Pointer to data to read
+ * @param[in]  data_len  Max length of the data requested to read.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
+        return -2;
+    }
+    if ((uint32_t)data & 0x03) {
+        return -3;
+    }
+
+    usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
+    usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
+    usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
+
+    if (ep_idx == 0) {
+        if (data_len == 0) {
+        } else {
+            CH585_USBHS_DEV->UEP0_DMA = (uint32_t)data;
+        }
+    } else {
+        USB_SET_RX_DMA(ep_idx, (uint32_t)data);
+    }
+
+    EPn_SET_RX_VALID(ep_idx);
+    return 0;
+}
+
+static inline void handle_ep0_in(void)
+{
+    switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
+        case 1:
+            CH585_USBHS_DEV->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
+            EPn_SET_TX_NAK(0);
+            if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
+                usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
+                usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
+                usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
+            } else {
+                usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
+                usb_dc_cfg.ep_in[0].xfer_len = 0;
+                usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
+            }
+            break;
+        case 0:
+            /* Set */
+            switch (usb_dc_cfg.setup.bRequest) {
+                case USB_REQUEST_SET_ADDRESS:
+                    /* Fill in the equipment address */
+                    CH585_USBHS_DEV->DEV_AD = usb_dc_cfg.address;
+                    CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
+                    EPn_SET_TX_NAK(0);
+                    EPn_SET_RX_VALID(0);
+                    break;
+                default:
+                    /* Normal out state phase */
+                    CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
+                    EPn_SET_TX_NAK(0);
+                    EPn_SET_RX_VALID(0);
+                    break;
+            }
+            break;
+    }
+}
+
+static inline void handle_non_ep0_in(uint8_t epid)
+{
+    EPn_SET_TX_NAK(epid);
+    if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
+        /* Need start in again */
+        usb_dc_cfg.ep_in[epid].xfer_buf += usb_dc_cfg.ep_in[epid].mps;
+        usb_dc_cfg.ep_in[epid].xfer_len -= usb_dc_cfg.ep_in[epid].mps;
+        usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].mps;
+
+        uint32_t write_count = MIN(usb_dc_cfg.ep_in[epid].xfer_len, usb_dc_cfg.ep_in[epid].mps);
+        USB_SET_TX_LEN(epid, write_count);
+        USB_SET_TX_DMA(epid, (uint32_t)usb_dc_cfg.ep_in[epid].xfer_buf);
+
+        if (usb_dc_cfg.ep_in[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+            EPn_SET_TX_VALID(epid);
+        } else {
+            EPn_SET_TX_ISO_VALID(epid);
+        }
+    } else {
+        usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
+        usb_dc_cfg.ep_in[epid].xfer_len = 0;
+        usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
+    }
+}
+
+static inline void usb_process_ep_in(uint8_t epid)
+{
+    if (epid == 0) {
+        handle_ep0_in();
+    } else {
+        handle_non_ep0_in(epid);
+    }
+
+    EPn_CLEAR_TX_DONE(epid);
+}
+
+static inline void usb_process_ep_out(uint8_t epid)
+{
+    EPn_SET_RX_NAK(epid);
+    if (epid == 0) {
+        if (CH585_USBHS_DEV->UEP0_RX_CTRL & USBHS_UEP_R_SETUP_IS) {
+            CH585_USBHS_DEV->UEP0_RX_CTRL |= USBHS_UEP_R_TOG_DATA1;
+            CH585_USBHS_DEV->UEP0_TX_CTRL |= USBHS_UEP_T_TOG_DATA1;
+            if (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT == 0) {
+                /**
+                 * Ep0 The next in must be the status stage.
+                 * The device must reply to the host data 0 length packet.
+                 * Here, set the transmission length to 0 and the transmission status to ACK,
+                 * and wait for the host to send the in token to retrieve
+                 */
+                EPn_SET_TX_LEN(0, 0);
+                EPn_SET_TX_VALID(0);
+            }
+            usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&usb_dc_cfg.setup);
+        } else {
+            CH585_USBHS_DEV->UEP0_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
+            uint32_t read_count = EPn_GET_RX_LEN(0);
+            usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
+            usb_dc_cfg.ep_out[0].xfer_len -= read_count;
+            usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
+            if (read_count == 0) {
+                /* Out status, start reading setup */
+                CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
+                EPn_SET_RX_VALID(0);
+            }
+        }
+    } else {
+        if (USB_GET_RX_CTRL(epid) & USBHS_UEP_R_TOG_MATCH) {
+            uint32_t read_count = EPn_GET_RX_LEN(epid);
+            usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
+            usb_dc_cfg.ep_out[epid].actual_xfer_len += read_count;
+            usb_dc_cfg.ep_out[epid].xfer_len -= read_count;
+
+            if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
+                usbd_event_ep_out_complete_handler(0, ((epid) & 0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
+            } else {
+                USB_SET_RX_DMA(epid, (uint32_t)usb_dc_cfg.ep_out[epid].xfer_buf);
+                if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+                    EPn_SET_RX_VALID(epid);
+                } else {
+                    EPn_SET_RX_ISO_VALID(epid);
+                }
+            }
+        }
+    }
+
+    EPn_CLEAR_RX_DONE(epid);
+}
+
+static inline void usb_trans_end_process(void)
+{
+    uint8_t epid = (CH585_USBHS_DEV->INT_ST & USBHS_UDIS_EP_ID_MASK);
+    switch (CH585_USBHS_DEV->INT_ST & USBHS_UDIS_EP_DIR) {
+        case USBHS_UDIS_EP_DIR: /* in */
+            usb_process_ep_in(epid);
+            break;
+        case 0: /* setup or out */
+            usb_process_ep_out(epid);
+            break;
+        default:
+            break;
+    }
+}
+
+/**
+ * @brief            USB interrupt processing function
+ * @pre              None
+ * @param[in]        None
+ * @retval           None
+ */
+__attribute__((interrupt("WCH-Interrupt-fast")))
+__attribute__((section(".highcode"))) void
+USBD_IRQHandler(void)
+{
+    volatile uint8_t intflag = 0;
+    intflag = CH585_USBHS_DEV->INT_FG;
+
+    if (intflag & USBHS_UDIF_TRANSFER) {
+        usb_trans_end_process();
+    } else if (intflag & USBHS_UDIF_BUS_RST) {
+        /* Reset */
+        CH585_USBHS_DEV->DEV_AD = 0;
+        usbd_event_reset_handler(0);
+        /* Set ep0 rx vaild to start receive setup packet */
+        CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
+        // EPn_SET_RX_VALID(0);
+        R8_U2EP0_TX_CTRL = USBHS_UEP_T_RES_NAK;
+        R8_U2EP0_RX_CTRL = USBHS_UEP_R_RES_ACK;
+        CH585_USBHS_DEV->INT_FG = USBHS_UDIF_BUS_RST;
+    } else if (intflag & USBHS_UDIF_SUSPEND) {
+        if (CH585_USBHS_DEV->MIS_ST & 0x04) {
+            /* Suspend */
+        } else {
+            /* Wake up */
+        }
+        CH585_USBHS_DEV->INT_FG = USBHS_UDIF_SUSPEND;
+    } else {
+        CH585_USBHS_DEV->INT_FG = intflag;
+    }
+}

+ 450 - 0
components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h

@@ -0,0 +1,450 @@
+#pragma once
+
+/**********************************/
+/*********USB high speed**********/
+/**********************************/
+typedef volatile unsigned short *PUINT16V;
+typedef volatile unsigned long *PUINT32V;
+typedef volatile unsigned char *PUINT8V;
+
+/* USB high speed device register */
+#define R8_USB2_CTRL            (*((PUINT8V)0x40009000)) // RW, USB_high_speed control register
+#define USBHS_UD_LPM_EN         0x80                     // RW, enable LPM
+#define USBHS_UD_DEV_EN         0x20                     // RW, enable USB equipment
+#define USBHS_UD_DMA_EN         0x10                     // RW, enable DMA transmit
+#define USBHS_UD_PHY_SUSPENDM   0x08                     // RW, suspeng USB PHY
+#define USBHS_UD_CLR_ALL        0x04                     // RW, clear all interupt flag
+#define USBHS_UD_RST_SIE        0x02                     // RW, reset USB protocol processor,including end point register
+#define USBHS_UD_RST_LINK       0x01                     // RW, enable LNK layer reset
+#define R8_USB2_BASE_MODE       (*((PUINT8V)0x40009001)) // RW, USB_high_speed mode control register
+#define USBHS_UD_SPEED_FULL     0x00
+#define USBHS_UD_SPEED_HIGH     0x01
+#define USBHS_UD_SPEED_LOW      0x02
+#define USBHS_UD_SPEED_TYPE     0x03                      // RW, speed mode excpeted by the equipment,00:full speed, 01:high speed, 10:low speed
+#define R8_USB2_INT_EN          (*((PUINT8V)0x40009002))  // RW, USB_high_speed intreurpt enable register
+#define USBHS_UDIE_FIFO_OVER    0x80                      // RW, enable fifo overflow interupt
+#define USBHS_UDIE_LINK_RDY     0x40                      // RW, enable USB conect interupt
+#define USBHS_UDIE_SOF_ACT      0x20                      // RW, enable SOF package received interupt
+#define USBHS_UDIE_TRANSFER     0x10                      // RW, enable USB transmit end interupt
+#define USBHS_UDIE_LPM_ACT      0x08                      // RW, enable lpm transmit end interupt
+#define USBHS_UDIE_BUS_SLEEP    0x04                      // RW, enable usb bus sleep interupt
+#define USBHS_UDIE_SUSPEND      0x02                      // RW, enable usb bus suspend interupt
+#define USBHS_UDIE_BUS_RST      0x01                      // RW, enable usb bus reset interupt
+#define R8_USB2_DEV_AD          (*((PUINT8V)0x40009003))  // RW, USB_high_speed device adress register
+#define USBHS_UD_DEV_ADDR       0x7F                      // RW, adress of usb equipment
+#define R8_USB2_WAKE_CTRL       (*((PUINT8V)0x40009004))  // RW, USB_high_speed wake up remotely register
+#define USBHS_UD_UD_REMOTE_WKUP 0x01                      // RW1, wake up remotely and auto reset hardware
+#define R8_USB2_TEST_MODE       (*((PUINT8V)0x40009005))  // RW, USB_high_speed test mode register
+#define USBHS_UD_TEST_EN        0x80                      // RW, enable test mode
+#define USBHS_UD_TEST_SE0NAK    0x08                      // RW, output SE0 when in test mode
+#define USBHS_UD_TEST_PKT       0x04                      // RW, output one package(including DATA0,data and length of end pont4) when in test mode,not work on virtual equipment
+#define USBHS_UD_TEST_K         0x02                      // RW, output K when in test mode
+#define USBHS_UD_TEST_J         0x01                      // RW, output J when in test mode
+#define R16_USB2_LPM_DATA       (*((PUINT16V)0x40009006)) // RW, USB_high_speed power control register
+#define USBHS_UD_LPM_BUSY       0x8000                    // RW, power control busy
+#define USBHS_UD_LPM_DATA       0x07FF                    // RO, power control data
+#define R8_USB2_INT_FG          (*((PUINT8V)0x40009008))  // RW, USB_high_speed interupt flag register
+#define USBHS_UDIF_FIFO_OV      0x80                      // RW1, clear fifo overflow interupt flag
+#define USBHS_UDIF_LINK_RDY     0x40                      // RW1, clear USB conect interupt flag
+#define USBHS_UDIF_RX_SOF       0x20                      // RW1, clear SOF package received interupt flag
+#define USBHS_UDIF_TRANSFER     0x10                      // RO,  USB transmit end interupt flag,cleared by USBHS_UDMS_HS_MOD
+#define USBHS_UDIF_LPM_ACT      0x08                      // RW1, clear lpm transmit end interupt flag
+#define USBHS_UDIF_BUS_SLEEP    0x04                      // RW1, clear usb bus sleep interupt flag
+#define USBHS_UDIF_SUSPEND      0x02                      // RW1, clear usb bus suspend interupt flag
+#define USBHS_UDIF_BUS_RST      0x01                      // RW1, clear usb bus reset interupt flag
+#define R8_USB2_INT_ST          (*((PUINT8V)0x40009009))  // RW, USB_high_speed interupt status register
+#define USBHS_UDIS_EP_DIR       0x10                      // RO, end point tranfer diector of data
+#define USBHS_UDIS_EP_ID_MASK   0x07                      // RO, number of end point which data transmission occured
+#define R8_USB2_MIS_ST          (*((PUINT8V)0x4000900A))  // RW, USB_high_speed miscellaneous register
+#define USBHS_UDMS_HS_MOD       0x80                      // RO, host with high speed
+#define USBHS_UDMS_SUSP_REQ     0x10                      // RO, requirment of suspending USB
+#define USBHS_UDMS_SIE_FREE     0x08                      // RO, USB free state
+#define USBHS_UDMS_SLEEP        0x04                      // RO, USB sleep state
+#define USBHS_UDMS_SUSPEND      0x02                      // RO, USB in suspend state
+#define USBHS_UDMS_READY        0x01                      // RO, USB in connected state
+#define R16_USB2_FRAME_NO       (*((PUINT16V)0x4000900C)) // RW, USB_high_speed frame number register
+#define USBHS_UD_MFRAME_NO      0xE000
+#define USBHS_UD_FRAME_NO       0x07FF
+#define R16_USB2_BUS            (*((PUINT16V)0x4000900E)) // RW, USB_high_speed bus status register
+#define USBHS_USB_DM_ST         0x08
+#define USBHS_USB_DP_ST         0x04
+#define USB_WAKEUP              0x01
+#define R16_U2EP_TX_EN          (*((PUINT16V)0x40009010)) // RW, USB_high_speed end point transmit enable register
+/* Bit definition for R16_U2EP_TX_EN & R16_U2EP_RX_EN register */
+#define RB_EP0_EN  0x0001
+#define RB_EP1_EN  0x0002
+#define RB_EP2_EN  0x0004
+#define RB_EP3_EN  0x0008
+#define RB_EP4_EN  0x0010
+#define RB_EP5_EN  0x0020
+#define RB_EP6_EN  0x0040
+#define RB_EP7_EN  0x0080
+#define RB_EP8_EN  0x0100
+#define RB_EP9_EN  0x0200
+#define RB_EP10_EN 0x0400
+#define RB_EP11_EN 0x0800
+#define RB_EP12_EN 0x1000
+#define RB_EP13_EN 0x2000
+#define RB_EP14_EN 0x4000
+#define RB_EP15_EN 0x8000
+
+#define R16_U2EP_RX_EN         (*((PUINT16V)0x40009012)) // RW, USB_high_speed end point receive enableregister
+#define USBHS_UEP_RX_EN        0xFFFF
+#define R16_U2EP_T_TOG_AUTO    (*((PUINT16V)0x40009014)) // RW, USB_high_speed end point transmit auto toggle enable register
+#define USBHS_UEP_T_TOG_AUTO   0xFF
+#define R16_U2EP_R_TOG_AUTO    (*((PUINT16V)0x40009016)) // RW, USB_high_speed end point receive auto toggle enable register
+#define USBHS_UEP_R_TOG_AUTO   0xFF
+#define R8_U2EP_T_BURST        (*((PUINT8V)0x40009018)) // RW, USB_high_speed end point transmit burst register
+#define USBHS_UEP_T_BURST_EN   0xFF
+#define R8_U2EP_T_BURST_MODE   (*((PUINT8V)0x40009019)) // RW, USB_high_speed end point transmit burst mode register
+#define USBHS_UEP_T_BURST_MODE 0xFF
+#define R8_U2EP_R_BURST        (*((PUINT8V)0x4000901A)) // RW, USB_high_speed end point receive burst register
+#define USBHS_UEP_R_BURST_EN   0xFF
+#define R8_U2EP_R_RES_MODE     (*((PUINT8V)0x4000901B)) // RW, USB_high_speed end point transmit reply mode register
+#define USBHS_UEP_R_RES_MODE   0xFF
+#define R32_U2EP_AF_MODE       (*((PUINT32V)0x4000901C)) // RW, USB_high_speed end point multiplexing register
+#define USBHS_UEP_T_AF         0xFE
+#define R32_U2EP0_DMA          (*((PUINT32V)0x40009020)) // RW, USB_high_speed end point0 begin adress of DMA buffer register
+#define UEPn_DMA               0x01FFFF
+#define R32_U2EP1_RX_DMA       (*((PUINT32V)0x40009024)) // RW, USB_high_speed end point1 begin adress of DMA receive buffer register
+#define R32_U2EP2_RX_DMA       (*((PUINT32V)0x40009028)) // RW, USB_high_speed end point2 begin adress of DMA receive buffer register
+#define R32_U2EP3_RX_DMA       (*((PUINT32V)0x4000902C)) // RW, USB_high_speed end point3 begin adress of DMA receive buffer register
+#define R32_U2EP4_RX_DMA       (*((PUINT32V)0x40009030)) // RW, USB_high_speed end point4 begin adress of DMA receive buffer register
+#define R32_U2EP5_RX_DMA       (*((PUINT32V)0x40009034)) // RW, USB_high_speed end point5 begin adress of DMA receive buffer register
+#define R32_U2EP6_RX_DMA       (*((PUINT32V)0x40009038)) // RW, USB_high_speed end point6 begin adress of DMA receive buffer register
+#define R32_U2EP7_RX_DMA       (*((PUINT32V)0x4000903C)) // RW, USB_high_speed end point7 begin adress of DMA receive buffer register
+#define UEPn_RX_DMA            0x01FFFF
+#define R32_U2EP1_TX_DMA       (*((PUINT32V)0x40009040)) // RW, USB_high_speed end point1 begin adress of DMA transmit buffer register
+#define R32_U2EP2_TX_DMA       (*((PUINT32V)0x40009044)) // RW, USB_high_speed end point2 begin adress of DMA transmit buffer register
+#define R32_U2EP3_TX_DMA       (*((PUINT32V)0x40009048)) // RW, USB_high_speed end point3 begin adress of DMA transmit buffer register
+#define R32_U2EP4_TX_DMA       (*((PUINT32V)0x4000904C)) // RW, USB_high_speed end point4 begin adress of DMA transmit buffer register
+#define R32_U2EP5_TX_DMA       (*((PUINT32V)0x40009050)) // RW, USB_high_speed end point5 begin adress of DMA transmit buffer register
+#define R32_U2EP6_TX_DMA       (*((PUINT32V)0x40009054)) // RW, USB_high_speed end point6 begin adress of DMA transmit buffer register
+#define R32_U2EP7_TX_DMA       (*((PUINT32V)0x40009058)) // RW, USB_high_speed end point7 begin adress of DMA transmit buffer register
+#define UEPn_TX_DMA            0x01FFFF
+#define R32_U2EP0_MAX_LEN      (*((PUINT32V)0x4000905C)) // RW, USB_high_speed end point0 max length package register
+#define R32_U2EP1_MAX_LEN      (*((PUINT32V)0x40009060)) // RW, USB_high_speed end point1 max length package register
+#define R32_U2EP2_MAX_LEN      (*((PUINT32V)0x40009064)) // RW, USB_high_speed end point2 max length package register
+#define R32_U2EP3_MAX_LEN      (*((PUINT32V)0x40009068)) // RW, USB_high_speed end point3 max length package register
+#define R32_U2EP4_MAX_LEN      (*((PUINT32V)0x4000906C)) // RW, USB_high_speed end point4 max length package register
+#define R32_U2EP5_MAX_LEN      (*((PUINT32V)0x40009070)) // RW, USB_high_speed end point5 max length package register
+#define R32_U2EP6_MAX_LEN      (*((PUINT32V)0x40009074)) // RW, USB_high_speed end point6 max length package register
+#define R32_U2EP7_MAX_LEN      (*((PUINT32V)0x40009078)) // RW, USB_high_speed end point7 max length package register
+#define UEPn_MAX_LEN           0x007F
+#define R16_U2EP0_RX_LEN       (*((PUINT16V)0x4000907C)) // RW, USB_high_speed end point0 length of receive register
+#define UEP0_RX_LEN            0x007F
+#define R16_U2EP1_RX_LEN       (*((PUINT16V)0x40009080)) // RW, USB_high_speed end point1 single received length register
+#define R16_U2EP1_R_SIZE       (*((PUINT16V)0x40009082)) // RW, USB_high_speed end point1 total received length register
+#define R16_U2EP2_RX_LEN       (*((PUINT16V)0x40009084)) // RW, USB_high_speed end point2 single received length register
+#define R16_U2EP2_R_SIZE       (*((PUINT16V)0x40009086)) // RW, USB_high_speed end point2 total received length register
+#define R16_U2EP3_RX_LEN       (*((PUINT16V)0x40009088)) // RW, USB_high_speed end point3 single received length register
+#define R16_U2EP3_R_SIZE       (*((PUINT16V)0x4000908A)) // RW, USB_high_speed end point3 total received length register
+#define R16_U2EP4_RX_LEN       (*((PUINT16V)0x4000908C)) // RW, USB_high_speed end point4 single received length register
+#define R16_U2EP4_R_SIZE       (*((PUINT16V)0x4000908E)) // RW, USB_high_speed end point4 total received length register
+#define R16_U2EP5_RX_LEN       (*((PUINT16V)0x40009090)) // RW, USB_high_speed end point5 single received length register
+#define R16_U2EP5_R_SIZE       (*((PUINT16V)0x40009092)) // RW, USB_high_speed end point5 total received length register
+#define R16_U2EP6_RX_LEN       (*((PUINT16V)0x40009094)) // RW, USB_high_speed end point6 single received length register
+#define R16_U2EP6_R_SIZE       (*((PUINT16V)0x40009096)) // RW, USB_high_speed end point6 total received length register
+#define R16_U2EP7_RX_LEN       (*((PUINT16V)0x40009098)) // RW, USB_high_speed end point7 single received length register
+#define R16_U2EP7_R_SIZE       (*((PUINT16V)0x4000909A)) // RW, USB_high_speed end point7 total received length register
+#define UEPn_RX_LEN            0xFFFF
+#define UEPn_R_SIZE            0xFFFF
+#define R16_U2EP0_T_LEN        (*((PUINT16V)0x4000909C)) // RW, USB_high_speed end point0 length of transmission register
+#define UEP0_T_LEN             0x7F
+#define R8_U2EP0_TX_CTRL       (*((PUINT8V)0x4000909E))  // RW, USB_high_speed end point0 transmit control register
+#define R8_U2EP0_RX_CTRL       (*((PUINT8V)0x4000909F))  // RW, USB_high_speed end point0 receive control register
+#define R16_U2EP1_T_LEN        (*((PUINT16V)0x400090A0)) // RW, USB_high_speed end point1 length of transmission register
+#define R8_U2EP1_TX_CTRL       (*((PUINT8V)0x400090A2))  // RW, USB_high_speed end point1 transmit control register
+#define R8_U2EP1_RX_CTRL       (*((PUINT8V)0x400090A3))  // RW, USB_high_speed end point1 receive control register
+#define R16_U2EP2_T_LEN        (*((PUINT16V)0x400090A4)) // RW, USB_high_speed end point2 length of transmission register
+#define R8_U2EP2_TX_CTRL       (*((PUINT8V)0x400090A6))  // RW, USB_high_speed end point2 transmit control register
+#define R8_U2EP2_RX_CTRL       (*((PUINT8V)0x400090A7))  // RW, USB_high_speed end point2 receive control register
+#define R16_U2EP3_T_LEN        (*((PUINT16V)0x400090A8)) // RW, USB_high_speed end point3 length of transmission register
+#define R8_U2EP3_TX_CTRL       (*((PUINT8V)0x400090AA))  // RW, USB_high_speed end point3 transmit control register
+#define R8_U2EP3_RX_CTRL       (*((PUINT8V)0x400090AB))  // RW, USB_high_speed end point3 receive control register
+#define R16_U2EP4_T_LEN        (*((PUINT16V)0x400090AC)) // RW, USB_high_speed end point4 length of transmission register
+#define R8_U2EP4_TX_CTRL       (*((PUINT8V)0x400090AE))  // RW, USB_high_speed end point4 transmit control register
+#define R8_U2EP4_RX_CTRL       (*((PUINT8V)0x400090AF))  // RW, USB_high_speed end point4 receive control register
+#define R16_U2EP5_T_LEN        (*((PUINT16V)0x400090B0)) // RW, USB_high_speed end point5 length of transmission register
+#define R8_U2EP5_TX_CTRL       (*((PUINT8V)0x400090B2))  // RW, USB_high_speed end point5 transmit control register
+#define R8_U2EP5_RX_CTRL       (*((PUINT8V)0x400090B3))  // RW, USB_high_speed end point5 receive control register
+#define R16_U2EP6_T_LEN        (*((PUINT16V)0x400090B4)) // RW, USB_high_speed end point6 length of transmission register
+#define R8_U2EP6_TX_CTRL       (*((PUINT8V)0x400090B6))  // RW, USB_high_speed end point6 transmit control register
+#define R8_U2EP6_RX_CTRL       (*((PUINT8V)0x400090B7))  // RW, USB_high_speed end point6 receive control register
+#define R16_U2EP7_T_LEN        (*((PUINT16V)0x400090B8)) // RW, USB_high_speed end point7 length of transmission register
+#define R8_U2EP7_TX_CTRL       (*((PUINT8V)0x400090BA))  // RW, USB_high_speed end point7 transmit control register
+#define R8_U2EP7_RX_CTRL       (*((PUINT8V)0x400090BB))  // RW, USB_high_speed end point7 receive control register
+/**R16_UEPn_T_LEN**/
+#define UEPn_T_LEN 0xFFFF
+/**R8_UEPn_TX_CTRL**/
+#define USBHS_UEP_T_DONE      0x80
+#define USBHS_UEP_T_NAK_ACT   0x40
+#define USBHS_UEP_T_TOG_MASK  0x0C
+#define USBHS_UEP_T_TOG_MDATA 0x0C
+#define USBHS_UEP_T_TOG_DATA2 0x08
+#define USBHS_UEP_T_TOG_DATA1 0x04
+#define USBHS_UEP_T_TOG_DATA0 0x00
+#define USBHS_UEP_T_RES_MASK  0x03
+#define USBHS_UEP_T_RES_ACK   0x02
+#define USBHS_UEP_T_RES_STALL 0x01
+#define USBHS_UEP_T_RES_NAK   0x00
+
+/**R8_UEPn_RX_CTRL**/
+#define USBHS_UEP_R_DONE      0x80
+#define USBHS_UEP_R_NAK_ACT   0x40
+#define USBHS_UEP_R_NAK_TOG   0x20
+#define USBHS_UEP_R_TOG_MATCH 0x10
+#define USBHS_UEP_R_SETUP_IS  0x08
+#define USBHS_UEP_R_TOG_MASK  0x0C
+#define USBHS_UEP_R_TOG_MDATA 0x0C
+#define USBHS_UEP_R_TOG_DATA2 0x08
+#define USBHS_UEP_R_TOG_DATA1 0x04
+#define USBHS_UEP_R_TOG_DATA0 0x00
+#define USBHS_UEP_R_RES_MASK  0x03
+#define USBHS_UEP_R_RES_ACK   0x02
+#define USBHS_UEP_R_RES_STALL 0x01
+#define USBHS_UEP_R_RES_NAK   0x00
+
+#define R16_U2EP_T_ISO      (*((PUINT16V)0x400090BC)) // RW, USB_high_speed end point transmit sync mode register
+#define USBHS_UEP1_T_ISO_EN 0x02
+#define USBHS_UEP2_T_ISO_EN 0x04
+#define USBHS_UEP3_T_ISO_EN 0x08
+#define USBHS_UEP4_T_ISO_EN 0x10
+#define USBHS_UEP5_T_ISO_EN 0x20
+#define USBHS_UEP6_T_ISO_EN 0x40
+#define USBHS_UEP7_T_ISO_EN 0x80
+#define R16_U2EP_R_ISO      (*((PUINT16V)0x400090BE)) // RW, USB_high_speed end point receive sync mode register
+#define USBHS_UEP1_R_ISO_EN 0x02
+#define USBHS_UEP2_R_ISO_EN 0x04
+#define USBHS_UEP3_R_ISO_EN 0x08
+#define USBHS_UEP4_R_ISO_EN 0x10
+#define USBHS_UEP5_R_ISO_EN 0x20
+#define USBHS_UEP6_R_ISO_EN 0x40
+#define USBHS_UEP7_R_ISO_EN 0x80
+
+/* USB high speed host register  */
+#define R8_U2H_CFG            (*((PUINT8V)0x40009100)) // RW, USB_high_speed register
+#define USBHS_UH_LPM_EN       0x80
+#define USBHS_UH_FORCE_FS     0x40
+#define USBHS_UH_SOF_EN       0x20
+#define USBHS_UH_DMA_EN       0x10
+#define USBHS_UH_PHY_SUSPENDM 0x08
+#define USBHS_UH_CLR_ALL      0x04
+#define USBHS_RST_SIE         0x02
+#define USBHS_RST_LINK        0x01
+#define R8_U2H_INT_EN         (*((PUINT8V)0x40009102)) // RW, USB_high_speed register
+#define USBHS_UHIE_FIFO_OVER  0x80
+#define USBHS_UHIE_TX_HALT    0x40
+#define USBHS_UHIE_SOF_ACT    0x20
+#define USBHS_UHIE_TRANSFER   0x10
+#define USBHS_UHIE_RESUME_ACT 0x08
+#define USBHS_UHIE_WKUP_ACT   0x04
+#define R8_U2H_DEV_AD         (*((PUINT8V)0x40009103)) // RW, USB_high_speed register
+#define USBHS_UH_DEV_ADDR     0xFF
+#define R32_U2H_CONTROL       (*((PUINT32V)0x40009104)) // RW, USB_high_speed register
+#define USBHS_UH_RX_NO_RES    0x800000
+#define USBHS_UH_TX_NO_RES    0x400000
+#define USBHS_UH_RX_NO_DATA   0x200000
+#define USBHS_UH_TX_NO_DATA   0x100000
+#define USBHS_UH_PRE_PID_EN   0x080000
+#define USBHS_UH_SPLIT_VALID  0x040000
+#define USBHS_UH_LPM_VALID    0x020000
+#define USBHS_UH_HOST_ACTION  0x010000
+#define USBHS_UH_BUF_MODE     0x0400
+#define USBHS_UH_T_TOG_MASK   0x0300
+#define USBHS_UH_T_TOG_MDATA  0x0300
+#define USBHS_UH_T_TOG_DATA2  0x0200
+#define USBHS_UH_T_TOG_DATA1  0x0100
+#define USBHS_UH_T_TOG_DATA0  0x0000
+#define USBHS_UH_T_ENDP_MASK  0xF0
+#define USBHS_UH_T_TOKEN_MASK 0x0F
+
+#define R8_U2H_INT_FLAG            (*((PUINT8V)0x40009108)) // RW, USB_high_speed register
+#define USBHS_UHIF_FIFO_OVER       0x80
+#define USBHS_UHIF_TX_HALT         0x40
+#define USBHS_UHIF_SOF_ACT         0x20
+#define USBHS_UHIF_TRANSFER        0x10
+#define USBHS_UHIF_RESUME_ACT      0x08
+#define USBHS_UHIF_WKUP_ACT        0x04
+#define R8_U2H_INT_ST              (*((PUINT8V)0x40009109)) // RW, USB_high_speed register
+#define USBHS_UHIF_PORT_RX_RESUME  0x10
+#define USBHS_UH_R_TOKEN_MASK      0x0F
+#define R8_U2H_MIS_ST              (*((PUINT8V)0x4000910A)) // RW, USB_high_speed register
+#define USBHS_UHMS_BUS_SE0         0x80
+#define USBHS_UHMS_BUS_J           0x40
+#define USBHS_UHMS_LINESTATE       0x30
+#define USBHS_UHMS_USB_WAKEUP      0x08
+#define USBHS_UHMS_SOF_ACT         0x04
+#define USBHS_UHMS_SOF_PRE         0x02
+#define USBHS_UHMS_SOF_FREE        0x01
+#define R32_U2H_LPM_DATA           (*((PUINT32V)0x4000910C)) // RW, USB_high_speed register
+#define USBHS_UH_LPM_DATA          0x07FF
+#define R32_U2H_SPLIT_DATA         (*((PUINT32V)0x40009110)) // RW, USB_high_speed register
+#define USBHS_UH_SPLIT_DATA        0x07FFFF
+#define R32_U2H_FRAME              (*((PUINT32V)0x40009114)) // RW, USB_high_speed register
+#define USBHS_UH_SOF_CNT_CLR       0x02000000
+#define USBHS_UH_SOF_CNT_EN        0x01000000
+#define USBHS_UH_MFRAME_NO         0x070000
+#define USBHS_UH_FRAME_NO          0x07FF
+#define R32_U2H_TX_LEN             (*((PUINT32V)0x40009118)) // RW, USB_high_speed register
+#define USBHS_UH_TX_LEN            0x07FF
+#define R32_U2H_RX_LEN             (*((PUINT32V)0x4000911C)) // RW, USB_high_speed register
+#define USBHS_UH_RX_LEN            0x07FF
+#define R32_U2H_RX_MAX_LEN         (*((PUINT32V)0x40009120)) // RW, USB_high_speed register
+#define USBHS_UH_RX_MAX_LEN        0x07FF
+#define R32_U2H_RX_DMA             (*((PUINT32V)0x40009124)) // RW, USB_high_speed register
+#define USBHS_R32_UH_RX_DMA        0x01FFFF
+#define R32_U2H_TX_DMA             (*((PUINT32V)0x40009128)) // RW, USB_high_speed register
+#define USBHS_R32_UH_TX_DMA        0x01FFFF
+#define R32_U2H_PORT_CTRL          (*((PUINT32V)0x4000912C)) // RW, USB_high_speed register
+#define USBHS_UH_BUS_RST_LONG      0x010000
+#define USBHS_UH_PORT_SLEEP_BESL   0xF000
+#define USBHS_UH_CLR_PORT_SLEEP    0x0100
+#define USBHS_UH_CLR_PORT_CONNECT  0x20
+#define USBHS_UH_CLR_PORT_EN       0x10
+#define USBHS_UH_SET_PORT_SLEEP    0x08
+#define USBHS_UH_CLR_PORT_SUSP     0x04
+#define USBHS_UH_SET_PORT_SUSP     0x02
+#define USBHS_UH_SET_PORT_RESET    0x01
+#define R8_U2H_PORT_CFG            (*((PUINT8V)0x40009130)) // RW, USB_high_speed register
+#define USBHS_UH_PD_EN             0x80
+#define USBHS_UH_HOST_EN           0x01
+#define R8_U2H_PORT_INT_EN         (*((PUINT8V)0x40009132)) // RW, USB_high_speed register
+#define USBHS_UHIE_PORT_SLP        0x20
+#define USBHS_UHIE_PORT_RESET      0x10
+#define USBHS_UHIE_PORT_SUSP       0x04
+#define USBHS_UHIE_PORT_EN         0x02
+#define USBHS_UHIE_PORT_CONNECT    0x01
+#define R8_U2H_PORT_TEST_CT        (*((PUINT8V)0x40009133)) // RW, USB_high_speed register
+#define USBHS_UH_TEST_FORCE_EN     0x04
+#define USBHS_UH_TEST_K            0x02
+#define USBHS_UH_TEST_J            0x01
+#define R16_U2H_PORT_ST            (*((PUINT16V)0x40009134)) // RW, USB_high_speed register
+#define USBHS_UHIS_PORT_TEST       0x0800
+#define USBHS_UHIS_PORT_SPEED_MASK 0x0600
+#define USBHS_UHIS_PORT_HS         0x0400
+#define USBHS_UHIS_PORT_LS         0x0200
+#define USBHS_UHIS_PORT_FS         0x0000
+#define USBHS_UHIS_PORT_SLP        0x20
+#define USBHS_UHIS_PORT_RST        0x10
+#define USBHS_UHIS_PORT_SUSP       0x04
+#define USBHS_UHIS_PORT_EN         0x02
+#define USBHS_UHIS_PORT_CONNECT    0x01
+#define R8_U2H_PORT_CHG            (*((PUINT8V)0x40009136))
+#define USBHS_UHIF_PORT_SLP        0x20
+#define USBHS_UHIF_PORT_RESET      0x10
+#define USBHS_UHIF_PORT_SUSP       0x04
+#define USBHS_UHIF_PORT_EN         0x02
+#define USBHS_UHIF_PORT_CONNECT    0x01
+#define R32_U2H_BC_CTRL            (*((PUINT32V)0x4000913C))
+#define UDM_VSRC_ACT               0x0400
+#define UDM_BC_VSRC                0x0200
+#define UDP_BC_VSRC                0x0100
+#define BC_AUTO_MODE               0x40
+#define UDM_BC_CMPE                0x20
+#define UDP_BC_CMPE                0x10
+#define UDM_BC_CMPO                0x02
+#define UDP_BC_CMPO                0x01
+#define R8_USBHS_PLL_CTRL          (*((PUINT8V)0x40009200))
+#define USBHS_PLL_EN               0x04
+#define USBHS_PLL_LOWPOW           0x02
+#define USBHS_PLL_CKSEL            0x01
+
+#define __IO volatile /* defines 'read / write' permissions */
+
+typedef struct
+{
+    __IO uint8_t CONTROL;     /* 0x40009000 */
+    __IO uint8_t BASE_MODE;   /* 0x40009001 */
+    __IO uint8_t INT_EN;      /* 0x40009002 */
+    __IO uint8_t DEV_AD;      /* 0x40009003 */
+    __IO uint8_t WAKE_CTRL;   /* 0x40009004 远程唤醒寄存器 */
+    __IO uint8_t TEST_MODE;   /* 0x40009005 测试模式寄存器 */
+    __IO uint16_t LPM_DATA;   /* 0x40009006 */
+    __IO uint8_t INT_FG;      /* 0x40009008 */
+    __IO uint8_t INT_ST;      /* 0x40009009 */
+    __IO uint8_t MIS_ST;      /* 0x4000900a */
+    __IO uint8_t RESERVE0;    /* 0x4000900b */
+    __IO uint16_t FRAME_NO;   /* 0x4000900c */
+    __IO uint16_t USB_BUS;    /* 0x4000900e */
+    __IO uint16_t UEP_TX_EN;  /* 0x40009010 */
+    __IO uint16_t UEP_RX_EN;  /* 0x40009012 */
+
+    __IO uint16_t UEP_T_TOG_AUTO;  /* 0x40009014 */
+    __IO uint16_t UEP_R_TOG_AUTO;  /* 0x40009016 */
+    __IO uint8_t UEP_T_BURST;      /* 0x40009018 */
+    __IO uint8_t UEP_T_BURST_MODE; /* 0x40009019 */
+    __IO uint8_t UEP_R_BURST;      /* 0x4000901a */
+    __IO uint8_t UEP_R_RES_MODE;   /* 0x4000901b */
+    __IO uint32_t UEP_AF_MODE;     /* 0x4000901c */
+
+    __IO uint32_t UEP0_DMA;    /* 0x40009020 */
+    __IO uint32_t UEP1_RX_DMA; /* 0x40009024 */
+    __IO uint32_t UEP2_RX_DMA; /* 0x40009028 */
+    __IO uint32_t UEP3_RX_DMA; /* 0x4000902c */
+    __IO uint32_t UEP4_RX_DMA; /* 0x40009030 */
+    __IO uint32_t UEP5_RX_DMA; /* 0x40009034 */
+    __IO uint32_t UEP6_RX_DMA; /* 0x40009038 */
+    __IO uint32_t UEP7_RX_DMA; /* 0x4000903c */
+
+    __IO uint32_t UEP1_TX_DMA; /* 0x40009040 */
+    __IO uint32_t UEP2_TX_DMA; /* 0x40009044 */
+    __IO uint32_t UEP3_TX_DMA; /* 0x40009048 */
+    __IO uint32_t UEP4_TX_DMA; /* 0x4000904c */
+    __IO uint32_t UEP5_TX_DMA; /* 0x40009050 */
+    __IO uint32_t UEP6_TX_DMA; /* 0x40009054 */
+    __IO uint32_t UEP7_TX_DMA; /* 0x40009058 */
+
+    __IO uint32_t UEP0_MAX_LEN; /* 0x4000905c */
+    __IO uint32_t UEP1_MAX_LEN; /* 0x40009060 */
+    __IO uint32_t UEP2_MAX_LEN; /* 0x40009064 */
+    __IO uint32_t UEP3_MAX_LEN; /* 0x40009068 */
+    __IO uint32_t UEP4_MAX_LEN; /* 0x4000906c */
+    __IO uint32_t UEP5_MAX_LEN; /* 0x40009070 */
+    __IO uint32_t UEP6_MAX_LEN; /* 0x40009074 */
+    __IO uint32_t UEP7_MAX_LEN; /* 0x40009078 */
+
+    __IO uint16_t USB_EP0_RX_LEN; /* 0x4000907c */
+    __IO uint16_t RESERVE1;       /* 0x4000907e */
+    __IO uint16_t UEP1_RX_LEN;    /* 0x40009080 */
+    __IO uint16_t UEP1_R_SIZE;    /* 0x40009082 */
+    __IO uint16_t UEP2_RX_LEN;    /* 0x40009084 */
+    __IO uint16_t UEP2_R_SIZE;    /* 0x40009086 */
+    __IO uint16_t UEP3_RX_LEN;    /* 0x40009088 */
+    __IO uint16_t UEP3_R_SIZE;    /* 0x4000908a */
+    __IO uint16_t UEP4_RX_LEN;    /* 0x4000908c */
+    __IO uint16_t UEP4_R_SIZE;    /* 0x4000908e */
+    __IO uint16_t UEP5_RX_LEN;    /* 0x40009090 */
+    __IO uint16_t UEP5_R_SIZE;    /* 0x40009092 */
+    __IO uint16_t UEP6_RX_LEN;    /* 0x40009094 */
+    __IO uint16_t UEP6_R_SIZE;    /* 0x40009096 */
+    __IO uint16_t UEP7_RX_LEN;    /* 0x40009098 */
+    __IO uint16_t UEP7_R_SIZE;    /* 0x4000909a */
+
+    __IO uint16_t UEP0_TX_LEN; /* 0x4000909c */
+    __IO uint8_t UEP0_TX_CTRL; /* 0x4000909e */
+    __IO uint8_t UEP0_RX_CTRL; /* 0x4000909f */
+    __IO uint16_t UEP1_TX_LEN; /* 0x400090a0 */
+    __IO uint8_t UEP1_TX_CTRL; /* 0x400090a2 */
+    __IO uint8_t UEP1_RX_CTRL; /* 0x400090a3 */
+    __IO uint16_t UEP2_TX_LEN; /* 0x400090a4 */
+    __IO uint8_t UEP2_TX_CTRL; /* 0x400090a6 */
+    __IO uint8_t UEP2_RX_CTRL; /* 0x400090a7 */
+    __IO uint16_t UEP3_TX_LEN; /* 0x400090a8 */
+    __IO uint8_t UEP3_TX_CTRL; /* 0x400090aa */
+    __IO uint8_t UEP3_RX_CTRL; /* 0x400090ab */
+    __IO uint16_t UEP4_TX_LEN; /* 0x400090ac */
+    __IO uint8_t UEP4_TX_CTRL; /* 0x400090ae */
+    __IO uint8_t UEP4_RX_CTRL; /* 0x400090af */
+    __IO uint16_t UEP5_TX_LEN; /* 0x400090b0 */
+    __IO uint8_t UEP5_TX_CTRL; /* 0x400090b2 */
+    __IO uint8_t UEP5_RX_CTRL; /* 0x400090b3 */
+    __IO uint16_t UEP6_TX_LEN; /* 0x400090b4 */
+    __IO uint8_t UEP6_TX_CTRL; /* 0x400090b6 */
+    __IO uint8_t UEP6_RX_CTRL; /* 0x400090b7 */
+    __IO uint16_t UEP7_TX_LEN; /* 0x400090b8 */
+    __IO uint8_t UEP7_TX_CTRL; /* 0x400090ba */
+    __IO uint8_t UEP7_RX_CTRL; /* 0x400090bb */
+    __IO uint16_t UEP_TX_ISO;  /* 0x400090bc */
+    __IO uint16_t UEP_RX_ISO;  /* 0x400090be */
+} USBHSD_TypeDef;

+ 639 - 0
components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c

@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usb_ch58x_usbfs_reg.h"
+
+/**
+ * @brief   Related register macro
+ */
+#define USB0_BASE 0x40008000u
+#define USB1_BASE 0x40008400u
+
+#ifndef USBD
+#define USBD USB0_BASE
+#endif
+#define CH58x_USBFS_DEV ((USB_FS_TypeDef *)USBD)
+
+#ifndef USBD_IRQHandler
+#define USBD_IRQHandler USB_IRQHandler //use actual usb irq name instead
+#endif
+
+/*!< 8-bit value of endpoint control register */
+#define EPn_CTRL(epid) \
+    *(volatile uint8_t *)(&(CH58x_USBFS_DEV->UEP0_CTRL) + epid * 4 + (epid / 5) * 48)
+
+/*!< The length register value of the endpoint send buffer */
+#define EPn_TX_LEN(epid) \
+    *(volatile uint8_t *)(&(CH58x_USBFS_DEV->UEP0_T_LEN) + epid * 4 + (epid / 5) * 48)
+
+/*!< Read setup packet to use in ep0 in */
+#define GET_SETUP_PACKET(data_add) \
+    *(struct usb_setup_packet *)data_add
+
+/*!< Set epid ep tx valid // Not an isochronous endpoint  */
+#define EPn_SET_TX_VALID(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
+/*!< Set epid ep rx valid // Not an isochronous endpoint */
+#define EPn_SET_RX_VALID(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_ACK;
+/*!< Set epid ep tx valid // Isochronous endpoint */
+#define EPn_SET_TX_ISO_VALID(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_TOUT;
+/*!< Set epid ep rx valid // Isochronous endpoint */
+#define EPn_SET_RX_ISO_VALID(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_TOUT;
+/*!< Set epid ep tx nak */
+#define EPn_SET_TX_NAK(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
+/*!< Set epid ep rx nak */
+#define EPn_SET_RX_NAK(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_NAK;
+/*!< Set epid ep tx stall */
+#define EPn_SET_TX_STALL(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_STALL
+/*!< Set epid ep rx stall */
+#define EPn_SET_RX_STALL(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_STALL
+/*!< Clear epid ep tx stall */
+#define EPn_CLR_TX_STALL(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK
+/*!< Clear epid ep rx stall */
+#define EPn_CLR_RX_STALL(epid) \
+    EPn_CTRL(epid) = (EPn_CTRL(epid) & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK
+/*!< Set epid ep tx len */
+#define EPn_SET_TX_LEN(epid, len) \
+    EPn_TX_LEN(epid) = len
+/*!< Get epid ep rx len */
+#define EPn_GET_RX_LEN(epid) \
+    CH58x_USBFS_DEV->USB_RX_LEN
+
+/*!< ep nums */
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 5
+#endif
+/*!< ep mps */
+#define EP_MPS 64
+/*!< set ep4 in mps 64 */
+#define EP4_IN_MPS EP_MPS
+/*!< set ep4 out mps 64 */
+#define EP4_OUT_MPS EP_MPS
+
+/*!< User defined assignment endpoint RAM */
+__attribute__((aligned(4))) uint8_t ep0_data_buff[64 + EP4_OUT_MPS + EP4_IN_MPS]; /*!< ep0(64)+ep4_out(64)+ep4_in(64) */
+__attribute__((aligned(4))) uint8_t ep1_data_buff[64 + 64];                       /*!< ep1_out(64)+ep1_in(64) */
+__attribute__((aligned(4))) uint8_t ep2_data_buff[64 + 64];                       /*!< ep2_out(64)+ep2_in(64) */
+__attribute__((aligned(4))) uint8_t ep3_data_buff[64 + 64];                       /*!< ep3_out(64)+ep3_in(64) */
+#if (CONFIG_USBDEV_EP_NUM == 8)
+/**
+ * This dcd porting can be used on ch581, ch582, ch583,
+ * and also on ch571, ch572, and ch573. Note that only five endpoints are available for ch571, ch572, and ch573.
+ */
+__attribute__((aligned(4))) uint8_t ep5_data_buff[64 + 64]; /*!< ep5_out(64)+ep5_in(64) */
+__attribute__((aligned(4))) uint8_t ep6_data_buff[64 + 64]; /*!< ep6_out(64)+ep6_in(64) */
+__attribute__((aligned(4))) uint8_t ep7_data_buff[64 + 64]; /*!< ep7_out(64)+ep7_in(64) */
+#endif
+/**
+ * @brief   Endpoint information structure
+ */
+typedef struct _usbd_ep_info {
+    uint8_t mps;          /*!< Maximum packet length of endpoint */
+    uint8_t eptype;       /*!< Endpoint Type */
+    uint8_t *ep_ram_addr; /*!< Endpoint buffer address */
+
+    uint8_t ep_enable; /* Endpoint enable */
+    uint8_t *xfer_buf;
+    uint32_t xfer_len;
+    uint32_t actual_xfer_len;
+} usbd_ep_info;
+
+/*!< ch58x usb */
+static struct _ch58x_core_prvi {
+    uint8_t address; /*!< Address */
+    usbd_ep_info ep_in[CONFIG_USBDEV_EP_NUM];
+    usbd_ep_info ep_out[CONFIG_USBDEV_EP_NUM];
+    struct usb_setup_packet setup;
+} usb_dc_cfg;
+
+__WEAK void usb_dc_low_level_init(void)
+{
+}
+
+__WEAK void usb_dc_low_level_deinit(void)
+{
+}
+
+/**
+ * @brief            USB initialization
+ * @pre              None
+ * @param[in]        None
+ * @retval           >=0 success otherwise failure
+ */
+int usb_dc_init(uint8_t busid)
+{
+    usb_dc_cfg.ep_in[0].ep_ram_addr = ep0_data_buff;
+    usb_dc_cfg.ep_out[0].ep_ram_addr = ep0_data_buff;
+
+    usb_dc_cfg.ep_in[1].ep_ram_addr = ep1_data_buff + 64;
+    usb_dc_cfg.ep_out[1].ep_ram_addr = ep1_data_buff;
+
+    usb_dc_cfg.ep_in[2].ep_ram_addr = ep2_data_buff + 64;
+    usb_dc_cfg.ep_out[2].ep_ram_addr = ep2_data_buff;
+
+    usb_dc_cfg.ep_in[3].ep_ram_addr = ep3_data_buff + 64;
+    usb_dc_cfg.ep_out[3].ep_ram_addr = ep3_data_buff;
+
+    usb_dc_cfg.ep_in[4].ep_ram_addr = ep0_data_buff + 64 + EP4_OUT_MPS;
+    usb_dc_cfg.ep_out[4].ep_ram_addr = ep0_data_buff + 64;
+#if (CONFIG_USBDEV_EP_NUM == 8)
+    usb_dc_cfg.ep_in[5].ep_ram_addr = ep5_data_buff + 64;
+    usb_dc_cfg.ep_out[5].ep_ram_addr = ep5_data_buff;
+
+    usb_dc_cfg.ep_in[6].ep_ram_addr = ep6_data_buff + 64;
+    usb_dc_cfg.ep_out[6].ep_ram_addr = ep6_data_buff;
+
+    usb_dc_cfg.ep_in[7].ep_ram_addr = ep7_data_buff + 64;
+    usb_dc_cfg.ep_out[7].ep_ram_addr = ep7_data_buff;
+#endif
+    /*!< Set the mode first and cancel RB_UC_CLR_ALL */
+    CH58x_USBFS_DEV->USB_CTRL = 0x00;
+    CH58x_USBFS_DEV->UEP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | RB_UEP1_RX_EN | RB_UEP1_TX_EN; /*!< EP4 OUT+IN   EP1 OUT+IN */
+    CH58x_USBFS_DEV->UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | RB_UEP3_RX_EN | RB_UEP3_TX_EN; /*!< EP2 OUT+IN   EP3 OUT+IN */
+#if (CONFIG_USBDEV_EP_NUM == 8)
+    CH58x_USBFS_DEV->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | RB_UEP7_RX_EN | RB_UEP7_TX_EN; /*!< EP5 EP6 EP7   OUT+IN */
+#endif
+    CH58x_USBFS_DEV->UEP0_DMA = (uint16_t)(uint32_t)ep0_data_buff;
+    CH58x_USBFS_DEV->UEP1_DMA = (uint16_t)(uint32_t)ep1_data_buff;
+    CH58x_USBFS_DEV->UEP2_DMA = (uint16_t)(uint32_t)ep2_data_buff;
+    CH58x_USBFS_DEV->UEP3_DMA = (uint16_t)(uint32_t)ep3_data_buff;
+#if (CONFIG_USBDEV_EP_NUM == 8)
+    CH58x_USBFS_DEV->UEP5_DMA = (uint16_t)(uint32_t)ep5_data_buff;
+    CH58x_USBFS_DEV->UEP6_DMA = (uint16_t)(uint32_t)ep6_data_buff;
+    CH58x_USBFS_DEV->UEP7_DMA = (uint16_t)(uint32_t)ep7_data_buff;
+#endif
+    CH58x_USBFS_DEV->UEP0_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK;
+    CH58x_USBFS_DEV->UEP1_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+    CH58x_USBFS_DEV->UEP2_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+    CH58x_USBFS_DEV->UEP3_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+    CH58x_USBFS_DEV->UEP4_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK;
+#if (CONFIG_USBDEV_EP_NUM == 8)
+    CH58x_USBFS_DEV->UEP5_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+    CH58x_USBFS_DEV->UEP6_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+    CH58x_USBFS_DEV->UEP7_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
+#endif
+    CH58x_USBFS_DEV->USB_DEV_AD = 0x00;
+
+    /*!< Start the USB device and DMA, and automatically return to NAK before the interrupt flag is cleared during the interrupt */
+    CH58x_USBFS_DEV->USB_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN;
+    if ((uint32_t) & (CH58x_USBFS_DEV->USB_CTRL) == (uint32_t)USB0_BASE) {
+        /*!< USB0 */
+        R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB_DP_PU;
+    } else if ((uint32_t) & (CH58x_USBFS_DEV->USB_CTRL) == (uint32_t)USB1_BASE) {
+        /*!< USB1 */
+        R16_PIN_ANALOG_IE |= RB_PIN_USB2_IE | RB_PIN_USB2_DP_PU;
+    }
+
+    CH58x_USBFS_DEV->USB_INT_FG = 0xff;                        /*!< Clear interrupt flag */
+    CH58x_USBFS_DEV->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; /*!< Allow USB port */
+    CH58x_USBFS_DEV->USB_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER;
+
+    usb_dc_low_level_init();
+    return 0;
+}
+
+int usb_dc_deinit(uint8_t busid)
+{
+    return 0;
+}
+
+/**
+ * @brief            Set address
+ * @pre              None
+ * @param[in]        address :8-bit valid address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_set_address(uint8_t busid, const uint8_t address)
+{
+    if (address == 0) {
+        CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & 0x80) | address;
+    }
+    usb_dc_cfg.address = address;
+    return 0;
+}
+
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
+uint8_t usbd_get_port_speed(uint8_t busid)
+{
+    return USB_SPEED_FULL;
+}
+
+/**
+ * @brief            Open endpoint
+ * @pre              None
+ * @param[in]        ep_cfg : Endpoint configuration structure pointer
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
+{
+    /*!< ep id */
+    uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
+    if (epid > (CONFIG_USBDEV_EP_NUM - 1)) {
+        /**
+         * If you use ch58x, you can change the CONFIG_USBDEV_EP_NUM set to 8
+         */
+        USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
+        return -1;
+    }
+
+    /*!< ep max packet length */
+    uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+    /*!< update ep max packet length */
+    if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
+        /*!< in */
+        usb_dc_cfg.ep_in[epid].ep_enable = true;
+        usb_dc_cfg.ep_in[epid].mps = mps;
+        usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+    } else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
+        /*!< out */
+        usb_dc_cfg.ep_out[epid].ep_enable = true;
+        usb_dc_cfg.ep_out[epid].mps = mps;
+        usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+    }
+    return 0;
+}
+
+/**
+ * @brief            Close endpoint
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_close(uint8_t busid, const uint8_t ep)
+{
+    /*!< ep id */
+    uint8_t epid = USB_EP_GET_IDX(ep);
+    if (USB_EP_DIR_IS_IN(ep)) {
+        /*!< in */
+        usb_dc_cfg.ep_in[epid].ep_enable = false;
+    } else if (USB_EP_DIR_IS_OUT(ep)) {
+        /*!< out */
+        usb_dc_cfg.ep_out[epid].ep_enable = false;
+    }
+    return 0;
+}
+
+
+/**
+ * @brief            Endpoint setting stall
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
+{
+    /*!< ep id */
+    uint8_t epid = USB_EP_GET_IDX(ep);
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        EPn_SET_RX_STALL(epid);
+    } else {
+        EPn_SET_TX_STALL(epid);
+    }
+    return 0;
+}
+
+/**
+ * @brief            Endpoint clear stall
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t epid = USB_EP_GET_IDX(ep);
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        EPn_CLR_RX_STALL(epid);
+    } else {
+        EPn_CLR_TX_STALL(epid);
+    }
+    return 0;
+}
+
+/**
+ * @brief            Check endpoint status
+ * @pre              None
+ * @param[in]        ep : Endpoint address
+ * @param[out]       stalled : Outgoing endpoint status
+ * @retval           >=0 success otherwise failure
+ */
+int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
+{
+    if (USB_EP_DIR_IS_OUT(ep)) {
+    } else {
+    }
+    return 0;
+}
+
+/**
+ * @brief Setup in ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with tx dma.
+ *
+ * This function is called to write data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is transmitted
+ * out.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      Pointer to data to write
+ * @param[in]  data_len  Length of the data requested to write. This may
+ *                       be zero for a zero length status packet.
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
+        return -2;
+    }
+    if ((uint32_t)data & 0x03) {
+        return -3;
+    }
+
+    usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
+    usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
+    usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
+
+    if (data_len == 0) {
+        /*!< write 0 len data */
+        EPn_SET_TX_LEN(ep_idx, 0);
+        /*!< enable tx */
+        if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+            EPn_SET_TX_VALID(ep_idx);
+        } else {
+            EPn_SET_TX_ISO_VALID(ep_idx);
+        }
+        /*!< return */
+        return 0;
+    } else {
+        /*!< Not zlp */
+        data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
+        /*!< write buff */
+        memcpy(usb_dc_cfg.ep_in[ep_idx].ep_ram_addr, data, data_len);
+        /*!< write real_wt_nums len data */
+        EPn_SET_TX_LEN(ep_idx, data_len);
+        /*!< enable tx */
+        if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+            EPn_SET_TX_VALID(ep_idx);
+        } else {
+            EPn_SET_TX_ISO_VALID(ep_idx);
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief Setup out ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with rx dma.
+ *
+ * This function is called to read data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is received
+ * in.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      Pointer to data to read
+ * @param[in]  data_len  Max length of the data requested to read.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
+        return -2;
+    }
+    if ((uint32_t)data & 0x03) {
+        return -3;
+    }
+
+    usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
+    usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
+    usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
+
+    if (data_len == 0) {
+    } else {
+        data_len = MIN(data_len, usb_dc_cfg.ep_out[ep_idx].mps);
+    }
+
+    if (usb_dc_cfg.ep_out[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+        EPn_SET_RX_VALID(ep_idx);
+    } else {
+        EPn_SET_RX_ISO_VALID(ep_idx);
+    }
+    return 0;
+}
+
+/**
+ * @brief            USB interrupt processing function
+ * @pre              None
+ * @param[in]        None
+ * @retval           None
+ */
+__attribute__((interrupt("WCH-Interrupt-fast")))
+__attribute__((section(".highcode"))) void
+USBD_IRQHandler(void)
+{
+    volatile uint8_t intflag = 0;
+    intflag = CH58x_USBFS_DEV->USB_INT_FG;
+
+    if (intflag & RB_UIF_TRANSFER) {
+        if ((CH58x_USBFS_DEV->USB_INT_ST & MASK_UIS_TOKEN) != MASK_UIS_TOKEN) {
+            uint8_t epid = ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0x0f);
+            switch ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0xf0) {
+                case UIS_TOKEN_IN:
+                    if (epid == 0) {
+                        /**
+                         * IN  The host takes away the data that has been stored in FIFO
+                         */
+                        switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
+                            case 1:
+                                /*!< Get */
+                                CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_T_TOG;
+                                /**
+                                 * Here is to take away the last data, and the IN interrupt will be triggered only after it is successfully taken away.
+                                 * Therefore, the status of the in endpoint is set to NAK here. If there is data transmission,
+                                 * the endpoint status will be set to ack again in the in handler of EP0.
+                                 */
+                                EPn_SET_TX_NAK(0);
+
+                                /*!< IN */
+                                if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
+                                    usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
+                                    usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
+                                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
+                                } else {
+                                    usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
+                                    usb_dc_cfg.ep_in[0].xfer_len = 0;
+                                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
+                                }
+                                break;
+                            case 0:
+                                /*!< Set */
+                                switch (usb_dc_cfg.setup.bRequest) {
+                                    case USB_REQUEST_SET_ADDRESS:
+                                        /*!< Fill in the equipment address */
+                                        CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & RB_UDA_GP_BIT) | usb_dc_cfg.address;
+                                        /**
+                                         * In the state phase after setting the address, the host has sent an in token packet of data1 to take the packet of 0 length,
+                                         * Ch58x USB IP needs to manually set the status of the in endpoint to NAK
+                                         */
+                                        EPn_SET_TX_NAK(0);
+                                        EPn_SET_RX_VALID(0);
+                                        break;
+                                    default:
+                                        /*!< Normal out state phase */
+                                        /**
+                                         * The host has sent an in token packet of data1 and taken the packet of 0 length.
+                                         * Here, you only need to set the status of the in endpoint to NAK and out endpoint ACK
+                                         */
+                                        EPn_SET_TX_NAK(0);
+                                        EPn_SET_RX_VALID(0);
+                                        break;
+                                }
+                                break;
+                        }
+                    } else {
+                        if (epid == 4) {
+                            CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_T_TOG;
+                        }
+                        EPn_SET_TX_NAK(epid);
+                        if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
+                            /*!< Need start in again */
+                            usb_dc_cfg.ep_in[epid].xfer_buf += usb_dc_cfg.ep_in[epid].mps;
+                            usb_dc_cfg.ep_in[epid].xfer_len -= usb_dc_cfg.ep_in[epid].mps;
+                            usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].mps;
+                            if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
+                                memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].mps);
+                                EPn_SET_TX_LEN(epid, usb_dc_cfg.ep_in[epid].mps);
+                            } else {
+                                memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].xfer_len);
+                                EPn_SET_TX_LEN(epid, usb_dc_cfg.ep_in[epid].xfer_len);
+                            }
+                            if (usb_dc_cfg.ep_in[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+                                EPn_SET_TX_VALID(epid);
+                            } else {
+                                EPn_SET_TX_ISO_VALID(epid);
+                            }
+                        } else {
+                            usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
+                            usb_dc_cfg.ep_in[epid].xfer_len = 0;
+                            usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
+                        }
+                    }
+                    break;
+                case UIS_TOKEN_OUT:
+                    EPn_SET_RX_NAK(epid);
+
+                    if (epid == 0) {
+                        /*!< ep0 out */
+                        CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_R_TOG;
+                        uint32_t read_count = EPn_GET_RX_LEN(0);
+                        memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
+
+                        usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
+                        usb_dc_cfg.ep_out[0].xfer_len -= read_count;
+                        usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
+                        if (read_count == 0) {
+                            /*!< Out status, start reading setup */
+                            EPn_SET_RX_VALID(0);
+                        }
+                    } else {
+                        if ((CH58x_USBFS_DEV->USB_INT_ST) & RB_UIS_TOG_OK) {
+                            if (epid == 4) {
+                                CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_R_TOG;
+                            }
+                            uint32_t read_count = EPn_GET_RX_LEN(epid);
+                            memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
+                            usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
+                            usb_dc_cfg.ep_out[epid].actual_xfer_len += read_count;
+                            usb_dc_cfg.ep_out[epid].xfer_len -= read_count;
+
+                            if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
+                                usbd_event_ep_out_complete_handler(0, ((epid)&0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
+                            } else {
+                                if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+                                    EPn_SET_RX_VALID(epid);
+                                } else {
+                                    EPn_SET_RX_ISO_VALID(epid);
+                                }
+                            }
+                        }
+                    }
+                    break;
+                default:
+                    break;
+            }
+            CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
+        }
+
+        if (CH58x_USBFS_DEV->USB_INT_ST & RB_UIS_SETUP_ACT) {
+            /*!< Setup */
+            /**
+             * Setup the device must respond with ACK, and the next data phase is DATA1
+             * If it is sent, the data1 packet will be sent.
+             * If it is received, the data1 packet is expected to be received.
+             * If it is in, the host will send the data1 out packet to complete the status phase after the in completes.
+             * If it is out, the host will send the data1 in packet to complete the status phase after the out completes.
+             */
+            CH58x_USBFS_DEV->UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_T_RES_NAK;
+            /*!< get setup packet */
+            usb_dc_cfg.setup = GET_SETUP_PACKET(usb_dc_cfg.ep_out[0].ep_ram_addr);
+            if (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT == 0) {
+                /**
+                 * Ep0 The next in must be the status stage.
+                 * The device must reply to the host data 0 length packet.
+                 * Here, set the transmission length to 0 and the transmission status to ACK,
+                 * and wait for the host to send the in token to retrieve
+                 */
+                EPn_SET_TX_LEN(0, 0);
+                EPn_SET_TX_VALID(0);
+            }
+            EPn_SET_RX_NAK(0);
+            usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&(usb_dc_cfg.setup));
+            CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
+        }
+    } else if (intflag & RB_UIF_BUS_RST) {
+        /*!< Reset */
+        CH58x_USBFS_DEV->USB_DEV_AD = 0;
+        usbd_event_reset_handler(0);
+        /*!< Set ep0 rx vaild to start receive setup packet */
+        EPn_SET_RX_VALID(0);
+        CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_BUS_RST;
+    } else if (intflag & RB_UIF_SUSPEND) {
+        if (CH58x_USBFS_DEV->USB_MIS_ST & RB_UMS_SUSPEND) {
+            /*!< Suspend */
+        } else {
+            /*!< Wake up */
+        }
+        CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_SUSPEND;
+    } else {
+        CH58x_USBFS_DEV->USB_INT_FG = intflag;
+    }
+}

+ 249 - 0
components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h

@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#define __IO volatile
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RB_UC_HOST_MODE  0x80 // enable USB host mode: 0=device mode, 1=host mode
+#define RB_UC_LOW_SPEED  0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps
+#define RB_UC_DEV_PU_EN  0x20 // USB device enable and internal pullup resistance enable
+#define RB_UC_SYS_CTRL1  0x20 // USB system control high bit
+#define RB_UC_SYS_CTRL0  0x10 // USB system control low bit
+#define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control
+#define RB_UC_INT_BUSY   0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid
+#define RB_UC_RESET_SIE  0x04 // force reset USB SIE, need software clear
+#define RB_UC_CLR_ALL    0x02 // force clear FIFO and count of USB
+#define RB_UC_DMA_EN     0x01 // DMA enable and DMA interrupt enable for USB
+
+#define RB_UD_PD_DIS    0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
+#define RB_UD_DP_PIN    0x20 // ReadOnly: indicate current UDP pin level
+#define RB_UD_DM_PIN    0x10 // ReadOnly: indicate current UDM pin level
+#define RB_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
+#define RB_UD_GP_BIT    0x02 // general purpose bit
+#define RB_UD_PORT_EN   0x01 // enable USB physical port I/O: 0=disable, 1=enable
+
+#define RB_UH_PD_DIS    0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
+#define RB_UH_DP_PIN    0x20 // ReadOnly: indicate current UDP pin level
+#define RB_UH_DM_PIN    0x10 // ReadOnly: indicate current UDM pin level
+#define RB_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
+#define RB_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
+#define RB_UH_PORT_EN   0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
+
+#define RB_UIE_DEV_SOF  0x80 // enable interrupt for SOF received for USB device mode
+#define RB_UIE_DEV_NAK  0x40 // enable interrupt for NAK responded for USB device mode
+#define RB_UIE_FIFO_OV  0x10 // enable interrupt for FIFO overflow
+#define RB_UIE_HST_SOF  0x08 // enable interrupt for host SOF timer action for USB host mode
+#define RB_UIE_SUSPEND  0x04 // enable interrupt for USB suspend or resume event
+#define RB_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
+#define RB_UIE_DETECT   0x01 // enable interrupt for USB device detected event for USB host mode
+#define RB_UIE_BUS_RST  0x01 // enable interrupt for USB bus reset event for USB device mode
+
+#define RB_UDA_GP_BIT 0x80 // general purpose bit
+#define MASK_USB_ADDR 0x7F // bit mask for USB device address
+
+#define RB_UMS_SOF_PRES   0x80 // RO, indicate host SOF timer presage status
+#define RB_UMS_SOF_ACT    0x40 // RO, indicate host SOF timer action status for USB host
+#define RB_UMS_SIE_FREE   0x20 // RO, indicate USB SIE free status
+#define RB_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty)
+#define RB_UMS_BUS_RESET  0x08 // RO, indicate USB bus reset status
+#define RB_UMS_SUSPEND    0x04 // RO, indicate USB suspend status
+#define RB_UMS_DM_LEVEL   0x02 // RO, indicate UDM level saved at device attached to USB host
+#define RB_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host
+
+#define RB_U_IS_NAK     0x80 // RO, indicate current USB transfer is NAK received
+#define RB_U_TOG_OK     0x40 // RO, indicate current USB transfer toggle is OK
+#define RB_U_SIE_FREE   0x20 // RO, indicate USB SIE free status
+#define RB_UIF_FIFO_OV  0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
+#define RB_UIF_HST_SOF  0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
+#define RB_UIF_SUSPEND  0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
+#define RB_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
+#define RB_UIF_DETECT   0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
+#define RB_UIF_BUS_RST  0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
+
+#define RB_UIS_SETUP_ACT 0x80 // RO, indicate SETUP token & 8 bytes setup request received for USB device mode
+#define RB_UIS_TOG_OK    0x40 // RO, indicate current USB transfer toggle is OK
+#define RB_UIS_TOKEN1    0x20 // RO, current token PID code bit 1 received for USB device mode
+#define RB_UIS_TOKEN0    0x10 // RO, current token PID code bit 0 received for USB device mode
+#define MASK_UIS_TOKEN   0x30 // RO, bit mask of current token PID code received for USB device mode
+#define UIS_TOKEN_OUT    0x00
+#define UIS_TOKEN_SOF    0x10
+#define UIS_TOKEN_IN     0x20
+#define UIS_TOKEN_SETUP  0x30
+
+#define MASK_UIS_ENDP  0x0F // RO, bit mask of current transfer endpoint number for USB device mode
+#define MASK_UIS_H_RES 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
+
+#define R8_USB_RX_LEN   (*((uint8_t *)0x40008008)) // USB receiving length
+#define RB_UEP1_RX_EN   0x80                       // enable USB endpoint 1 receiving (OUT)
+#define RB_UEP1_TX_EN   0x40                       // enable USB endpoint 1 transmittal (IN)
+#define RB_UEP1_BUF_MOD 0x10                       // buffer mode of USB endpoint 1
+
+#define RB_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
+#define RB_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
+
+#define RB_UEP3_RX_EN   0x80 // enable USB endpoint 3 receiving (OUT)
+#define RB_UEP3_TX_EN   0x40 // enable USB endpoint 3 transmittal (IN)
+#define RB_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
+#define RB_UEP2_RX_EN   0x08 // enable USB endpoint 2 receiving (OUT)
+#define RB_UEP2_TX_EN   0x04 // enable USB endpoint 2 transmittal (IN)
+#define RB_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
+
+#define RB_UEP7_RX_EN 0x20 // enable USB endpoint 7 receiving (OUT)
+#define RB_UEP7_TX_EN 0x10 // enable USB endpoint 7 transmittal (IN)
+#define RB_UEP6_RX_EN 0x08 // enable USB endpoint 6 receiving (OUT)
+#define RB_UEP6_TX_EN 0x04 // enable USB endpoint 6 transmittal (IN)
+#define RB_UEP5_RX_EN 0x02 // enable USB endpoint 5 receiving (OUT)
+#define RB_UEP5_TX_EN 0x01 // enable USB endpoint 5 transmittal (IN)
+
+#define RB_UH_EP_TX_EN    0x40 // enable USB host OUT endpoint transmittal
+#define RB_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
+
+#define RB_UH_EP_RX_EN    0x08 // enable USB host IN endpoint receiving
+#define RB_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
+
+#define RB_UEP_R_TOG    0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
+#define RB_UEP_T_TOG    0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
+#define RB_UEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
+#define RB_UEP_R_RES1   0x08 // handshake response type high bit for USB endpoint X receiving (OUT)
+#define RB_UEP_R_RES0   0x04 // handshake response type low bit for USB endpoint X receiving (OUT)
+#define MASK_UEP_R_RES  0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT)
+#define UEP_R_RES_ACK   0x00
+#define UEP_R_RES_TOUT  0x04
+#define UEP_R_RES_NAK   0x08
+#define UEP_R_RES_STALL 0x0C
+
+#define RB_UEP_T_RES1   0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
+#define RB_UEP_T_RES0   0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
+#define MASK_UEP_T_RES  0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
+#define UEP_T_RES_ACK   0x00
+#define UEP_T_RES_TOUT  0x01
+#define UEP_T_RES_NAK   0x02
+#define UEP_T_RES_STALL 0x03
+
+#define RB_UH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
+#define RB_UH_SOF_EN     0x40 // USB host automatic SOF enable
+
+#define R8_UH_EP_PID  R8_UEP2_T_LEN // host endpoint and PID
+#define MASK_UH_TOKEN 0xF0          // bit mask of token PID for USB host transfer
+#define MASK_UH_ENDP  0x0F          // bit mask of endpoint number for USB host transfer
+
+#define R8_UH_RX_CTRL    R8_UEP2_CTRL // host receiver endpoint control
+#define RB_UH_R_TOG      0x80         // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
+#define RB_UH_R_AUTO_TOG 0x10         // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
+#define RB_UH_R_RES      0x04         // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
+
+#define R8_UH_TX_LEN R8_UEP3_T_LEN // host transmittal endpoint transmittal length
+
+#define RB_UH_T_TOG      0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
+#define RB_UH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
+#define RB_UH_T_RES      0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
+
+#define R16_PIN_ANALOG_IE (*((uint16_t *)0x4000101A)) // RW, analog pin enable and digital input disable
+#define RB_PIN_USB_IE     0x80                        // RW, USB analog I/O enable: 0=analog I/O disable, 1=analog I/O enable
+#define RB_PIN_USB_DP_PU  0x40                        // RW, USB UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode
+#define RB_PIN_USB2_IE    0x20                        // RW, USB2 analog I/O enable: 0=analog I/O disable, 1=analog I/O enable
+#define RB_PIN_USB2_DP_PU 0x10                        // RW, USB2 UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode
+/*!< USB Regs */
+typedef struct
+{
+    __IO uint8_t USB_CTRL; /*!< 0x40008000 */
+    union {
+        __IO uint8_t UDEV_CTRL;  /*!< 0x40008001 */
+        __IO uint8_t UHOST_CTRL; /*!< 0x40008001 */
+    };
+    __IO uint8_t USB_INT_EN;  /*!< 0x40008002 */
+    __IO uint8_t USB_DEV_AD;  /*!< 0x40008003 */
+    __IO uint8_t USB_STATUS0; /*!< 0x40008004 */
+    __IO uint8_t USB_MIS_ST;  /*!< 0x40008005 */
+    __IO uint8_t USB_INT_FG;  /*!< 0x40008006 */
+    __IO uint8_t USB_INT_ST;  /*!< 0x40008007 */
+    __IO uint8_t USB_RX_LEN;  /*!< 0x40008008 */
+    __IO uint8_t Reserve1;    /*!< 0x40008009 */
+    __IO uint8_t Reserve2;    /*!< 0x4000800a */
+    __IO uint8_t Reserve3;    /*!< 0x4000800b */
+    __IO uint8_t UEP4_1_MOD;  /*!< 0x4000800c */
+    union {
+        __IO uint8_t UEP2_3_MOD; /*!< 0x4000800d */
+        __IO uint8_t UH_EP_MOD;  /*!< 0x4000800d */
+    };
+    __IO uint8_t UEP567_MOD; /*!< 0x4000800e */
+    __IO uint8_t Reserve4;   /*!< 0x4000800f */
+    __IO uint16_t UEP0_DMA;  /*!< 0x40008010 */
+    __IO uint16_t Reserve5;  /*!< 0x40008012 */
+    __IO uint16_t UEP1_DMA;  /*!< 0x40008014 */
+    __IO uint16_t Reserve6;  /*!< 0x40008016 */
+    union {
+        __IO uint16_t UEP2_DMA;  /*!< 0x40008018 */
+        __IO uint16_t UH_RX_DMA; /*!< 0x40008018 */
+    };
+    __IO uint16_t Reserve7; /*!< 0x4000801a */
+    union {
+        __IO uint16_t UEP3_DMA;  /*!< 0x4000801c */
+        __IO uint16_t UH_TX_DMA; /*!< 0x4000801c */
+    };
+    __IO uint16_t Reserve8;  /*!< 0x4000801e */
+    __IO uint8_t UEP0_T_LEN; /*!< 0x40008020 */
+    __IO uint8_t Reserve9;   /*!< 0x40008021 */
+    __IO uint8_t UEP0_CTRL;  /*!< 0x40008022 */
+    __IO uint8_t Reserve10;  /*!< 0x40008023 */
+    __IO uint8_t UEP1_T_LEN; /*!< 0x40008024 */
+    __IO uint8_t Reserve11;  /*!< 0x40008025 */
+    union {
+        __IO uint8_t UEP1_CTRL; /*!< 0x40008026 */
+        __IO uint8_t UH_SETUP;  /*!< 0x40008026 */
+    };
+    __IO uint8_t Reserve12; /*!< 0x40008027 */
+    union {
+        __IO uint8_t UEP2_T_LEN; /*!< 0x40008028 */
+        __IO uint8_t UH_EP_PID;  /*!< 0x40008028 */
+    };
+    __IO uint8_t Reserve13; /*!< 0x40008029 */
+    union {
+        __IO uint8_t UEP2_CTRL;  /*!< 0x4000802a */
+        __IO uint8_t UH_RX_CTRL; /*!< 0x4000802a */
+    };
+    __IO uint8_t Reserve14; /*!< 0x4000802b */
+    union {
+        __IO uint8_t UEP3_T_LEN; /*!< 0x4000802c */
+        __IO uint8_t UH_TX_LEN;  /*!< 0x4000802c */
+    };
+    __IO uint8_t Reserve15; /*!< 0x4000802d */
+    union {
+        __IO uint8_t UEP3_CTRL;  /*!< 0x4000802e */
+        __IO uint8_t UH_TX_CTRL; /*!< 0x4000802e */
+    };
+    __IO uint8_t Reserve16;     /*!< 0x4000802f */
+    __IO uint8_t UEP4_T_LEN;    /*!< 0x40008030 */
+    __IO uint8_t Reserve17;     /*!< 0x40008031 */
+    __IO uint8_t UEP4_CTRL;     /*!< 0x40008032 */
+    __IO uint8_t Reserve18[33]; /*!< 0x40008033 */
+    __IO uint16_t UEP5_DMA;     /*!< 0x40008054 */
+    __IO uint16_t Reserve19;    /*!< 0x40008056 */
+    __IO uint16_t UEP6_DMA;     /*!< 0x40008058 */
+    __IO uint16_t Reserve20;    /*!< 0x4000805a */
+    __IO uint16_t UEP7_DMA;     /*!< 0x4000805c */
+    __IO uint8_t Reserve21[6];  /*!< 0x4000805e */
+    __IO uint8_t UEP5_T_LEN;    /*!< 0x40008064 */
+    __IO uint8_t Reserve22;     /*!< 0x40008065 */
+    __IO uint8_t UEP5_CTRL;     /*!< 0x40008066 */
+    __IO uint8_t Reserve23;     /*!< 0x40008067 */
+    __IO uint8_t UEP6_T_LEN;    /*!< 0x40008068 */
+    __IO uint8_t Reserve24;     /*!< 0x40008069 */
+    __IO uint8_t UEP6_CTRL;     /*!< 0x4000806a */
+    __IO uint8_t Reserve25;     /*!< 0x4000806b */
+    __IO uint8_t UEP7_T_LEN;    /*!< 0x4000806c */
+    __IO uint8_t Reserve26;     /*!< 0x4000806d */
+    __IO uint8_t UEP7_CTRL;     /*!< 0x4000806e */
+} USB_FS_TypeDef;
+
+#ifdef __cplusplus
+}
+#endif

+ 2 - 2
components/drivers/usb/cherryusb/port/dwc2/README.md

@@ -27,7 +27,7 @@ CONFIG_USBDEV_EP_NUM 必须为4 或者 6,并删除 usb_dc_dwc2.c 中 while(1){
 
 - GD32F30X_CL
 - GD32F405、GD32F407
-- GD32F450
+- GD32F350、GD32F450
 
 ## HC32
 
@@ -35,7 +35,7 @@ CONFIG_USBDEV_EP_NUM 必须为4 或者 6,并删除 usb_dc_dwc2.c 中 while(1){
 
 ## Espressif
 
-- ESP32S2、ESP32S3
+- ESP32S2、ESP32S3、ESP32P4
 
 ## Sophgo
 

+ 1 - 0
components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c

@@ -9,6 +9,7 @@
 #include "esp_private/usb_phy.h"
 #include "soc/periph_defs.h"
 #include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
 #include "usbd_core.h"
 #include "usbh_core.h"
 

+ 0 - 2
components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c

@@ -194,8 +194,6 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
     USB_OTG_GLB->GCCFG = (1 << 23);
     usb_hsphy_init(25000000U);
     return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/
-#elif __has_include("stm32h7rsxx.h")
-    return (1 << 21);
 #else
     return 0;
 #endif

+ 31 - 7
components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c

@@ -41,6 +41,7 @@ struct dwc2_chan {
     uint32_t xferlen;
     uint8_t chidx;
     bool inuse;
+    bool dir_in;
     usb_osal_sem_t waitsem;
     struct usbh_urb *urb;
     uint32_t iso_frame_idx;
@@ -256,16 +257,26 @@ static void dwc2_chan_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr
 }
 
 /* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/
-static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
+static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint8_t ep_addr, uint8_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
 {
     __IO uint32_t tmpreg;
     uint8_t is_oddframe;
+    struct dwc2_chan *chan;
+
+    chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[ch_num];
 
     /* Initialize the HCTSIZn register */
     USB_OTG_HC(ch_num)->HCTSIZ = (size & USB_OTG_HCTSIZ_XFRSIZ) |
                                  (((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
                                  (((uint32_t)pid << 29) & USB_OTG_HCTSIZ_DPID);
 
+    if (!(ep_addr & 0x80)) {
+        chan->dir_in = false;
+        usb_dcache_clean((uintptr_t)buf, USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE));
+    } else {
+        chan->dir_in = true;
+    }
+
     /* xfer_buff MUST be 32-bits aligned */
     USB_OTG_HC(ch_num)->HCDMA = (uint32_t)buf;
 
@@ -400,17 +411,17 @@ static void dwc2_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct us
     {
         chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
         dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
-        dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
+        dwc2_chan_transfer(bus, chidx, 0x00, (uint8_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
     } else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */
     {
         chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
         dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
-        dwc2_chan_transfer(bus, chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
+        dwc2_chan_transfer(bus, chidx, 0x80, buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
     } else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */
     {
         chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
         dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
-        dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
+        dwc2_chan_transfer(bus, chidx, 0x00, buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
     } else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */
     {
         chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
@@ -432,9 +443,10 @@ static void dwc2_bulk_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct
 
     chan->num_packets = dwc2_calculate_packet_num(buflen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
     dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
-    dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle == 0 ? HC_PID_DATA0 : HC_PID_DATA1);
+    dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, buffer, chan->xferlen, chan->num_packets, urb->data_toggle == 0 ? HC_PID_DATA0 : HC_PID_DATA1);
 }
 
+#if 0
 static void dwc2_iso_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet)
 {
     struct dwc2_chan *chan;
@@ -443,8 +455,9 @@ static void dwc2_iso_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_u
 
     chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
     dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
-    dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
+    dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
 }
+#endif
 
 __WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
 {
@@ -754,6 +767,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
         return -USB_ERR_INVAL;
     }
 
+#ifdef CONFIG_USB_DCACHE_ENABLE
+    if (((uintptr_t)urb->setup % CONFIG_USB_ALIGN_SIZE) || ((uintptr_t)urb->transfer_buffer % CONFIG_USB_ALIGN_SIZE)) {
+        USB_LOG_ERR("urb buffer is not align with %d\r\n", CONFIG_USB_ALIGN_SIZE);
+        while (1) {
+        }
+    }
+#endif
     bus = urb->hport->bus;
 
     if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !urb->hport->connected) {
@@ -907,7 +927,7 @@ static void dwc2_inchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
             urb->errorcode = 0;
 
             uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);                        /* how many size has received */
-            uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
+            //uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
 
             urb->actual_length += count;
 
@@ -919,6 +939,10 @@ static void dwc2_inchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
                 urb->data_toggle = 1;
             }
 
+            if (chan->dir_in) {
+                usb_dcache_invalidate((uintptr_t)urb->transfer_buffer, USB_ALIGN_UP(count, CONFIG_USB_ALIGN_SIZE));
+            }
+
             if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
                 if (chan->ep0_state == DWC2_EP0_STATE_INDATA) {
                     chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS;

+ 1 - 1
components/drivers/usb/cherryusb/port/ehci/README.md

@@ -12,7 +12,7 @@
 
 ### AllwinnerTech
 
-- F133
+- F133/T113
 
 ### Nuvoton
 

+ 219 - 0
components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c

@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2025, YC113
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usb_hc_ehci.h"
+#include "usb_hc_ohci.h"
+
+#include "interrupt.h"
+#include "drv_reg_base.h"
+#include "drv_clock.h"
+
+#if !defined(CONFIG_USB_EHCI_WITH_OHCI)
+#error "t113 must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device"
+#endif
+
+#if CONFIG_USBHOST_MAX_BUS != 2
+#error "t113 has 2 usb host controller"
+#endif
+
+#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400
+#error "t113 CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400"
+#endif
+
+#if defined(CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE)
+#error "t113 usb ehci register need reserved"
+#endif
+
+#if !defined(CONFIG_USB_EHCI_CONFIGFLAG)
+#error "t113 usb ehci has configflag register"
+#endif
+
+#if defined(CONFIG_USB_EHCI_ISO)
+#error "t113 usb ehci no iso register"
+#endif
+
+void usb_select_phyTohci(void)
+{
+    *(volatile rt_uint32_t *)(USB0_OTG_BASE_ADDR + 0x420) &= ~(1 << 0);
+}
+
+void usb_gate_open(rt_uint8_t busid)
+{
+    rt_uint32_t addr;
+
+    /* otg bus reset and gate open */
+    if (busid == 0)
+        usb_select_phyTohci();
+
+    /* reset phy */
+    addr = (rt_uint32_t)&CCU->usb0_clk + busid * 4;
+    *(volatile rt_uint32_t *)addr &= ~(1 << 30);
+    sdelay(10);
+    *(volatile rt_uint32_t *)addr |= 1 << 30;
+    sdelay(10);
+
+    /* ehci bus reset */
+    CCU->usb_bgr &= ~((1 << 20) << busid);
+    sdelay(10);
+    CCU->usb_bgr |= (1 << 20) << busid;
+    sdelay(10);
+
+    /* ehci gate open */
+    CCU->usb_bgr |= (1 << 4) << busid;
+
+    /* ohci bus reset */
+    CCU->usb_bgr &= ~((1 << 16) << busid);
+    sdelay(10);
+    CCU->usb_bgr |= (1 << 16) << busid;
+    sdelay(10);
+
+    /* ohci gate open */
+    CCU->usb_bgr |= 1 << busid;
+
+    sdelay(10);
+
+    /* clock enable */
+    *(volatile rt_uint32_t *)addr &= ~(3 << 24);
+    *(volatile rt_uint32_t *)addr |= (1 << 31) | (1 << 24);
+
+    USB_LOG_DBG("usb%d gate : %X, clock : %X\n", busid, CCU->usb_bgr, *(volatile rt_uint32_t *)addr);
+}
+
+void usb_clean_siddp(struct usbh_bus *bus)
+{
+    *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810) &= ~(1 << 3);
+}
+
+static void usb_new_phyx_tp_write(struct usbh_bus *bus, int addr, int data, int len)
+{
+    rt_uint32_t base = bus->hcd.reg_base;
+
+    for (int i = 0; i < len; i++) {
+        *(volatile rt_uint8_t *)(base + 0x810) |= 1 << 1;
+
+        *(volatile rt_uint8_t *)(base + 0x810 + 1) = addr + i;
+
+        *(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 0);
+
+        *(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 7);
+        *(volatile rt_uint8_t *)(base + 0x810) |= (data & 0x1) << 7;
+
+        *(volatile rt_uint8_t *)(base + 0x810) |= 1 << 0;
+
+        *(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 0);
+
+        *(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 1);
+
+        data >>= 1;
+    }
+}
+
+void usb_new_phy_init(struct usbh_bus *bus)
+{
+    rt_int32_t value = 0;
+    rt_uint32_t efuse_val = 0x1E5080F;
+
+    usb_new_phyx_tp_write(bus, 0x1C, 0x0, 0x03);
+
+    /* vref mode */
+    usb_new_phyx_tp_write(bus, 0x60, 0x0, 0x01);
+
+    value = (efuse_val & 0x3C0000) >> 18;
+    usb_new_phyx_tp_write(bus, 0x44, value, 0x04);
+
+    value = (efuse_val & 0x1C00000) >> 22;
+    usb_new_phyx_tp_write(bus, 0x36, value, 0x03);
+}
+
+void usb_hci_set_passby(struct usbh_bus *bus)
+{
+    /* AHB Master interface INCR16 enable */
+    /* AHB Master interface INCR8 enable */
+    /* AHB Master interface burst type INCR4 enable */
+    /* AHB Master interface INCRX align enable */
+    /* ULPI bypass enable */
+    *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x800) |= (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 0);
+}
+
+void t113_ehci_isr(int vector, void *arg)
+{
+    struct usbh_bus *bus = (struct usbh_bus *)arg;
+
+    USB_LOG_DBG("t113_ehci_isr");
+
+    extern void USBH_IRQHandler(uint8_t busid);
+    USBH_IRQHandler(bus->hcd.hcd_id);
+}
+
+void t113_ohci_isr(int vector, void *arg)
+{
+    struct usbh_bus *bus = (struct usbh_bus *)arg;
+
+    USB_LOG_DBG("t113_ohci_isr");
+
+    extern void OHCI_IRQHandler(uint8_t busid);
+    OHCI_IRQHandler(bus->hcd.hcd_id);
+}
+
+void usb_hc_low_level_init(struct usbh_bus *bus)
+{
+    int vector;
+    RT_ASSERT(bus->busid <= 1);
+
+    usb_gate_open(bus->busid);
+    usb_clean_siddp(bus);
+    usb_hci_set_passby(bus);
+
+    /* register EHCI interrupt callback */
+    vector = T113_IRQ_USB0_EHCI + (bus->busid > 0 ? 3 : 0);
+    rt_hw_interrupt_install(vector, t113_ehci_isr, bus, RT_NULL);
+    rt_hw_interrupt_umask(vector);
+
+    /* register OHCI interrupt callback */
+    rt_hw_interrupt_install(vector + 1, t113_ohci_isr, bus, RT_NULL);
+    rt_hw_interrupt_umask(vector + 1);
+
+    USB_LOG_DBG("usb%d vector : %d, phy : %X\n", bus->busid, vector, *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810));
+    USB_LOG_DBG("usb%d hc low level init success\n", bus->busid);
+}
+
+uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
+{
+    /* Defined by individual manufacturers */
+    uint32_t regval;
+
+    regval = EHCI_HCOR->portsc[port - 1];
+    if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE)
+        return USB_SPEED_LOW;
+
+    if (regval & EHCI_PORTSC_PE)
+        return USB_SPEED_HIGH;
+    else
+        return USB_SPEED_FULL;
+}
+
+int __usbh_init(void)
+{
+#ifdef T113_USING_USB0_HOST
+    /* USB0 MSC test OK */
+    usbh_initialize(0, USB0_BASE_ADDR);
+#endif
+
+#ifdef T113_USING_USB1_HOST
+    /* USB1 MSC test OK */
+    usbh_initialize(1, USB1_BASE_ADDR);
+#endif
+    return 0;
+}
+
+#ifdef PKG_CHERRYUSB_HOST
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+INIT_ENV_EXPORT(__usbh_init);
+
+#endif

+ 45 - 1
components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c

@@ -76,10 +76,36 @@ static void ehci_qh_free(struct usbh_bus *bus, struct ehci_qh_hw *qh)
     }
 }
 
+#ifdef CONFIG_USB_DCACHE_ENABLE
+static inline void usb_ehci_qh_qtd_flush(struct ehci_qh_hw *qh)
+{
+    struct ehci_qtd_hw *qtd;
+
+    qtd = EHCI_ADDR2QTD(qh->first_qtd);
+
+    while (qtd) {
+        usb_dcache_clean((uintptr_t)&qtd->hw, USB_ALIGN_UP(SIZEOF_EHCI_QTD, CONFIG_USB_EHCI_ALIGN_SIZE));
+
+        if (!qtd->dir_in) {
+            usb_dcache_clean(qtd->bufaddr, USB_ALIGN_UP(qtd->length, CONFIG_USB_ALIGN_SIZE));
+        }
+        qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
+    }
+
+    usb_dcache_clean((uintptr_t)&qh->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
+}
+#else
+#define usb_ehci_qh_qtd_flush(qh)
+#endif
+
 static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
 {
     n->hw.hlp = head->hw.hlp;
+    usb_ehci_qh_qtd_flush(n);
+
     head->hw.hlp = QH_HLP_QH(n);
+
+    usb_dcache_clean((uintptr_t)&head->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
 }
 
 static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
@@ -92,6 +118,7 @@ static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
 
     if (tmp) {
         tmp->hw.hlp = n->hw.hlp;
+        usb_dcache_clean((uintptr_t)&tmp->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
     }
 }
 
@@ -254,7 +281,9 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl
 
     qtd->hw.token = token;
 
-    ehci_qtd_bpl_fill(qtd, bufaddr, buflen);
+    ehci_qtd_bpl_fill(qtd, usb_phyaddr2ramaddr(bufaddr), buflen);
+    qtd->dir_in = ((token & QTD_TOKEN_PID_MASK) == QTD_TOKEN_PID_IN) ? true : false;
+    qtd->bufaddr = bufaddr;
     qtd->length = buflen;
 }
 
@@ -591,6 +620,9 @@ static void ehci_qh_scan_qtds(struct usbh_bus *bus, struct ehci_qh_hw *qhead, st
     qtd = EHCI_ADDR2QTD(qh->first_qtd);
 
     while (qtd) {
+        if (qtd->dir_in) {
+            usb_dcache_invalidate(qtd->bufaddr, USB_ALIGN_UP(qtd->length - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT), CONFIG_USB_ALIGN_SIZE));
+        }
         qtd->urb->actual_length += (qtd->length - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
 
         qh->first_qtd = qtd->hw.next_qtd;
@@ -611,6 +643,7 @@ static void ehci_check_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct
     }
 
     while (qtd) {
+        usb_dcache_invalidate((uintptr_t)&qtd->hw, USB_ALIGN_UP(SIZEOF_EHCI_QTD, CONFIG_USB_EHCI_ALIGN_SIZE));
         token = qtd->hw.token;
 
         if (token & QTD_TOKEN_STATUS_ERRORS) {
@@ -766,6 +799,10 @@ int usb_hc_init(struct usbh_bus *bus)
         g_framelist[bus->hcd.hcd_id][i] = QH_HLP_QH(&g_periodic_qh_head[bus->hcd.hcd_id]);
     }
 
+    usb_dcache_clean((uintptr_t)&g_async_qh_head[bus->hcd.hcd_id].hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
+    usb_dcache_clean((uintptr_t)&g_periodic_qh_head[bus->hcd.hcd_id].hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
+    usb_dcache_clean((uintptr_t)g_framelist[bus->hcd.hcd_id], sizeof(uint32_t) * CONFIG_USB_EHCI_FRAME_LIST_SIZE);
+
     usb_hc_low_level_init(bus);
 
     USB_LOG_INFO("EHCI HCIVERSION:0x%04x\r\n", (unsigned int)EHCI_HCCR->hciversion);
@@ -1138,6 +1175,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
         return -USB_ERR_INVAL;
     }
 
+#ifdef CONFIG_USB_DCACHE_ENABLE
+    if (((uintptr_t)urb->setup % CONFIG_USB_ALIGN_SIZE) || ((uintptr_t)urb->transfer_buffer % CONFIG_USB_ALIGN_SIZE)) {
+        USB_LOG_ERR("urb buffer is not align with %d\r\n", CONFIG_USB_ALIGN_SIZE);
+        while (1) {
+        }
+    }
+#endif
     bus = urb->hport->bus;
 
     /* find active hubport in roothub */

+ 9 - 3
components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h

@@ -30,14 +30,19 @@
 #ifndef CONFIG_USB_EHCI_ISO_NUM
 #define CONFIG_USB_EHCI_ISO_NUM  4
 #endif
+#ifndef CONFIG_USB_EHCI_ALIGN_SIZE
+#define CONFIG_USB_EHCI_ALIGN_SIZE  64
+#endif
 
 extern uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port);
 
 struct ehci_qtd_hw {
     struct ehci_qtd hw;
     struct usbh_urb *urb;
+    bool dir_in;
+    uintptr_t bufaddr;
     uint32_t length;
-} __attribute__((aligned(32)));
+} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
 
 struct ehci_qh_hw {
     struct ehci_qh hw;
@@ -46,7 +51,7 @@ struct ehci_qh_hw {
     struct usbh_urb *urb;
     usb_osal_sem_t waitsem;
     uint8_t remove_in_iaad;
-} __attribute__((aligned(32)));
+} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
 
 struct ehci_itd_hw {
     struct ehci_itd hw;
@@ -55,7 +60,8 @@ struct ehci_itd_hw {
     uint8_t mf_unmask;
     uint8_t mf_valid;
     uint32_t pkt_idx[8];
-} __attribute__((aligned(32)));
+    bool dir_in;
+} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
 
 struct ehci_iso_hw
 {

+ 1 - 4
components/drivers/usb/cherryusb/port/fsdev/README.md

@@ -23,10 +23,7 @@
 
 ## GD32
 
-- GD32F10X_MD、GD32F10X_HD、GD32F10X_XD
-- GD32F30X_HD、GD32F30X_XD
-- GD32F350
-- GD32F407
+- GD32F10X
 
 ## CH32
 

+ 4 - 12
components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c

@@ -869,12 +869,7 @@ void handle_ep0(struct usbh_bus *bus)
             break;
         case USB_EP0_STATE_IN_DATA:
             if (ep0_status & USB_CSRL0_RXRDY) {
-                size = urb->transfer_buffer_length;
-                if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
-                    size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
-                }
-
-                size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
+                size = HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET);
                 musb_read_packet(bus, 0, urb->transfer_buffer, size);
                 HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_RXRDY;
                 urb->transfer_buffer += size;
@@ -933,6 +928,7 @@ void USBH_IRQHandler(uint8_t busid)
     uint8_t ep_idx;
     uint8_t old_ep_idx;
     struct usbh_bus *bus;
+    uint32_t size;
 
     bus = &g_usbhost_bus[busid];
 
@@ -1024,7 +1020,7 @@ void USBH_IRQHandler(uint8_t busid)
                     urb->errorcode = 0;
                     musb_urb_waitup(urb);
                 } else {
-                    musb_write_packet(bus, ep_idx, urb->transfer_buffer, size);
+                    musb_write_packet(bus, ep_idx, urb->transfer_buffer, MIN(urb->transfer_buffer_length, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)));
                     HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
                 }
             }
@@ -1056,11 +1052,7 @@ void USBH_IRQHandler(uint8_t busid)
                 urb->errorcode = -USB_ERR_STALL;
                 musb_urb_waitup(urb);
             } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {
-                uint32_t size = urb->transfer_buffer_length;
-                if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
-                    size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
-                }
-                size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
+                size = HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET);
 
                 musb_read_packet(bus, ep_idx, urb->transfer_buffer, size);
 

+ 6 - 2
components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h

@@ -22,14 +22,18 @@
 #ifndef CONFIG_USB_OHCI_TD_NUM
 #define CONFIG_USB_OHCI_TD_NUM 3
 #endif
+#ifndef CONFIG_USB_OHCI_ALIGN_SIZE
+#define CONFIG_USB_OHCI_ALIGN_SIZE  64
+#endif
 
 struct ohci_ed_hw;
 struct ohci_td_hw {
     struct ohci_gtd hw;
     struct usbh_urb *urb;
+    bool dir_in;
     uint32_t buf_start;
     uint32_t length;
-} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
+} __attribute__((aligned(CONFIG_USB_OHCI_ALIGN_SIZE))); /* min is 16bytes, we use CONFIG_USB_OHCI_ALIGN_SIZE for cacheline */
 
 struct ohci_ed_hw {
     struct ohci_ed hw;
@@ -37,7 +41,7 @@ struct ohci_ed_hw {
     uint32_t td_count;
     uint8_t ed_type;
     usb_osal_sem_t waitsem;
-} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
+} __attribute__((aligned(CONFIG_USB_OHCI_ALIGN_SIZE))); /* min is 16bytes, we use CONFIG_USB_OHCI_ALIGN_SIZE for cacheline */
 
 struct ohci_hcd {
     bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM];

+ 5 - 0
components/drivers/usb/cherryusb/port/rp2040/README.md

@@ -0,0 +1,5 @@
+# Note
+
+## Support Chip List
+
+- RP2040/RP2350

+ 588 - 0
components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c

@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2022, HaiMianBBao
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "hardware/resets.h"
+#include "hardware/irq.h"
+#include "hardware/structs/usb.h"
+#if CHERRYUSB_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
+#include "pico/fix/rp2040_usb_device_enumeration.h"
+#endif
+
+#define usb_hw_set   hw_set_alias(usb_hw)
+#define usb_hw_clear hw_clear_alias(usb_hw)
+
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 16
+#endif
+
+#ifndef FORCE_VBUS_DETECT
+#define FORCE_VBUS_DETECT 1
+#endif
+
+/* Endpoint state */
+struct rp2040_ep_state {
+    uint16_t ep_mps;    /* Endpoint max packet size */
+    uint8_t ep_type;    /* Endpoint type */
+    uint8_t ep_stalled; /* Endpoint stall flag */
+    uint8_t ep_enable;  /* Endpoint enable */
+    uint8_t ep_addr;    /* Endpoint address */
+    uint8_t *xfer_buf;
+    uint32_t xfer_len;
+    uint32_t actual_xfer_len;
+
+    volatile uint32_t *endpoint_control; /*!< Endpoint control register */
+    volatile uint32_t *buffer_control;   /*!< Buffer control register */
+    uint8_t *data_buffer;                /*!< Buffer pointer in usb dpram */
+    uint8_t next_pid;                    /*!< Toggle after each packet (unless replying to a SETUP) */
+};
+
+/* Driver state */
+struct rp2040_udc {
+    volatile uint8_t dev_addr;
+    struct rp2040_ep_state in_ep[CONFIG_USBDEV_EP_NUM];  /*!< IN endpoint parameters*/
+    struct rp2040_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
+    struct usb_setup_packet setup;                       /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
+} g_rp2040_udc;
+
+void rp2040_usbd_irq(void);
+
+/**
+ * @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
+ *
+ * @param buf
+ * @return uint32_t
+ */
+static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
+{
+    return (uint32_t)buf ^ (uint32_t)usb_dpram;
+}
+
+/**
+ * @brief Set up the endpoint control register for an endpoint (if applicable. Not valid for EP0).
+ *
+ * @param ep
+ */
+void usb_setup_endpoint(const struct rp2040_ep_state *ep)
+{
+    // EP0 doesn't have one so return if that is the case
+    if (!ep->endpoint_control) {
+        return;
+    }
+
+    // Get the data buffer as an offset of the USB controller's DPRAM
+    uint32_t dpram_offset = usb_buffer_offset(ep->data_buffer);
+    uint32_t reg = EP_CTRL_ENABLE_BITS |
+                   EP_CTRL_INTERRUPT_PER_BUFFER |
+                   (ep->ep_type << EP_CTRL_BUFFER_TYPE_LSB) |
+                   dpram_offset;
+    *ep->endpoint_control = reg;
+}
+
+/**
+ * @brief Starts a transfer on a given endpoint.
+ *
+ * @param ep, the endpoint configuration.
+ * @param buf, the data buffer to send. Only applicable if the endpoint is TX
+ * @param len, the length of the data in buf (this example limits max len to one packet - 64 bytes)
+ */
+static void usb_start_transfer(struct rp2040_ep_state *ep, uint8_t *buf, uint16_t len)
+{
+    /*!< Prepare buffer control register value */
+    uint32_t val = len | USB_BUF_CTRL_AVAIL;
+
+    if (len < ep->ep_mps) {
+        val |= USB_BUF_CTRL_LAST;
+    }
+
+    if (USB_EP_DIR_IS_IN(ep->ep_addr)) {
+        /*!< Need to copy the data from the user buffer to the usb memory */
+        if (buf != NULL) {
+            memcpy((void *)ep->data_buffer, (void *)buf, len);
+        }
+        /*!< Mark as full */
+        val |= USB_BUF_CTRL_FULL;
+    }
+
+    /*!< Set pid and flip for next transfer */
+    val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
+    ep->next_pid ^= 1u;
+
+    *ep->buffer_control = val;
+}
+
+int usb_dc_init(uint8_t busid)
+{
+    uint8_t *next_buffer_ptr;
+
+    memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
+
+    g_rp2040_udc.in_ep[0].endpoint_control = NULL;
+    g_rp2040_udc.in_ep[0].data_buffer = &usb_dpram->ep0_buf_a[0];
+    g_rp2040_udc.out_ep[0].endpoint_control = NULL;
+    g_rp2040_udc.out_ep[0].data_buffer = &usb_dpram->ep0_buf_a[0];
+
+    for (uint32_t i = 0; i < CONFIG_USBDEV_EP_NUM; i++) {
+        g_rp2040_udc.in_ep[i].buffer_control = &usb_dpram->ep_buf_ctrl[i].in;
+        g_rp2040_udc.out_ep[i].buffer_control = &usb_dpram->ep_buf_ctrl[i].out;
+
+        if (i != 0) {
+            g_rp2040_udc.in_ep[i].endpoint_control = &usb_dpram->ep_ctrl[i - 1].in;
+            g_rp2040_udc.out_ep[i].endpoint_control = &usb_dpram->ep_ctrl[i - 1].out;
+        }
+    }
+
+    next_buffer_ptr = &usb_dpram->epx_data[0];
+
+    for (uint32_t i = 1; i < CONFIG_USBDEV_EP_NUM; i++) {
+        g_rp2040_udc.in_ep[i].data_buffer = next_buffer_ptr;
+        if (i == 1) {
+            next_buffer_ptr += 1024; /* for iso video */
+        } else {
+            next_buffer_ptr += 64;
+        }
+
+        g_rp2040_udc.out_ep[i].data_buffer = next_buffer_ptr;
+        next_buffer_ptr += 64;
+    }
+
+    // Remove shared irq if it was previously added so as not to fill up shared irq slots
+    irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
+
+    irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbd_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
+
+    // Reset usb controller
+    reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
+
+    /*!< Clear any previous state just in case */
+    memset(usb_hw, 0, sizeof(*usb_hw));
+    memset(usb_dpram, 0, sizeof(*usb_dpram));
+
+    /*!< Mux the controller to the onboard usb phy */
+    usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
+
+#if FORCE_VBUS_DETECT
+    // Force VBUS detect so the device thinks it is plugged into a host
+    usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+#endif
+
+    // Enable the USB controller in device mode.
+    usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
+
+    // Enable an interrupt per EP0 transaction
+    usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; // <2>
+
+    // Enable interrupts for when a buffer is done, when the bus is reset,
+    // and when a setup packet is received
+    usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
+                   USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
+                   (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
+
+    // Enable USB interrupt at processor
+    irq_set_enabled(USBCTRL_IRQ, true);
+
+    usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
+    return 0;
+}
+
+int usb_dc_deinit(uint8_t busid)
+{
+    irq_set_enabled(USBCTRL_IRQ, false);
+    // Remove shared irq if it was previously added so as not to fill up shared irq slots
+    irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
+
+    usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
+    memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
+
+    return 0;
+}
+
+int usbd_set_address(uint8_t busid, const uint8_t addr)
+{
+    g_rp2040_udc.dev_addr = addr;
+    return 0;
+}
+
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
+uint8_t usbd_get_port_speed(uint8_t busid)
+{
+    return USB_SPEED_FULL;
+}
+
+int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
+
+    if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
+        g_rp2040_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_rp2040_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        g_rp2040_udc.out_ep[ep_idx].ep_addr = ep->bEndpointAddress;
+        g_rp2040_udc.out_ep[ep_idx].ep_enable = true;
+        /*!< Clear control reg */
+        *(g_rp2040_udc.out_ep[ep_idx].buffer_control) = 0;
+
+        usb_setup_endpoint(&g_rp2040_udc.out_ep[ep_idx]);
+    } else {
+        g_rp2040_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_rp2040_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        g_rp2040_udc.in_ep[ep_idx].ep_addr = ep->bEndpointAddress;
+        g_rp2040_udc.in_ep[ep_idx].ep_enable = true;
+        /*!< Clear control reg */
+        *(g_rp2040_udc.in_ep[ep_idx].buffer_control) = 0;
+
+        usb_setup_endpoint(&g_rp2040_udc.in_ep[ep_idx]);
+    }
+    return 0;
+}
+
+int usbd_ep_close(uint8_t busid, const uint8_t ep)
+{
+    if (USB_EP_DIR_IS_IN(ep)) {
+    } else if (USB_EP_DIR_IS_OUT(ep)) {
+    }
+    return 0;
+}
+
+int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
+{
+    if (USB_EP_GET_IDX(ep) == 0) {
+        /**
+         * A stall on EP0 has to be armed so it can be cleared on the next setup packet
+         */
+        usb_hw_set->ep_stall_arm = (USB_EP_DIR_IS_IN(ep)) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
+    }
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        *(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
+    } else {
+        *(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
+    }
+
+    return 0;
+}
+
+int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (ep_idx != 0) {
+        if (USB_EP_DIR_IS_OUT(ep)) {
+            g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
+            *(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = ~USB_BUF_CTRL_STALL;
+        } else {
+            g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
+            *(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = ~USB_BUF_CTRL_STALL;
+        }
+    }
+    return 0;
+}
+
+int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
+{
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) & USB_BUF_CTRL_STALL) {
+            *stalled = 1;
+        } else {
+            *stalled = 0;
+        }
+    } else {
+        if (*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) & USB_BUF_CTRL_STALL) {
+            *stalled = 1;
+        } else {
+            *stalled = 0;
+        }
+    }
+    return 0;
+}
+
+int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!g_rp2040_udc.in_ep[ep_idx].ep_enable) {
+        return -2;
+    }
+
+    g_rp2040_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_rp2040_udc.in_ep[ep_idx].xfer_len = data_len;
+    g_rp2040_udc.in_ep[ep_idx].actual_xfer_len = 0;
+
+    if (data_len == 0) {
+        usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], NULL, 0);
+    } else {
+        data_len = MIN(data_len, g_rp2040_udc.in_ep[ep_idx].ep_mps);
+        usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], g_rp2040_udc.in_ep[ep_idx].xfer_buf, data_len);
+    }
+
+    return 0;
+}
+
+int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+    if (!g_rp2040_udc.out_ep[ep_idx].ep_enable) {
+        return -2;
+    }
+    g_rp2040_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_rp2040_udc.out_ep[ep_idx].xfer_len = data_len;
+    g_rp2040_udc.out_ep[ep_idx].actual_xfer_len = 0;
+
+    if (data_len == 0) {
+        usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], NULL, 0);
+    } else {
+        /*!< Not zlp */
+        data_len = MIN(data_len, g_rp2040_udc.out_ep[ep_idx].ep_mps);
+        usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], g_rp2040_udc.out_ep[ep_idx].xfer_buf, data_len);
+    }
+    return 0;
+}
+
+/**
+ * @brief Notify an endpoint that a transfer has completed.
+ *
+ * @param ep, the endpoint to notify.
+ */
+static void usb_handle_ep_buff_done(struct rp2040_ep_state *ep)
+{
+    uint32_t buffer_control = *ep->buffer_control;
+    /*!< Get the transfer length for this endpoint */
+    uint16_t read_count = buffer_control & USB_BUF_CTRL_LEN_MASK;
+    /*!< Call that endpoints buffer done handler */
+    if (ep->ep_addr == 0x80) {
+        /*!< EP0 In */
+        /**
+         * Determine the current setup direction
+         */
+        switch (g_rp2040_udc.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
+            case 1:
+                /*!< Get */
+                if (g_rp2040_udc.in_ep[0].xfer_len > g_rp2040_udc.in_ep[0].ep_mps) {
+                    g_rp2040_udc.in_ep[0].xfer_len -= g_rp2040_udc.in_ep[0].ep_mps;
+                    g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].ep_mps;
+                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
+                } else {
+                    g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].xfer_len;
+                    g_rp2040_udc.in_ep[0].xfer_len = 0;
+                    /**
+                     * EP0 In complete and host will send a out token to get 0 length packet
+                     * In the next usbd_event_ep_in_complete_handler, stack will start read 0 length packet
+                     * and host must send data1 packet.We resest the ep0 next_pid = 1 in setup interrupt head.
+                     */
+                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
+                }
+                break;
+            case 0:
+                /*!< Set */
+                if (g_rp2040_udc.dev_addr > 0) {
+                    usb_hw->dev_addr_ctrl = g_rp2040_udc.dev_addr;
+                    g_rp2040_udc.dev_addr = 0;
+                } else {
+                    /*!< Normal status stage // Setup  out...out  in  */
+                    /**
+                     * Perpar for next setup
+                     */
+                }
+                break;
+        }
+
+    } else if (ep->ep_addr == 0x00) {
+        /*!< EP0 Out */
+        memcpy(g_rp2040_udc.out_ep[0].xfer_buf, g_rp2040_udc.out_ep[0].data_buffer, read_count);
+        if (read_count == 0) {
+            /*!< Normal status stage // Setup  in...in  out  */
+            /**
+              * Perpar for next setup
+              */
+        }
+
+        g_rp2040_udc.out_ep[0].actual_xfer_len += read_count;
+        g_rp2040_udc.out_ep[0].xfer_len -= read_count;
+
+        usbd_event_ep_out_complete_handler(0, 0x00, g_rp2040_udc.out_ep[0].actual_xfer_len);
+    } else {
+        /*!< Others ep */
+        uint16_t data_len = 0;
+        if (USB_EP_DIR_IS_OUT(ep->ep_addr)) {
+            /*!< flip the pid */
+            memcpy(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].data_buffer, read_count);
+            g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf += read_count;
+            g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += read_count;
+            g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len -= read_count;
+
+            if (read_count < g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps || g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len == 0) {
+                /*!< Out complete */
+                usbd_event_ep_out_complete_handler(0, ep->ep_addr, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
+            } else {
+                /*!< Need read again */
+                data_len = MIN(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps);
+                usb_start_transfer(&g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f], NULL, data_len);
+            }
+        } else {
+            if (g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len > g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps) {
+                /*!< Need tx again */
+                g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len -= g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
+                g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
+                g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
+                data_len = MIN(g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps);
+                usb_start_transfer(&g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f], g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf, data_len);
+            } else {
+                /*!< In complete */
+                g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len;
+                g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len = 0;
+                usbd_event_ep_in_complete_handler(0, ep->ep_addr, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
+            }
+        }
+    }
+}
+
+/**
+ * @brief Find the endpoint configuration for a specified endpoint number and
+ * direction and notify it that a transfer has completed.
+ *
+ * @param ep_num
+ * @param in
+ */
+static void usb_handle_buff_done(uint8_t ep_num, bool in)
+{
+    uint8_t ep_addr = ep_num | (in ? USB_EP_DIR_IN : 0);
+    if (USB_EP_DIR_IS_OUT(ep_addr)) {
+        usb_handle_ep_buff_done(&g_rp2040_udc.out_ep[ep_num]);
+    } else {
+        usb_handle_ep_buff_done(&g_rp2040_udc.in_ep[ep_num]);
+    }
+}
+
+/**
+ * @brief Handle a "buffer status" irq. This means that one or more
+ * buffers have been sent / received. Notify each endpoint where this
+ * is the case.
+ */
+static void usb_handle_buff_status(void)
+{
+    uint32_t remaining_buffers = usb_hw->buf_status;
+
+    uint32_t bit = 1u;
+    for (uint8_t i = 0; remaining_buffers && i < USB_NUM_ENDPOINTS * 2; i++) {
+        if (remaining_buffers & bit) {
+            /*!< clear this in advance */
+            usb_hw_clear->buf_status = bit;
+            /*!< IN transfer for even i, OUT transfer for odd i */
+            usb_handle_buff_done(i >> 1u, !(i & 1u));
+            remaining_buffers &= ~bit;
+        }
+        bit <<= 1u;
+    }
+}
+
+void USBD_IRQHandler(uint8_t busid)
+{
+    uint32_t const status = usb_hw->ints;
+    uint32_t handled = 0;
+
+    if (status & USB_INTS_BUFF_STATUS_BITS) {
+        handled |= USB_INTS_BUFF_STATUS_BITS;
+        usb_handle_buff_status();
+    }
+
+    if (status & USB_INTS_SETUP_REQ_BITS) {
+        handled |= USB_INTS_SETUP_REQ_BITS;
+        memcpy((uint8_t *)&g_rp2040_udc.setup, (uint8_t const *)&usb_dpram->setup_packet, 8);
+        /**
+         * reset pid to both 1 (data and ack)
+         */
+        g_rp2040_udc.in_ep[0].next_pid = 1;
+        g_rp2040_udc.out_ep[0].next_pid = 1;
+        usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_rp2040_udc.setup);
+        usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
+    }
+
+#if FORCE_VBUS_DETECT == 0
+    /**
+     * Since we force VBUS detect On, device will always think it is connected and
+     * couldn't distinguish between disconnect and suspend
+     */
+    if (status & USB_INTS_DEV_CONN_DIS_BITS) {
+        handled |= USB_INTS_DEV_CONN_DIS_BITS;
+        if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) {
+            /*!< Connected: nothing to do */
+            usbd_event_connect_handler(0);
+        } else {
+            /*!< Disconnected */
+            usbd_event_disconnect_handler(0);
+        }
+        usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
+    }
+#endif
+
+    /**
+     * SE0 for 2.5 us or more (will last at least 10ms)
+     */
+    if (status & USB_INTS_BUS_RESET_BITS) {
+        handled |= USB_INTS_BUS_RESET_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
+
+        usb_hw->dev_addr_ctrl = 0;
+
+        for (uint8_t i = 0; i < CONFIG_USBDEV_EP_NUM - 1; i++) {
+            /*!< Start at ep1 */
+            usb_dpram->ep_ctrl[i].in = 0;
+            usb_dpram->ep_ctrl[i].out = 0;
+        }
+
+        usbd_event_reset_handler(0);
+
+#if CHERRYUSB_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
+        /**
+         * Only run enumeration walk-around if pull up is enabled
+         */
+        if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS)
+            rp2040_usb_device_enumeration_fix();
+#endif
+    }
+
+    /**
+     * Note from pico datasheet 4.1.2.6.4 (v1.2)
+     * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when
+     * the device is first connected but the bus is idle. The bus can be idle for a few ms before
+     * the host begins sending start of frame packets. You will also see a suspend interrupt
+     * when the device is disconnected if you do not have a VBUS detect circuit connected. This is
+     * because without VBUS detection, it is impossible to tell the difference between
+     * being disconnected and suspended.
+     */
+    if (status & USB_INTS_DEV_SUSPEND_BITS) {
+        handled |= USB_INTS_DEV_SUSPEND_BITS;
+        /*!< Suspend */
+        usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
+        usbd_event_suspend_handler(0);
+    }
+
+    if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) {
+        handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
+        /*!< Resume */
+        usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
+        usbd_event_resume_handler(0);
+    }
+
+    if (status ^ handled) {
+        USB_LOG_INFO("Unhandled IRQ 0x%x\n", (uint32_t)(status ^ handled));
+    }
+}
+
+void rp2040_usbd_irq(void)
+{
+    USBD_IRQHandler(0);
+}

+ 824 - 0
components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c

@@ -0,0 +1,824 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_hub.h"
+#include "hardware/resets.h"
+#include "hardware/irq.h"
+#include "hardware/structs/usb.h"
+
+#define usb_hw_set   hw_set_alias(usb_hw)
+#define usb_hw_clear hw_clear_alias(usb_hw)
+
+#define SIE_CTRL_COMMON (USB_SIE_CTRL_SOF_EN_BITS |        \
+                         USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | \
+                         USB_SIE_CTRL_PULLDOWN_EN_BITS |   \
+                         USB_SIE_CTRL_EP0_INT_1BUF_BITS)
+
+typedef enum {
+    USB_EP0_STATE_SETUP = 0x0, /**< SETUP DATA */
+    USB_EP0_STATE_IN_DATA,     /**< IN DATA */
+    USB_EP0_STATE_IN_STATUS,   /**< IN status*/
+    USB_EP0_STATE_OUT_DATA,    /**< OUT DATA */
+    USB_EP0_STATE_OUT_STATUS,  /**< OUT status */
+} ep0_state_t;
+
+struct rp2040_pipe {
+    uint8_t chidx;
+    bool inuse;
+    volatile uint8_t ep0_state;
+    volatile uint32_t *endpoint_control; /*!< Endpoint control register */
+    volatile uint32_t *buffer_control;   /*!< Buffer control register */
+    uint8_t *data_buffer;                /*!< Buffer pointer in usb dpram */
+    uint32_t buffer_size;                /*!< Buffer size */
+    usb_osal_sem_t waitsem;
+    struct usbh_urb *urb;
+};
+
+struct rp2040_hcd {
+    volatile bool port_csc;
+    volatile bool port_pec;
+    volatile bool port_pe;
+    usb_osal_mutex_t ep0_mutex;
+    struct rp2040_pipe pipe_pool[1 + CONFIG_USBHOST_PIPE_NUM];
+} g_rp2040_hcd[CONFIG_USBHOST_MAX_BUS];
+
+void rp2040_usbh_irq(void);
+
+static int rp2040_pipe_alloc(struct usbh_bus *bus)
+{
+    size_t flags;
+    int chidx;
+
+    flags = usb_osal_enter_critical_section();
+    for (chidx = 1; chidx <= CONFIG_USBHOST_PIPE_NUM; chidx++) {
+        if (!g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse) {
+            g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse = true;
+            usb_osal_leave_critical_section(flags);
+            return chidx;
+        }
+    }
+    usb_osal_leave_critical_section(flags);
+    return -1;
+}
+
+static void rp2040_pipe_free(struct rp2040_pipe *pipe)
+{
+    size_t flags;
+
+    flags = usb_osal_enter_critical_section();
+    pipe->inuse = false;
+    usb_osal_leave_critical_section(flags);
+}
+
+/**
+ * @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
+ *
+ * @param buf
+ * @return uint32_t
+ */
+static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
+{
+    return (uint32_t)buf ^ (uint32_t)usbh_dpram;
+}
+
+static inline uint8_t usbh_get_port_speed(void)
+{
+    return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB;
+}
+
+static inline void rp2040_init_endpoint(struct usbh_bus *bus,
+                                        uint8_t chidx,
+                                        uint8_t dev_addr,
+                                        uint8_t ep_addr,
+                                        uint8_t ep_type,
+                                        uint8_t ep_interval,
+                                        uint8_t speed)
+{
+    struct rp2040_pipe *pipe;
+    uint32_t regval;
+
+    pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
+
+    // Get the data buffer as an offset of the USB controller's DPRAM
+    uint32_t dpram_offset = usb_buffer_offset(pipe->data_buffer);
+    regval = EP_CTRL_ENABLE_BITS |
+             EP_CTRL_INTERRUPT_PER_BUFFER |
+             (ep_type << EP_CTRL_BUFFER_TYPE_LSB) |
+             dpram_offset;
+
+    if (ep_interval) {
+        regval |= (uint32_t)((ep_interval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
+    }
+
+    *pipe->endpoint_control = regval;
+
+    if (chidx != 0) {
+        regval = (uint32_t)(dev_addr | ((ep_addr & 0x0f) << USB_ADDR_ENDP1_ENDPOINT_LSB));
+
+        if (!(ep_addr & 0x80)) {
+            regval |= USB_ADDR_ENDP1_INTEP_DIR_BITS;
+        }
+
+        // ls device plugged to hub
+        if ((usbh_get_port_speed() == USB_SPEED_FULL) && (speed == USB_SPEED_LOW)) {
+            regval |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS;
+        }
+
+        usb_hw->int_ep_addr_ctrl[(chidx - 1)] = regval;
+
+        // Finally, enable interrupt that endpoint
+        usb_hw_set->int_ep_ctrl = 1 << chidx;
+    } else {
+        usb_hw->dev_addr_ctrl = dev_addr;
+    }
+}
+
+static inline uint32_t usb_buf_ctrl_fill(struct usbh_bus *bus, uint8_t chidx, uint8_t ep_addr, uint8_t buf_id)
+{
+    struct rp2040_pipe *pipe;
+    struct usbh_urb *urb;
+    uint32_t len;
+    uint32_t buf_ctrl;
+
+    pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
+    urb = pipe->urb;
+
+    len = MIN(urb->transfer_buffer_length, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize));
+    urb->transfer_buffer_length -= len;
+
+    buf_ctrl = len | USB_BUF_CTRL_AVAIL;
+    buf_ctrl |= urb->data_toggle ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
+
+    if (USB_EP_DIR_IS_OUT(ep_addr)) {
+        /*!< Need to copy the data from the user buffer to the usb memory */
+        if (urb->transfer_buffer != NULL) {
+            memcpy((void *)pipe->data_buffer + buf_id * 64, (void *)urb->transfer_buffer, len);
+            urb->transfer_buffer += len;
+        }
+        /*!< Mark as full */
+        buf_ctrl |= USB_BUF_CTRL_FULL;
+    }
+
+    if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+        if (urb->transfer_buffer_length == 0) {
+            buf_ctrl |= USB_BUF_CTRL_LAST;
+        }
+    } else {
+        //TODO: handle isochronous transfer
+    }
+
+    if (buf_id)
+        buf_ctrl = buf_ctrl << 16;
+
+    return buf_ctrl;
+}
+
+/**
+ * @brief Starts a transfer on a given endpoint.
+ *
+ * @param ep, the endpoint configuration.
+ * @param buf, the data buffer to send. Only applicable if the endpoint is TX
+ * @param len, the length of the data in buf (this example limits max len to one packet - 64 bytes)
+ */
+static void usb_start_transfer(struct usbh_bus *bus, uint8_t chidx, uint8_t ep_addr)
+{
+    struct rp2040_pipe *pipe;
+    struct usbh_urb *urb;
+    uint32_t buf_ctrl;
+    uint32_t ep_ctrl;
+
+    pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
+    urb = pipe->urb;
+
+    ep_ctrl = *pipe->endpoint_control;
+    buf_ctrl = usb_buf_ctrl_fill(bus, chidx, ep_addr, 0);
+
+    if (urb->transfer_buffer_length && (ep_addr & 0x0f) == 0x00) {
+        urb->data_toggle ^= 1;
+        buf_ctrl |= usb_buf_ctrl_fill(bus, chidx, ep_addr, 1);
+
+        // Set endpoint control double buffered bit if needed
+        ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER;
+        ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER;
+    } else {
+        // Single buffered since 1 is enough
+        ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
+        ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
+    }
+    *pipe->endpoint_control = ep_ctrl;
+    *pipe->buffer_control = buf_ctrl;
+}
+
+static inline void rp2040_control_transfer_start(bool dir_in, bool isetup, uint8_t speed)
+{
+    uint32_t regval;
+
+    regval = SIE_CTRL_COMMON | USB_SIE_CTRL_START_TRANS_BITS;
+
+    if ((usbh_get_port_speed() == USB_SPEED_FULL) && (speed == USB_SPEED_LOW)) {
+        regval |= USB_SIE_CTRL_PREAMBLE_EN_BITS;
+    }
+
+    if (isetup) {
+        regval |= USB_SIE_CTRL_SEND_SETUP_BITS;
+    } else {
+        if (dir_in) {
+            regval |= USB_SIE_CTRL_RECEIVE_DATA_BITS;
+        } else {
+            regval |= USB_SIE_CTRL_SEND_DATA_BITS;
+        }
+    }
+
+    usb_hw->sie_ctrl = regval & ~USB_SIE_CTRL_START_TRANS_BITS;
+    busy_wait_at_least_cycles(12);
+    usb_hw->sie_ctrl = regval;
+}
+
+static void rp2040_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
+{
+    struct rp2040_pipe *pipe;
+
+    pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
+
+    if (pipe->ep0_state == USB_EP0_STATE_SETUP) /* fill setup */
+    {
+        pipe->urb->data_toggle = 1;
+        memcpy((uint8_t *)usbh_dpram->setup_packet, (uint8_t *)setup, 8);
+        rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
+        rp2040_control_transfer_start(false, true, urb->hport->speed);
+    } else if (pipe->ep0_state == USB_EP0_STATE_IN_DATA) /* fill in data */
+    {
+        rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
+        usb_start_transfer(bus, chidx, 0x80);
+        rp2040_control_transfer_start(true, false, urb->hport->speed);
+    } else if (pipe->ep0_state == USB_EP0_STATE_OUT_DATA) /* fill out data */
+    {
+        rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
+        usb_start_transfer(bus, chidx, 0x00);
+        rp2040_control_transfer_start(false, false, urb->hport->speed);
+    } else if (pipe->ep0_state == USB_EP0_STATE_IN_STATUS) /* fill in status */
+    {
+        urb->data_toggle = 1;
+        rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
+        usb_start_transfer(bus, chidx, 0x80);
+        rp2040_control_transfer_start(true, false, urb->hport->speed);
+    } else if (pipe->ep0_state == USB_EP0_STATE_OUT_STATUS) /* fill out status */
+    {
+        urb->data_toggle = 1;
+        rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
+        usb_start_transfer(bus, chidx, 0x00);
+        rp2040_control_transfer_start(false, false, urb->hport->speed);
+    }
+}
+
+static void rp2040_bulk_int_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
+{
+    rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), urb->ep->bInterval, urb->hport->speed);
+    usb_start_transfer(bus, chidx, urb->ep->bEndpointAddress);
+}
+
+int usb_hc_init(struct usbh_bus *bus)
+{
+    uint8_t *next_buffer_ptr;
+
+    memset(&g_rp2040_hcd[bus->hcd.hcd_id], 0, sizeof(struct rp2040_hcd));
+
+    for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem = usb_osal_sem_create(0);
+        if (g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem == NULL) {
+            USB_LOG_ERR("Failed to create waitsem\r\n");
+            return -USB_ERR_NOMEM;
+        }
+    }
+
+    g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex = usb_osal_mutex_create();
+    if (g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex == NULL) {
+        USB_LOG_ERR("Failed to create ep0_mutex\r\n");
+        return -USB_ERR_NOMEM;
+    }
+
+    g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].endpoint_control = &usbh_dpram->epx_ctrl;
+    g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_control = &usbh_dpram->epx_buf_ctrl;
+    g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].data_buffer = &usbh_dpram->epx_data[0];
+    g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_size = (64 * 2);
+
+    next_buffer_ptr = &usb_dpram->epx_data[64 * 2];
+
+    for (uint8_t i = 1; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].chidx = i;
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].endpoint_control = &usbh_dpram->int_ep_ctrl[i - 1].ctrl;
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_control = &usbh_dpram->int_ep_buffer_ctrl[i - 1].ctrl;
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].data_buffer = next_buffer_ptr;
+        g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_size = (64 * 2);
+        next_buffer_ptr += (64 * 2);
+    }
+
+    // Reset usb controller
+    reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
+
+    // Remove shared irq if it was previously added so as not to fill up shared irq slots
+    irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
+
+    irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbh_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
+
+    /*!< Clear any previous state just in case */
+    memset(usb_hw, 0, sizeof(*usb_hw));
+    memset(usbh_dpram, 0, sizeof(*usbh_dpram));
+
+    /*!< Mux the controller to the onboard usb phy */
+    usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
+
+    // Force VBUS detect so the device thinks it is plugged into a host
+    usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+
+    // Enable the USB controller in device mode.
+    usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;
+
+    usb_hw->sie_ctrl = SIE_CTRL_COMMON;
+
+    // Enable USB interrupt at processor
+    irq_set_enabled(USBCTRL_IRQ, true);
+
+    usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
+                   USB_INTE_HOST_CONN_DIS_BITS |
+                   USB_INTE_STALL_BITS |
+                   USB_INTE_TRANS_COMPLETE_BITS |
+                   USB_INTE_ERROR_RX_TIMEOUT_BITS |
+                   USB_INTE_ERROR_DATA_SEQ_BITS;
+    return 0;
+}
+
+int usb_hc_deinit(struct usbh_bus *bus)
+{
+    // Enable USB interrupt at processor
+    irq_set_enabled(USBCTRL_IRQ, false);
+
+    // Remove shared irq if it was previously added so as not to fill up shared irq slots
+    irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
+
+    for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
+        usb_osal_sem_delete(g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem);
+    }
+
+    usb_osal_mutex_delete(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
+
+    return 0;
+}
+
+uint16_t usbh_get_frame_number(struct usbh_bus *bus)
+{
+    return usb_hw->sof_rd;
+}
+
+int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
+{
+    uint8_t nports;
+    uint8_t port;
+    uint32_t status;
+
+    nports = CONFIG_USBHOST_MAX_RHPORTS;
+    port = setup->wIndex;
+    if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
+        switch (setup->bRequest) {
+            case HUB_REQUEST_CLEAR_FEATURE:
+                switch (setup->wValue) {
+                    case HUB_FEATURE_HUB_C_LOCALPOWER:
+                        break;
+                    case HUB_FEATURE_HUB_C_OVERCURRENT:
+                        break;
+                    default:
+                        return -USB_ERR_INVAL;
+                }
+                break;
+            case HUB_REQUEST_SET_FEATURE:
+                switch (setup->wValue) {
+                    case HUB_FEATURE_HUB_C_LOCALPOWER:
+                        break;
+                    case HUB_FEATURE_HUB_C_OVERCURRENT:
+                        break;
+                    default:
+                        return -USB_ERR_INVAL;
+                }
+                break;
+            case HUB_REQUEST_GET_DESCRIPTOR:
+                break;
+            case HUB_REQUEST_GET_STATUS:
+                memset(buf, 0, 4);
+                break;
+            default:
+                break;
+        }
+    } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
+        switch (setup->bRequest) {
+            case HUB_REQUEST_CLEAR_FEATURE:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                switch (setup->wValue) {
+                    case HUB_PORT_FEATURE_ENABLE:
+                        break;
+                    case HUB_PORT_FEATURE_SUSPEND:
+                    case HUB_PORT_FEATURE_C_SUSPEND:
+                        break;
+                    case HUB_PORT_FEATURE_POWER:
+                        break;
+                    case HUB_PORT_FEATURE_C_CONNECTION:
+                        g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 0;
+                        break;
+                    case HUB_PORT_FEATURE_C_ENABLE:
+                        g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 0;
+                        break;
+                    case HUB_PORT_FEATURE_C_OVER_CURREN:
+                        break;
+                    case HUB_PORT_FEATURE_C_RESET:
+                        break;
+                    default:
+                        return -USB_ERR_INVAL;
+                }
+                break;
+            case HUB_REQUEST_SET_FEATURE:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                switch (setup->wValue) {
+                    case HUB_PORT_FEATURE_SUSPEND:
+                        break;
+                    case HUB_PORT_FEATURE_POWER:
+                        break;
+                    case HUB_PORT_FEATURE_RESET:
+                        break;
+
+                    default:
+                        return -USB_ERR_INVAL;
+                }
+                break;
+            case HUB_REQUEST_GET_STATUS:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                status = 0;
+                if (g_rp2040_hcd[bus->hcd.hcd_id].port_csc) {
+                    status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
+                }
+                if (g_rp2040_hcd[bus->hcd.hcd_id].port_pec) {
+                    status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
+                }
+
+                if (g_rp2040_hcd[bus->hcd.hcd_id].port_pe) {
+                    status |= (1 << HUB_PORT_FEATURE_CONNECTION);
+                    status |= (1 << HUB_PORT_FEATURE_ENABLE);
+                    if (usbh_get_port_speed() == USB_SPEED_LOW) {
+                        status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
+                    }
+                }
+
+                status |= (1 << HUB_PORT_FEATURE_POWER);
+                memcpy(buf, &status, 4);
+                break;
+            default:
+                break;
+        }
+    }
+    return 0;
+}
+
+int usbh_submit_urb(struct usbh_urb *urb)
+{
+    struct rp2040_pipe *pipe;
+    struct usbh_bus *bus;
+    int chidx;
+    size_t flags;
+    int ret = 0;
+
+    if (!urb || !urb->hport || !urb->ep || !urb->hport->bus) {
+        return -USB_ERR_INVAL;
+    }
+
+    if (!urb->hport->connected || !(usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS)) {
+        return -USB_ERR_NOTCONN;
+    }
+
+    if (urb->errorcode == -USB_ERR_BUSY) {
+        return -USB_ERR_BUSY;
+    }
+
+    bus = urb->hport->bus;
+
+    if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
+        chidx = 0;
+        /* all the control transfers use the only one ep0 register, we need to lock */
+        usb_osal_mutex_take(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
+    } else {
+        chidx = rp2040_pipe_alloc(bus);
+        if (chidx == -1) {
+            return -USB_ERR_NOMEM;
+        }
+    }
+
+    flags = usb_osal_enter_critical_section();
+
+    pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
+    pipe->chidx = chidx;
+    pipe->urb = urb;
+
+    urb->hcpriv = pipe;
+    urb->errorcode = -USB_ERR_BUSY;
+    urb->actual_length = 0;
+    usb_osal_leave_critical_section(flags);
+
+    switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
+        case USB_ENDPOINT_TYPE_CONTROL:
+            pipe->ep0_state = USB_EP0_STATE_SETUP;
+            rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
+            break;
+        case USB_ENDPOINT_TYPE_BULK:
+        case USB_ENDPOINT_TYPE_INTERRUPT:
+            rp2040_bulk_int_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
+            break;
+        default:
+            break;
+    }
+
+    if (urb->timeout > 0) {
+        /* wait until timeout or sem give */
+        ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
+        if (ret < 0) {
+            goto errout_timeout;
+        }
+        urb->timeout = 0;
+        ret = urb->errorcode;
+        /* we can free pipe when waitsem is done */
+        rp2040_pipe_free(pipe);
+
+        if (chidx == 0) {
+            usb_osal_mutex_give(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
+        }
+    }
+    return ret;
+errout_timeout:
+    if (chidx == 0) {
+        usb_osal_mutex_give(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
+    }
+    urb->timeout = 0;
+    usbh_kill_urb(urb);
+    return ret;
+}
+
+int usbh_kill_urb(struct usbh_urb *urb)
+{
+    struct rp2040_pipe *pipe;
+    struct usbh_bus *bus;
+    size_t flags;
+
+    if (!urb || !urb->hcpriv || !urb->hport->bus) {
+        return -USB_ERR_INVAL;
+    }
+
+    bus = urb->hport->bus;
+
+    ARG_UNUSED(bus);
+
+    flags = usb_osal_enter_critical_section();
+
+    pipe = (struct rp2040_pipe *)urb->hcpriv;
+    urb->hcpriv = NULL;
+    urb->errorcode = -USB_ERR_SHUTDOWN;
+    pipe->urb = NULL;
+    usb_hw_clear->int_ep_ctrl = 1 << pipe->chidx;
+    usb_hw_clear->buf_status = 1 << (pipe->chidx * 2 + 0);
+    usb_hw_clear->buf_status = 1 << (pipe->chidx * 2 + 1);
+    *pipe->endpoint_control = 0;
+    *pipe->buffer_control = 0;
+
+    if (urb->timeout) {
+        usb_osal_sem_give(pipe->waitsem);
+    } else {
+        rp2040_pipe_free(pipe);
+    }
+
+    usb_osal_leave_critical_section(flags);
+
+    return 0;
+}
+
+static void rp2040_urb_waitup(struct usbh_urb *urb)
+{
+    struct rp2040_pipe *pipe;
+
+    pipe = (struct rp2040_pipe *)urb->hcpriv;
+    pipe->urb = NULL;
+    urb->hcpriv = NULL;
+
+    if (urb->timeout) {
+        usb_osal_sem_give(pipe->waitsem);
+    } else {
+        rp2040_pipe_free(pipe);
+    }
+
+    if (urb->complete) {
+        if (urb->errorcode < 0) {
+            urb->complete(urb->arg, urb->errorcode);
+        } else {
+            urb->complete(urb->arg, urb->actual_length);
+        }
+    }
+}
+
+static void rp2040_handle_buffer_status(struct usbh_bus *bus)
+{
+    struct rp2040_pipe *pipe;
+    struct usbh_urb *urb;
+    uint32_t remaining_buffers;
+    uint32_t size;
+
+    remaining_buffers = usb_hw->buf_status;
+
+    uint32_t bit = 1u;
+    if (remaining_buffers & bit) {
+        remaining_buffers &= ~bit;
+        usb_hw_clear->buf_status = bit;
+
+        pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0];
+        urb = pipe->urb;
+        switch (pipe->ep0_state) {
+            case USB_EP0_STATE_IN_DATA:
+                size = *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
+                memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer, size);
+
+                urb->transfer_buffer += size;
+                urb->actual_length += size;
+
+                if (*pipe->endpoint_control & EP_CTRL_DOUBLE_BUFFERED_BITS) {
+                    if (size == USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
+                        size = (*pipe->buffer_control >> 16) & USB_BUF_CTRL_LEN_MASK;
+                        memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer + 64, size);
+
+                        urb->transfer_buffer += size;
+                        urb->actual_length += size;
+                    }
+                }
+
+                if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) {
+                    pipe->ep0_state = USB_EP0_STATE_OUT_STATUS;
+                    rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
+                } else {
+                    urb->data_toggle ^= 1;
+                    usb_start_transfer(bus, 0, 0x80);
+                }
+                break;
+            case USB_EP0_STATE_OUT_DATA:
+                urb->actual_length += *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
+
+                if (*pipe->endpoint_control & EP_CTRL_DOUBLE_BUFFERED_BITS) {
+                    urb->actual_length += (*pipe->buffer_control >> 16) & USB_BUF_CTRL_LEN_MASK;
+                }
+
+                if (urb->transfer_buffer_length == 0) {
+                    pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
+                    rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
+                } else {
+                    urb->data_toggle ^= 1;
+                    usb_start_transfer(bus, 0, 0x00);
+                }
+                break;
+            case USB_EP0_STATE_IN_STATUS:
+            case USB_EP0_STATE_OUT_STATUS:
+                urb->errorcode = 0;
+                rp2040_urb_waitup(urb);
+                break;
+            default:
+                break;
+        }
+    }
+
+    for (uint8_t i = 1; remaining_buffers && i <= CONFIG_USBHOST_PIPE_NUM; i++) {
+        for (uint8_t j = 0; j < 2; j++) {
+            bit = 1 << (i * 2 + j);
+            if (remaining_buffers & bit) {
+                remaining_buffers &= ~bit;
+                usb_hw_clear->buf_status = bit;
+
+                pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i];
+                urb = pipe->urb;
+                if (urb == NULL) {
+                    continue;
+                }
+
+                if (j == 0) { //IN
+                    size = *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
+                    memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer, size);
+
+                    urb->transfer_buffer += size;
+                    urb->actual_length += size;
+
+                    urb->data_toggle ^= 1;
+                    if (size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) || urb->transfer_buffer_length == 0) {
+                        urb->errorcode = 0;
+                        rp2040_urb_waitup(urb);
+                    } else {
+                        usb_start_transfer(bus, i, urb->ep->bEndpointAddress);
+                    }
+                } else { //OUT
+                    urb->data_toggle ^= 1;
+
+                    urb->actual_length += *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
+
+                    if (urb->transfer_buffer_length == 0) {
+                        urb->errorcode = 0;
+                        rp2040_urb_waitup(urb);
+                    } else {
+                        usb_start_transfer(bus, i, urb->ep->bEndpointAddress);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void USBH_IRQHandler(uint8_t busid)
+{
+    uint32_t status;
+    uint32_t handled = 0;
+    struct usbh_bus *bus;
+    struct rp2040_pipe *pipe;
+    struct usbh_urb *urb;
+
+    bus = &g_usbhost_bus[busid];
+    status = usb_hw->ints;
+
+    if (status & USB_INTS_HOST_CONN_DIS_BITS) {
+        handled |= USB_INTS_HOST_CONN_DIS_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
+        if (usbh_get_port_speed()) {
+            g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
+            g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
+            g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 1;
+            bus->hcd.roothub.int_buffer[0] = (1 << 1);
+            usbh_hub_thread_wakeup(&bus->hcd.roothub);
+        } else {
+            g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
+            g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
+            g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 0;
+            bus->hcd.roothub.int_buffer[0] = (1 << 1);
+            usbh_hub_thread_wakeup(&bus->hcd.roothub);
+        }
+    }
+
+    if (status & USB_INTS_STALL_BITS) {
+        handled |= USB_INTS_STALL_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS;
+    }
+
+    if (status & USB_INTS_BUFF_STATUS_BITS) {
+        handled |= USB_INTS_BUFF_STATUS_BITS;
+        rp2040_handle_buffer_status(bus);
+    }
+
+    if (status & USB_INTS_TRANS_COMPLETE_BITS) {
+        handled |= USB_INTS_TRANS_COMPLETE_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
+        if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) {
+            pipe = (struct rp2040_pipe *)&g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0];
+            urb = pipe->urb;
+            if (urb) {
+                if (urb->setup->wLength) {
+                    if (urb->setup->bmRequestType & 0x80) {
+                        pipe->ep0_state = USB_EP0_STATE_IN_DATA;
+                    } else {
+                        pipe->ep0_state = USB_EP0_STATE_OUT_DATA;
+                    }
+                } else {
+                    pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
+                }
+                urb->actual_length = 8;
+                rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
+            }
+        } else {
+        }
+    }
+
+    if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) {
+        handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS;
+    }
+
+    if (status & USB_INTS_ERROR_DATA_SEQ_BITS) {
+        handled |= USB_INTS_ERROR_DATA_SEQ_BITS;
+        usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
+    }
+
+    if (status ^ handled) {
+        USB_LOG_ERR("Unhandled IRQ 0x%x\n", (uint)(status ^ handled));
+    }
+}
+
+void rp2040_usbh_irq(void)
+{
+    USBH_IRQHandler(0);
+}

+ 125 - 0
components/drivers/usb/cherryusb/port/template/usb_dc.c

@@ -0,0 +1,125 @@
+#include "usbd_core.h"
+
+/* Endpoint state */
+struct usb_dc_ep_state {
+    uint16_t ep_mps;    /* Endpoint max packet size */
+    uint8_t ep_type;    /* Endpoint type */
+    uint8_t ep_stalled; /* Endpoint stall flag */
+    uint8_t *xfer_buf;
+    uint32_t xfer_len;
+    uint32_t actual_xfer_len;
+};
+
+/* Driver state */
+struct xxx_udc {
+    volatile uint8_t dev_addr;
+    struct usb_dc_ep_state in_ep[CONFIG_USBDEV_EP_NUM];  /*!< IN endpoint parameters*/
+    struct usb_dc_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
+} g_xxx_udc;
+
+__WEAK void usb_dc_low_level_init(void)
+{
+}
+
+__WEAK void usb_dc_low_level_deinit(void)
+{
+}
+
+int usb_dc_init(uint8_t busid)
+{
+    memset(&g_xxx_udc, 0, sizeof(struct xxx_udc));
+
+    usb_dc_low_level_init();
+    return 0;
+}
+
+int usb_dc_deinit(uint8_t busid)
+{
+    return 0;
+}
+
+int usbd_set_address(uint8_t busid, const uint8_t addr)
+{
+    return 0;
+}
+
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
+uint8_t usbd_get_port_speed(uint8_t busid)
+{
+    return USB_SPEED_FULL;
+}
+
+int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
+
+    if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
+        g_xxx_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_xxx_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        g_xxx_udc.out_ep[ep_idx].ep_enable = true;
+    } else {
+        g_xxx_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
+        g_xxx_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
+        g_xxx_udc.in_ep[ep_idx].ep_enable = true;
+    }
+    return 0;
+}
+
+int usbd_ep_close(uint8_t busid, const uint8_t ep)
+{
+    return 0;
+}
+
+int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
+{
+    return 0;
+}
+
+int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
+{
+    return 0;
+}
+
+int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
+{
+    return 0;
+}
+
+int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    uint32_t tmp;
+
+    if (!data && data_len) {
+        return -1;
+    }
+
+    g_xxx_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_xxx_udc.in_ep[ep_idx].xfer_len = data_len;
+    g_xxx_udc.in_ep[ep_idx].actual_xfer_len = 0;
+
+    return 0;
+}
+
+int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!data && data_len) {
+        return -1;
+    }
+
+    g_xxx_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
+    g_xxx_udc.out_ep[ep_idx].xfer_len = data_len;
+    g_xxx_udc.out_ep[ep_idx].actual_xfer_len = 0;
+
+    return 0;
+}
+
+void USBD_IRQHandler(uint8_t busid)
+{
+}

+ 133 - 0
components/drivers/usb/cherryusb/port/template/usb_hc.c

@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_hub.h"
+
+int usb_hc_init(struct usbh_bus *bus)
+{
+    return 0;
+}
+
+int usb_hc_deinit(struct usbh_bus *bus)
+{
+    return 0;
+}
+
+uint16_t usbh_get_frame_number(struct usbh_bus *bus)
+{
+    return 0;
+}
+
+int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
+{
+    uint8_t nports;
+    uint8_t port;
+    uint32_t status;
+
+    nports = CONFIG_USBHOST_MAX_RHPORTS;
+    port = setup->wIndex;
+    if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
+        switch (setup->bRequest) {
+            case HUB_REQUEST_CLEAR_FEATURE:
+                switch (setup->wValue) {
+                    case HUB_FEATURE_HUB_C_LOCALPOWER:
+                        break;
+                    case HUB_FEATURE_HUB_C_OVERCURRENT:
+                        break;
+                    default:
+                        return -USB_ERR_NOTSUPP;
+                }
+                break;
+            case HUB_REQUEST_SET_FEATURE:
+                switch (setup->wValue) {
+                    case HUB_FEATURE_HUB_C_LOCALPOWER:
+                        break;
+                    case HUB_FEATURE_HUB_C_OVERCURRENT:
+                        break;
+                    default:
+                        return -USB_ERR_NOTSUPP;
+                }
+                break;
+            case HUB_REQUEST_GET_DESCRIPTOR:
+                break;
+            case HUB_REQUEST_GET_STATUS:
+                memset(buf, 0, 4);
+                break;
+            default:
+                break;
+        }
+    } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
+        switch (setup->bRequest) {
+            case HUB_REQUEST_CLEAR_FEATURE:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                switch (setup->wValue) {
+                    case HUB_PORT_FEATURE_ENABLE:
+                        break;
+                    case HUB_PORT_FEATURE_SUSPEND:
+                        break;
+                    case HUB_PORT_FEATURE_C_SUSPEND:
+                        break;
+                    case HUB_PORT_FEATURE_POWER:
+                        break;
+                    case HUB_PORT_FEATURE_C_CONNECTION:
+                        break;
+                    case HUB_PORT_FEATURE_C_ENABLE:
+                        break;
+                    case HUB_PORT_FEATURE_C_OVER_CURREN:
+                        break;
+                    case HUB_PORT_FEATURE_C_RESET:
+                        break;
+                    default:
+                        return -USB_ERR_NOTSUPP;
+                }
+                break;
+            case HUB_REQUEST_SET_FEATURE:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                switch (setup->wValue) {
+                    case HUB_PORT_FEATURE_SUSPEND:
+                        break;
+                    case HUB_PORT_FEATURE_POWER:
+                        break;
+                    case HUB_PORT_FEATURE_RESET:
+                        break;
+
+                    default:
+                        return -USB_ERR_NOTSUPP;
+                }
+                break;
+            case HUB_REQUEST_GET_STATUS:
+                if (!port || port > nports) {
+                    return -USB_ERR_INVAL;
+                }
+
+                memcpy(buf, &status, 4);
+                break;
+            default:
+                break;
+        }
+    }
+    return 0;
+}
+
+int usbh_submit_urb(struct usbh_urb *urb)
+{
+    return -USB_ERR_NOTSUPP;
+}
+
+int usbh_kill_urb(struct usbh_urb *urb)
+{
+    return -USB_ERR_NOTSUPP;
+}
+
+void USBH_IRQHandler(uint8_t busid)
+{
+}