Browse Source

update(cherryusb): update to v1.4.2

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu 4 months ago
parent
commit
243854a353
81 changed files with 1413 additions and 507 deletions
  1. 0 0
      components/drivers/usb/cherryusb/CherryUSB.svg
  2. 4 0
      components/drivers/usb/cherryusb/Kconfig
  3. 17 5
      components/drivers/usb/cherryusb/README.md
  4. 17 5
      components/drivers/usb/cherryusb/README_zh.md
  5. 6 0
      components/drivers/usb/cherryusb/SConscript
  6. 1 1
      components/drivers/usb/cherryusb/VERSION
  7. 9 0
      components/drivers/usb/cherryusb/cherryusb.cmake
  8. 3 0
      components/drivers/usb/cherryusb/cherryusb_config_template.h
  9. 48 0
      components/drivers/usb/cherryusb/class/aoa/usb_aoa.h
  10. 289 0
      components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c
  11. 40 0
      components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h
  12. 12 0
      components/drivers/usb/cherryusb/class/audio/usb_audio.h
  13. 25 17
      components/drivers/usb/cherryusb/class/audio/usbd_audio.c
  14. 1 1
      components/drivers/usb/cherryusb/class/audio/usbd_audio.h
  15. 142 37
      components/drivers/usb/cherryusb/class/audio/usbh_audio.c
  16. 6 2
      components/drivers/usb/cherryusb/class/audio/usbh_audio.h
  17. 2 2
      components/drivers/usb/cherryusb/class/cdc/usb_cdc.h
  18. 56 34
      components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c
  19. 4 10
      components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h
  20. 6 6
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c
  21. 3 3
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c
  22. 3 3
      components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c
  23. 3 3
      components/drivers/usb/cherryusb/class/hid/usbh_hid.c
  24. 3 3
      components/drivers/usb/cherryusb/class/hub/usbh_hub.c
  25. 3 3
      components/drivers/usb/cherryusb/class/msc/usbh_msc.c
  26. 3 3
      components/drivers/usb/cherryusb/class/template/usbh_xxx.c
  27. 3 3
      components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c
  28. 3 3
      components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c
  29. 3 3
      components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c
  30. 3 3
      components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c
  31. 3 3
      components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c
  32. 3 3
      components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c
  33. 3 3
      components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c
  34. 3 3
      components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c
  35. 96 55
      components/drivers/usb/cherryusb/class/video/usbd_video.c
  36. 1 3
      components/drivers/usb/cherryusb/class/video/usbd_video.h
  37. 6 6
      components/drivers/usb/cherryusb/class/video/usbh_video.c
  38. 12 1
      components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c
  39. 2 1
      components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h
  40. 6 6
      components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c
  41. 3 3
      components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c
  42. 2 0
      components/drivers/usb/cherryusb/common/usb_log.h
  43. 2 2
      components/drivers/usb/cherryusb/common/usb_version.h
  44. 16 7
      components/drivers/usb/cherryusb/core/usbd_core.c
  45. 55 4
      components/drivers/usb/cherryusb/core/usbh_core.c
  46. 4 3
      components/drivers/usb/cherryusb/core/usbh_core.h
  47. 5 4
      components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c
  48. 7 3
      components/drivers/usb/cherryusb/demo/cdc_ecm_template.c
  49. 8 4
      components/drivers/usb/cherryusb/demo/cdc_rndis_template.c
  50. 4 3
      components/drivers/usb/cherryusb/demo/hid_keyboard_template.c
  51. 5 4
      components/drivers/usb/cherryusb/demo/hid_mouse_template.c
  52. 5 4
      components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c
  53. 29 6
      components/drivers/usb/cherryusb/demo/usb_host.c
  54. 13 35
      components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c
  55. 9 29
      components/drivers/usb/cherryusb/demo/video_static_h264_template.c
  56. 3 28
      components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c
  57. 9 32
      components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c
  58. 4 3
      components/drivers/usb/cherryusb/demo/webusb_hid_template.c
  59. 25 0
      components/drivers/usb/cherryusb/idf_component.yml
  60. 0 4
      components/drivers/usb/cherryusb/platform/rtthread/usb_check.c
  61. 5 0
      components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c
  62. 5 0
      components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c
  63. 11 0
      components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c
  64. 5 0
      components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c
  65. 5 0
      components/drivers/usb/cherryusb/port/dwc2/README.md
  66. 9 7
      components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c
  67. 5 0
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c
  68. 4 0
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c
  69. 4 0
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c
  70. 7 1
      components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c
  71. 17 19
      components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c
  72. 8 3
      components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c
  73. 5 0
      components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c
  74. 4 1
      components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c
  75. 2 1
      components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c
  76. 2 4
      components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c
  77. 9 4
      components/drivers/usb/cherryusb/port/ohci/README.md
  78. 45 0
      components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c
  79. 157 44
      components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c
  80. 32 0
      components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h
  81. 11 11
      components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h

File diff suppressed because it is too large
+ 0 - 0
components/drivers/usb/cherryusb/CherryUSB.svg


+ 4 - 0
components/drivers/usb/cherryusb/Kconfig

@@ -38,6 +38,8 @@ if RT_USING_CHERRYUSB
                 bool "dwc2_gd"
             config RT_CHERRYUSB_DEVICE_DWC2_HC
                 bool "dwc2_hc"
+            config RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE
+                bool "dwc2_kendryte"
             config RT_CHERRYUSB_DEVICE_DWC2_CUSTOM
                 bool "dwc2_custom"
             config RT_CHERRYUSB_DEVICE_MUSB_ES
@@ -182,6 +184,8 @@ if RT_USING_CHERRYUSB
                 bool "dwc2_st"
             config RT_CHERRYUSB_HOST_DWC2_ESP
                 bool "dwc2_esp"
+            config RT_CHERRYUSB_HOST_DWC2_KENDRYTE
+                bool "dwc2_kendryte"
             config RT_CHERRYUSB_HOST_DWC2_CUSTOM
                 bool "dwc2_custom"
             config RT_CHERRYUSB_HOST_MUSB_ES

+ 17 - 5
components/drivers/usb/cherryusb/README.md

@@ -1,6 +1,16 @@
-# CherryUSB
-
-[中文版](./README_zh.md)
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
+<p align="center">
+	<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
+	<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
+    <a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
+    <a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
+</p>
+
+<p align="center">
+    <a href="./README_zh.md">中文</a>
+    |
+    <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.
 
@@ -103,6 +113,7 @@ CherryUSB Host Stack has the following functions:
 - Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
 - Support Vendor class (serial, net, wifi)
 - Support USB modeswitch
+- Support Android Open Accessory
 - Support multi host with the same USB IP
 
 The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
@@ -149,7 +160,7 @@ Only standard and commercial USB IP are listed.
 
 |   IP             |  device    | host     | Support status |
 |:----------------:|:----------:|:--------:|:--------------:|
-|  OHCI(intel)     |  none      | OHCI     |  ×   |
+|  OHCI(intel)     |  none      | OHCI     |     |
 |  EHCI(intel)     |  none      | EHCI     |  √   |
 |  XHCI(intel)     |  none      | XHCI     |  √   |
 |  UHCI(intel)     |  none      | UHCI     |  ×   |
@@ -186,6 +197,7 @@ 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 |
 |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 |
@@ -212,4 +224,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
 
 Thanks to the following companies for their support (in no particular order).
 
-<img src="docs/assets/bouffalolab.jpg"  width="100" height="80"/> <img src="docs/assets/hpmicro.jpg"  width="100" height="80" /> <img src="docs/assets/eastsoft.jpg"  width="100" height="80" /> <img src="docs/assets/rtthread.jpg"  width="100" height="80" /> <img src="docs/assets/sophgo.jpg"  width="100" height="80" /> <img src="docs/assets/phytium.jpg"  width="100" height="80" /> <img src="docs/assets/thead.jpg"  width="100" height="80" /> <img src="docs/assets/nuvoton.jpg"  width="100" height="80" /> <img src="docs/assets/artinchip.jpg"  width="100" height="80" /> <img src="docs/assets/bekencorp.jpg"  width="100" height="80" /> <img src="docs/assets/nxp.png"  width="100" height="80" /> <img src="docs/assets/espressif.png"  width="100" height="80" />
+<img src="docs/assets/bouffalolab.jpg"  width="100" height="80"/> <img src="docs/assets/hpmicro.jpg"  width="100" height="80" /> <img src="docs/assets/eastsoft.jpg"  width="100" height="80" /> <img src="docs/assets/rtthread.jpg"  width="100" height="80" /> <img src="docs/assets/sophgo.jpg"  width="100" height="80" /> <img src="docs/assets/phytium.jpg"  width="100" height="80" /> <img src="docs/assets/thead.jpg"  width="100" height="80" /> <img src="docs/assets/nuvoton.jpg"  width="100" height="80" /> <img src="docs/assets/artinchip.jpg"  width="100" height="80" /> <img src="docs/assets/bekencorp.jpg"  width="100" height="80" /> <img src="docs/assets/nxp.png"  width="100" height="80" /> <img src="docs/assets/espressif.png"  width="100" height="80" /> <img src="docs/assets/canaan.jpg"  width="100" height="80" />

+ 17 - 5
components/drivers/usb/cherryusb/README_zh.md

@@ -1,6 +1,16 @@
-# CherryUSB
-
-[English](./README.md)
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
+<p align="center">
+	<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
+	<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
+    <a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
+    <a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
+</p>
+
+<p align="center">
+    <a href="./README_zh.md">中文</a>
+    |
+    <a href="./README.md">English</a>
+</p>
 
 CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
 
@@ -103,6 +113,7 @@ CherryUSB Host 协议栈当前实现以下功能:
 - 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
 - 支持 Vendor 类 class (serial, net, wifi)
 - 支持 USB modeswitch
+- 支持 Android Open Accessory
 - 支持相同 USB IP 的多主机
 
 同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
@@ -149,7 +160,7 @@ x 受以下宏影响:
 
 |   IP             |  device    | host     | Support status |
 |:----------------:|:----------:|:--------:|:--------------:|
-|  OHCI(intel)     |  none      | OHCI     |  ×   |
+|  OHCI(intel)     |  none      | OHCI     |     |
 |  EHCI(intel)     |  none      | EHCI     |  √   |
 |  XHCI(intel)     |  none      | XHCI     |  √   |
 |  UHCI(intel)     |  none      | UHCI     |  ×   |
@@ -187,6 +198,7 @@ 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 |
 |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 |
@@ -214,4 +226,4 @@ CherryUSB 微信群:与我联系后邀请加入
 
 感谢以下企业支持(顺序不分先后)。
 
-<img src="docs/assets/bouffalolab.jpg"  width="100" height="80"/> <img src="docs/assets/hpmicro.jpg"  width="100" height="80" /> <img src="docs/assets/eastsoft.jpg"  width="100" height="80" /> <img src="docs/assets/rtthread.jpg"  width="100" height="80" /> <img src="docs/assets/sophgo.jpg"  width="100" height="80" /> <img src="docs/assets/phytium.jpg"  width="100" height="80" /> <img src="docs/assets/thead.jpg"  width="100" height="80" /> <img src="docs/assets/nuvoton.jpg"  width="100" height="80" /> <img src="docs/assets/artinchip.jpg"  width="100" height="80" /> <img src="docs/assets/bekencorp.jpg"  width="100" height="80" /> <img src="docs/assets/nxp.png"  width="100" height="80" /> <img src="docs/assets/espressif.png"  width="100" height="80" />
+<img src="docs/assets/bouffalolab.jpg"  width="100" height="80"/> <img src="docs/assets/hpmicro.jpg"  width="100" height="80" /> <img src="docs/assets/eastsoft.jpg"  width="100" height="80" /> <img src="docs/assets/rtthread.jpg"  width="100" height="80" /> <img src="docs/assets/sophgo.jpg"  width="100" height="80" /> <img src="docs/assets/phytium.jpg"  width="100" height="80" /> <img src="docs/assets/thead.jpg"  width="100" height="80" /> <img src="docs/assets/nuvoton.jpg"  width="100" height="80" /> <img src="docs/assets/artinchip.jpg"  width="100" height="80" /> <img src="docs/assets/bekencorp.jpg"  width="100" height="80" /> <img src="docs/assets/nxp.png"  width="100" height="80" /> <img src="docs/assets/espressif.png"  width="100" height="80" /> <img src="docs/assets/canaan.jpg"  width="100" height="80" />

+ 6 - 0
components/drivers/usb/cherryusb/SConscript

@@ -45,6 +45,9 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
     if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_HC']):
         src += Glob('port/dwc2/usb_dc_dwc2.c')
         src += Glob('port/dwc2/usb_glue_hc.c')
+    if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE']):
+        src += Glob('port/dwc2/usb_dc_dwc2.c')
+        src += Glob('port/dwc2/usb_glue_kendryte.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_CUSTOM']):
         src += Glob('port/dwc2/usb_dc_dwc2.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_MUSB_ES']):
@@ -177,6 +180,9 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
     if GetDepend(['RT_CHERRYUSB_HOST_DWC2_ESP']):
         src += Glob('port/dwc2/usb_hc_dwc2.c')
         src += Glob('port/dwc2/usb_glue_esp.c')
+    if GetDepend(['RT_CHERRYUSB_HOST_DWC2_KENDRYTE']):
+        src += Glob('port/dwc2/usb_hc_dwc2.c')
+        src += Glob('port/dwc2/usb_glue_kendryte.c')
     if GetDepend(['RT_CHERRYUSB_HOST_DWC2_CUSTOM']):
         src += Glob('port/dwc2/usb_hc_dwc2.c')
     if GetDepend(['RT_CHERRYUSB_HOST_MUSB_STANDARD']):

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

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

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

@@ -40,6 +40,7 @@ ${CMAKE_CURRENT_LIST_DIR}/class/adb
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
 ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
+${CMAKE_CURRENT_LIST_DIR}/class/aoa
 )
 
 if(CONFIG_CHERRYUSB_DEVICE)
@@ -218,6 +219,9 @@ if(CONFIG_CHERRYUSB_HOST)
     if(CONFIG_CHERRYUSB_HOST_BL616)
     list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
     endif()
+    if(CONFIG_CHERRYUSB_HOST_AOA)
+    list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c)
+    endif()
 
     if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
         if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
@@ -294,4 +298,9 @@ endif()
 if(CONFIG_CHERRYMP)
 list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c)
 list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
+    if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
+    list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c)
+    elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
+    list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c)
+    endif()
 endif()

+ 3 - 0
components/drivers/usb/cherryusb/cherryusb_config_template.h

@@ -208,6 +208,9 @@
 #define CONFIG_USBDEV_EP_NUM 8
 #endif
 
+/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */
+// #define CONFIG_USB_HS
+
 /* ---------------- FSDEV Configuration ---------------- */
 //#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
 

+ 48 - 0
components/drivers/usb/cherryusb/class/aoa/usb_aoa.h

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_AOA_H
+#define USB_AOA_H
+
+//AOA 1.0
+#define AOA_ACCESSORY_VENDOR_ID      0x18D1
+#define AOA_ACCESSORY_PRODUCT_ID     0x2D00
+#define AOA_ACCESSORY_ADB_PRODUCT_ID 0x2D01
+
+//AOA 2.0
+#define AOA_AUDIO_PRODUCT_ID               0x2D02
+#define AOA_AUDIO_ADB_PRODUCT_ID           0x2D03
+#define AOA_ACCESSORY_AUDIO_PRODUCT_ID     0x2D04
+#define AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID 0x2D05
+
+//AOA 1.0
+#define AOA_ACCESSORY_GET_PROTOCOL 51
+#define AOA_ACCESSORY_SEND_STRING  52
+#define AOA_ACCESSORY_START        53
+
+//AOA 2.0
+#define AOA_ACCESSORY_REGISTER_HID        54
+#define AOA_ACCESSORY_UNREGISTER_HID      55
+#define AOA_ACCESSORY_SET_HID_REPORT_DESC 56
+#define AOA_ACCESSORY_SEND_HID_EVENT      57
+#define AOA_ACCESSORY_SET_AUDIO_MODE      58
+
+#define AOA_ACCESSORY_STRING_MANUFACTURER 0
+#define AOA_ACCESSORY_STRING_MODEL        1
+#define AOA_ACCESSORY_STRING_DESCRIPTION  2
+#define AOA_ACCESSORY_STRING_VERSION      3
+#define AOA_ACCESSORY_STRING_URI          4
+#define AOA_ACCESSORY_STRING_SERIAL       5
+
+struct aoa_string_info {
+    char acc_manufacturer[64];
+    char acc_model[64];
+    char acc_description[64];
+    char acc_version[64];
+    char acc_uri[64];
+    char acc_serial[64];
+};
+
+#endif /* USB_AOA_H */

+ 289 - 0
components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c

@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_aoa.h"
+
+#undef USB_DBG_TAG
+#define USB_DBG_TAG "usbh_aoa"
+#include "usb_log.h"
+
+#define DEV_FORMAT "/dev/aoa"
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_aoa_buffer[128];
+
+static struct usbh_aoa g_aoa_class;
+
+int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info)
+{
+    struct usb_setup_packet *setup;
+    int ret;
+
+    setup = hport->setup;
+
+    if (setup == NULL) {
+        return -USB_ERR_INVAL;
+    }
+
+    USB_LOG_INFO("Try switch into aoa mode\r\n");
+
+    setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_GET_PROTOCOL;
+    setup->wValue = 0;
+    setup->wIndex = 0;
+    setup->wLength = 2;
+
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    USB_LOG_INFO("AOA version: v%d.%d\r\n", g_aoa_buffer[0], g_aoa_buffer[1]);
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_MANUFACTURER;
+    setup->wLength = strlen(info->acc_manufacturer) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_manufacturer, strlen(info->acc_manufacturer));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_MODEL;
+    setup->wLength = strlen(info->acc_model) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_model, strlen(info->acc_model));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_DESCRIPTION;
+    setup->wLength = strlen(info->acc_description) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_description, strlen(info->acc_description));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_VERSION;
+    setup->wLength = strlen(info->acc_version) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_version, strlen(info->acc_version));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_URI;
+    setup->wLength = strlen(info->acc_uri) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_uri, strlen(info->acc_uri));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_STRING;
+    setup->wValue = 0;
+    setup->wIndex = AOA_ACCESSORY_STRING_SERIAL;
+    setup->wLength = strlen(info->acc_serial) + 1;
+
+    memcpy(g_aoa_buffer, info->acc_serial, strlen(info->acc_serial));
+    ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
+    if (ret < 0) {
+        return ret;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_START;
+    setup->wValue = 0;
+    setup->wIndex = 0;
+    setup->wLength = 0;
+
+    ret = usbh_control_transfer(hport, setup, NULL);
+    if (ret < 0) {
+        return ret;
+    }
+
+    USB_LOG_INFO("Switch into aoa mode success, wait usb device restart...\r\n");
+    return 0;
+}
+
+int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len)
+{
+    struct usb_setup_packet *setup;
+    int ret;
+    uint8_t len;
+    uint32_t offset;
+
+    if (!aoa_class || !aoa_class->hport) {
+        return -USB_ERR_INVAL;
+    }
+    setup = aoa_class->hport->setup;
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_REGISTER_HID;
+    setup->wValue = id;
+    setup->wIndex = report_len;
+    setup->wLength = 0;
+
+    ret = usbh_control_transfer(aoa_class->hport, setup, NULL);
+    if (ret < 0) {
+        return ret;
+    }
+
+    offset = 0;
+    while (report_len > 0) {
+        len = report_len > 64 ? 64 : report_len;
+
+        setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+        setup->bRequest = AOA_ACCESSORY_SET_HID_REPORT_DESC;
+        setup->wValue = id;
+        setup->wIndex = offset;
+        setup->wLength = len;
+
+        memcpy(g_aoa_buffer, report + offset, len);
+        ret = usbh_control_transfer(aoa_class->hport, setup, g_aoa_buffer);
+        if (ret < 0) {
+            return ret;
+        }
+        offset += len;
+        report_len -= len;
+    }
+    return ret;
+}
+
+int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len)
+{
+    struct usb_setup_packet *setup;
+    int ret;
+    uint8_t len;
+    uint32_t offset;
+
+    if (!aoa_class || !aoa_class->hport) {
+        return -USB_ERR_INVAL;
+    }
+    setup = aoa_class->hport->setup;
+
+    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
+    setup->bRequest = AOA_ACCESSORY_SEND_HID_EVENT;
+    setup->wValue = id;
+    setup->wIndex = 0;
+    setup->wLength = event_len;
+
+    memcpy(g_aoa_buffer, event, event_len);
+    return usbh_control_transfer(aoa_class->hport, setup, event);
+}
+
+static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+    struct usb_endpoint_descriptor *ep_desc;
+    int ret = 0;
+
+    struct usbh_aoa *aoa_class = &g_aoa_class;
+
+    memset(aoa_class, 0, sizeof(struct usbh_aoa));
+
+    aoa_class->hport = hport;
+    aoa_class->intf = intf;
+
+    hport->config.intf[intf].priv = aoa_class;
+
+    for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
+        ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
+
+        if (ep_desc->bEndpointAddress & 0x80) {
+            USBH_EP_INIT(aoa_class->bulkin, ep_desc);
+        } else {
+            USBH_EP_INIT(aoa_class->bulkout, ep_desc);
+        }
+    }
+
+    strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
+
+    USB_LOG_INFO("Register AOA Class:%s\r\n", hport->config.intf[intf].devname);
+
+    usbh_aoa_run(aoa_class);
+    return 0;
+}
+
+static int usbh_aoa_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+    int ret = 0;
+
+    struct usbh_aoa *aoa_class = (struct usbh_aoa *)hport->config.intf[intf].priv;
+
+    if (aoa_class) {
+        if (aoa_class->bulkin) {
+            usbh_kill_urb(&aoa_class->bulkin_urb);
+        }
+
+        if (aoa_class->bulkout) {
+            usbh_kill_urb(&aoa_class->bulkout_urb);
+        }
+
+        if (hport->config.intf[intf].devname[0] != '\0') {
+            USB_LOG_INFO("Unregister AOA Class:%s\r\n", hport->config.intf[intf].devname);
+            usbh_aoa_stop(aoa_class);
+        }
+
+        memset(aoa_class, 0, sizeof(struct usbh_aoa));
+    }
+
+    return ret;
+}
+
+__WEAK void usbh_aoa_run(struct usbh_aoa *aoa_class)
+{
+    (void)aoa_class;
+}
+
+__WEAK void usbh_aoa_stop(struct usbh_aoa *aoa_class)
+{
+    (void)aoa_class;
+}
+
+static const uint16_t aoa_id_table[][2] = {
+    { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_PRODUCT_ID },
+    { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_ADB_PRODUCT_ID },
+    { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_PRODUCT_ID },
+    { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_ADB_PRODUCT_ID },
+    { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_PRODUCT_ID },
+    { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID },
+    { 0, 0 },
+};
+
+const struct usbh_class_driver aoa_class_driver = {
+    .driver_name = "aoa",
+    .connect = usbh_aoa_connect,
+    .disconnect = usbh_aoa_disconnect
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info aoa_intf_class_info = {
+    .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0xff,
+    .bInterfaceProtocol = 0x00,
+    .id_table = aoa_id_table,
+    .class_driver = &aoa_class_driver
+};

+ 40 - 0
components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_AOA_H
+#define USBH_AOA_H
+
+#include "usb_aoa.h"
+
+struct usbh_aoa {
+    struct usbh_hubport *hport;
+    struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
+    struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
+
+    struct usbh_urb bulkout_urb;
+    struct usbh_urb bulkin_urb;
+
+    uint8_t intf;
+    uint8_t minor;
+
+    void *user_data;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info);
+int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len);
+int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len);
+
+void usbh_aoa_run(struct usbh_aoa *aoa_class);
+void usbh_aoa_stop(struct usbh_aoa *aoa_class);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_AOA_H */

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

@@ -648,6 +648,18 @@ struct audio_cs_if_ac_feature_unit_descriptor {
 
 #define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n)
 
+struct audio_cs_if_ac_selector_unit_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint8_t bUnitID;
+    uint8_t bNrInPins;
+    uint8_t baSourceID[1];
+    uint8_t iSelector;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n)
+
 struct audio_cs_if_as_general_descriptor {
     uint8_t bLength;
     uint8_t bDescriptorType;

+ 25 - 17
components/drivers/usb/cherryusb/class/audio/usbd_audio.c

@@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 memcpy(&volume, *data, *len);
                                 if (volume < 0x8000) {
                                     volume_db = volume / 256;
-                                } else if (volume > 0x8000) {
-                                    volume_db = (0xffff - volume + 1) / -256;
+                                } else {
+                                    volume_db = (volume - 0x10000) / 256;
                                 }
-                                volume_db += 128; /* 0 ~ 255 */
-                                USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
+                                USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
                                 usbd_audio_set_volume(busid, ep, ch, volume_db);
                                 break;
                             case AUDIO_REQUEST_GET_CUR:
                                 volume_db = usbd_audio_get_volume(busid, ep, ch);
-                                volume_db -= 128;
                                 if (volume_db >= 0) {
                                     volume = volume_db * 256;
                                 } else {
-                                    volume = volume_db * 256 + 0xffff + 1;
+                                    volume = volume_db * 256 + 0x10000;
                                 }
+                                USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
                                 memcpy(*data, &volume, 2);
                                 *len = 2;
                                 break;
                             case AUDIO_REQUEST_GET_MIN:
-                                (*data)[0] = 0x00; /* -2560/256 dB */
-                                (*data)[1] = 0xdb;
+                                (*data)[0] = 0x00; /* -100 dB */
+                                (*data)[1] = 0x9c;
                                 *len = 2;
                                 break;
                             case AUDIO_REQUEST_GET_MAX:
@@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 *len = 2;
                                 break;
                             case AUDIO_REQUEST_GET_RES:
-                                (*data)[0] = 0x00; /* -256/256 dB */
+                                (*data)[0] = 0x00; /* 1 dB */
                                 (*data)[1] = 0x01;
                                 *len = 2;
                                 break;
@@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                             case AUDIO_REQUEST_CUR:
                                 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
                                     volume_db = usbd_audio_get_volume(busid, ep, ch);
-                                    volume = volume_db;
+                                    if (volume_db >= 0) {
+                                        volume = volume_db * 256;
+                                    } else {
+                                        volume = volume_db * 256 + 0x10000;
+                                    }
+                                    USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
                                     memcpy(*data, &volume, 2);
                                     *len = 2;
                                 } else {
                                     memcpy(&volume, *data, *len);
-                                    volume_db = volume;
-                                    USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
+                                    if (volume < 0x8000) {
+                                        volume_db = volume / 256;
+                                    } else {
+                                        volume_db = (volume - 0x10000) / 256;
+                                    }
+                                    USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
                                     usbd_audio_set_volume(busid, ep, ch, volume_db);
                                 }
                                 break;
                             case AUDIO_REQUEST_RANGE:
                                 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
                                     *((uint16_t *)(*data + 0)) = 1;
-                                    *((uint16_t *)(*data + 2)) = 0;
-                                    *((uint16_t *)(*data + 4)) = 100;
-                                    *((uint16_t *)(*data + 6)) = 1;
+                                    *((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */
+                                    *((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */
+                                    *((uint16_t *)(*data + 6)) = 0x100;  /* RES 1 dB */
                                     *len = 8;
                                 } else {
                                 }
@@ -312,12 +320,12 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
     return intf;
 }
 
-__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
+__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db)
 {
     (void)busid;
     (void)ep;
     (void)ch;
-    (void)volume;
+    (void)volume_db;
 }
 
 __WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)

+ 1 - 1
components/drivers/usb/cherryusb/class/audio/usbd_audio.h

@@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface
 void usbd_audio_open(uint8_t busid, uint8_t intf);
 void usbd_audio_close(uint8_t busid, uint8_t intf);
 
-void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
+void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db);
 int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
 void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
 bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);

+ 142 - 37
components/drivers/usb/cherryusb/class/audio/usbh_audio.c

@@ -184,18 +184,21 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
     return ret;
 }
 
-int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
+int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db)
 {
     struct usb_setup_packet *setup;
     int ret;
     uint8_t feature_id = 0xff;
+    uint8_t intf;
     uint16_t volume_hex;
+    int volume_min_db;
+    int volume_max_db;
 
     if (!audio_class || !audio_class->hport) {
         return -USB_ERR_INVAL;
     }
 
-    if (volume > 100) {
+    if ((volume_db > 127) || (volume_db < -127)) {
         return -USB_ERR_INVAL;
     }
 
@@ -204,20 +207,102 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
     for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
         if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
             feature_id = audio_class->as_msg_table[i].feature_terminal_id;
+            intf = audio_class->as_msg_table[i].stream_intf;
         }
     }
 
+    if (feature_id == 0xff) {
+        return -USB_ERR_NODEV;
+    }
+
+    setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+    setup->bRequest = AUDIO_REQUEST_GET_CUR;
+    setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
+    setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
+    setup->wLength = 2;
+
+    ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
+    if (ret < 0) {
+        return ret;
+    }
+
+    memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2);
+
+    setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+    setup->bRequest = AUDIO_REQUEST_GET_MIN;
+    setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
+    setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
+    setup->wLength = 2;
+
+    ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
+    if (ret < 0) {
+        return ret;
+    }
+
+    memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2);
+
+    setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+    setup->bRequest = AUDIO_REQUEST_GET_MAX;
+    setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
+    setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
+    setup->wLength = 2;
+
+    ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
+    if (ret < 0) {
+        return ret;
+    }
+    memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2);
+
+    setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+    setup->bRequest = AUDIO_REQUEST_GET_RES;
+    setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
+    setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
+    setup->wLength = 2;
+
+    ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
+    if (ret < 0) {
+        return ret;
+    }
+    memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2);
+
     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
     setup->bRequest = AUDIO_REQUEST_SET_CUR;
     setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
     setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
     setup->wLength = 2;
 
-    volume_hex = -0xDB00 / 100 * volume + 0xdb00;
+    if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
+        volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
+    } else {
+        volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256;
+    }
+
+    if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) {
+        volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256;
+    } else {
+        volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256;
+    }
 
-    memcpy(g_audio_buf, &volume_hex, 2);
-    ret = usbh_control_transfer(audio_class->hport, setup, NULL);
+    USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db);
 
+    if (volume_db >= 0) {
+        volume_hex = volume_db * 256;
+        if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) {
+            return -USB_ERR_RANGE;
+        }
+    } else {
+        volume_hex = volume_db * 256 + 0x10000;
+        if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) {
+            return -USB_ERR_RANGE;
+        }
+    }
+
+    memcpy(g_audio_buf, &volume_hex, 2);
+    ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
+    if (ret < 0) {
+        return ret;
+    }
+    audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex;
     return ret;
 }
 
@@ -226,6 +311,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
     struct usb_setup_packet *setup;
     int ret;
     uint8_t feature_id = 0xff;
+    uint8_t intf = 0xff;
 
     if (!audio_class || !audio_class->hport) {
         return -USB_ERR_INVAL;
@@ -235,9 +321,14 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
     for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
         if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
             feature_id = audio_class->as_msg_table[i].feature_terminal_id;
+            intf = audio_class->as_msg_table[i].stream_intf;
         }
     }
 
+    if (feature_id == 0xff) {
+        return -USB_ERR_NODEV;
+    }
+
     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
     setup->bRequest = AUDIO_REQUEST_SET_CUR;
     setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
@@ -246,7 +337,10 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
 
     memcpy(g_audio_buf, &mute, 1);
     ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
-
+    if (ret < 0) {
+        return ret;
+    }
+    audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute;
     return ret;
 }
 
@@ -286,13 +380,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
 static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
 {
     int ret;
-    uint8_t cur_iface = 0xff;
-    uint8_t cur_iface_count = 0xff;
-    uint8_t cur_alt_setting = 0xff;
+    uint8_t cur_iface = 0;
+    uint8_t cur_iface_count = 0;
+    uint8_t cur_alt_setting = 0;
     uint8_t input_offset = 0;
     uint8_t output_offset = 0;
     uint8_t feature_unit_offset = 0;
     uint8_t *p;
+    struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
 
     struct usbh_audio *audio_class = usbh_audio_class_alloc();
     if (audio_class == NULL) {
@@ -327,26 +422,24 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                         case AUDIO_CONTROL_INPUT_TERMINAL: {
                             struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p;
 
-                            memcpy(&audio_class->ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor));
+                            memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor));
                             input_offset++;
                         } break;
                         case AUDIO_CONTROL_OUTPUT_TERMINAL: {
                             struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p;
 
-                            memcpy(&audio_class->ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor));
+                            memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor));
                             output_offset++;
                         } break;
                         case AUDIO_CONTROL_FEATURE_UNIT: {
                             struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p;
 
-                            memcpy(&audio_class->ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
+                            memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
                             feature_unit_offset++;
                         } break;
-                        case AUDIO_CONTROL_PROCESSING_UNIT:
-
-                            break;
                         default:
-                            break;
+                            USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]);
+                            return -USB_ERR_NOTSUPP;
                     }
                 } else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
                     switch (p[DESC_bDescriptorSubType]) {
@@ -383,7 +476,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
     }
 
     if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) {
-        USB_LOG_ERR("Audio descriptor is invalid\r\n");
+        USB_LOG_ERR("Audio control descriptor is invalid\r\n");
+        return -USB_ERR_INVAL;
+    }
+
+    if (cur_iface_count == 0xff) {
+        USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n");
         return -USB_ERR_INVAL;
     }
 
@@ -392,21 +490,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
     for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
         /* Search 0x0101 in input or output desc */
         for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) {
-            if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_input.bTerminalID) {
+            if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) {
                 /* INPUT --> FEATURE UNIT --> OUTPUT */
-                audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[streamidx].ac_input.bTerminalID;
+                audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID;
 
                 /* Search input terminal id in feature desc */
                 for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
-                    if (audio_class->ac_msg_table[streamidx].ac_input.bTerminalID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID) {
-                        audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID;
+                    if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) {
+                        audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
 
                         /* Search feature unit id in output desc */
                         for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) {
-                            if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID == audio_class->ac_msg_table[outputid].ac_output.bSourceID) {
-                                audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[outputid].ac_output.bTerminalID;
+                            if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) {
+                                audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID;
 
-                                switch (audio_class->ac_msg_table[outputid].ac_output.wTerminalType) {
+                                switch (ac_msg_table[outputid].ac_output.wTerminalType) {
                                     case AUDIO_OUTTERM_SPEAKER:
                                         audio_class->as_msg_table[i].stream_name = "speaker";
                                         break;
@@ -426,21 +524,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                         break;
                     }
                 }
-            } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_output.bTerminalID) {
+            } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) {
                 /* OUTPUT --> FEATURE UNIT --> INPUT */
-                audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[streamidx].ac_output.bTerminalID;
+                audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID;
 
                 /* Search output terminal id in feature desc */
                 for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
-                    if (audio_class->ac_msg_table[streamidx].ac_output.bSourceID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID) {
-                        audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID;
+                    if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) {
+                        audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
 
                         /* Search feature unit id in input desc */
                         for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) {
-                            if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID == audio_class->ac_msg_table[inputid].ac_input.bTerminalID) {
-                                audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[inputid].ac_input.bTerminalID;
+                            if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) {
+                                audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID;
 
-                                switch (audio_class->ac_msg_table[inputid].ac_input.wTerminalType) {
+                                switch (ac_msg_table[inputid].ac_input.wTerminalType) {
                                     case AUDIO_INTERM_MIC:
                                         audio_class->as_msg_table[i].stream_name = "mic";
                                         break;
@@ -458,6 +556,13 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
         }
     }
 
+    for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
+        if (audio_class->as_msg_table[i].stream_name == NULL) {
+            USB_LOG_ERR("Audio stream search fail\r\n");
+            return -USB_ERR_NODEV;
+        }
+    }
+
     for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
         ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name);
         if (ret < 0) {
@@ -537,18 +642,18 @@ const struct usbh_class_driver audio_streaming_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
-    .class = USB_DEVICE_CLASS_AUDIO,
-    .subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
-    .protocol = 0x00,
+    .bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
+    .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL,
+    .bInterfaceProtocol = 0x00,
     .id_table = NULL,
     .class_driver = &audio_ctrl_class_driver
 };
 
 CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
-    .class = USB_DEVICE_CLASS_AUDIO,
-    .subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
-    .protocol = 0x00,
+    .bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
+    .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING,
+    .bInterfaceProtocol = 0x00,
     .id_table = NULL,
     .class_driver = &audio_streaming_class_driver
 };

+ 6 - 2
components/drivers/usb/cherryusb/class/audio/usbh_audio.h

@@ -26,6 +26,11 @@ struct usbh_audio_as_msg {
     uint8_t output_terminal_id;
     uint8_t ep_attr;
     uint8_t num_of_altsetting;
+    uint16_t volume_min;
+    uint16_t volume_max;
+    uint16_t volume_res;
+    uint16_t volume_cur;
+    bool mute;
     struct audio_cs_if_as_general_descriptor as_general;
     struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
 };
@@ -43,7 +48,6 @@ struct usbh_audio {
     uint16_t bcdADC;
     uint8_t bInCollection;
     uint8_t stream_intf_num;
-    struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
     struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
 
     void *user_data;
@@ -55,7 +59,7 @@ extern "C" {
 
 int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution);
 int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
-int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
+int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db);
 int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
 
 void usbh_audio_run(struct usbh_audio *audio_class);

+ 2 - 2
components/drivers/usb/cherryusb/class/cdc/usb_cdc.h

@@ -524,7 +524,7 @@ struct cdc_ncm_ndp16 {
     int_ep,                                                /* bEndpointAddress */              \
     0x03,                                                  /* bmAttributes */                  \
     0x08, 0x00,                                            /* wMaxPacketSize */                \
-    0x10,                                                  /* bInterval */                     \
+    0x05,                                                  /* bInterval */                     \
     0x09,                                                  /* bLength */                       \
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
@@ -596,7 +596,7 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
     int_ep,                                                /* bEndpointAddress */              \
     0x03,                                                  /* bmAttributes */                  \
     0x10, 0x00,                                            /* wMaxPacketSize */                \
-    0x10,                                                  /* bInterval */                     \
+    0x05,                                                  /* bInterval */                     \
     0x09,                                                  /* bLength */                       \
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \

+ 56 - 34
components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c

@@ -7,17 +7,21 @@
 #include "usbd_cdc_ecm.h"
 
 #define CDC_ECM_OUT_EP_IDX 0
-#define CDC_ECM_IN_EP_IDX   1
-#define CDC_ECM_INT_EP_IDX  2
+#define CDC_ECM_IN_EP_IDX  1
+#define CDC_ECM_INT_EP_IDX 2
+
+/* Ethernet Maximum Segment size, typically 1514 bytes */
+#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1536U
 
 /* Describe EndPoints configuration */
 static struct usbd_endpoint cdc_ecm_ep_data[3];
 
+#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
+#endif
 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
 
-volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
 volatile uint32_t g_cdc_ecm_rx_data_length = 0;
 volatile uint32_t g_cdc_ecm_tx_data_length = 0;
 
@@ -68,8 +72,10 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed
             break;
     }
 
-    if (bytes2send) {
-        usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
+    if (usb_device_is_configured(0)) {
+        if (bytes2send) {
+            usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
+        }
     }
 }
 
@@ -93,11 +99,11 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
              * bit3 Broadcast
              * bit4 Multicast
             */
-            if (g_current_net_status == 0) {
-                g_current_net_status = 1;
-                usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
-            }
-
+#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
+            g_connect_speed_table[0] = 100000000; /* 100 Mbps */
+            g_connect_speed_table[1] = 100000000; /* 100 Mbps */
+            usbd_cdc_ecm_set_connect(true, g_connect_speed_table);
+#endif
             break;
         default:
             USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
@@ -117,10 +123,11 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
             g_current_net_status = 0;
             g_cdc_ecm_rx_data_length = 0;
             g_cdc_ecm_tx_data_length = 0;
-            g_cdc_ecm_rx_data_buffer = NULL;
             break;
         case USBD_EVENT_CONFIGURED:
-            usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
+#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
+            usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
+#endif
             break;
 
         default:
@@ -132,14 +139,8 @@ void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
     (void)busid;
 
-    g_cdc_ecm_rx_data_length += nbytes;
-
-    if (nbytes < usbd_get_ep_mps(0, ep)) {
-        g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
-        usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
-    } else {
-        usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep));
-    }
+    g_cdc_ecm_rx_data_length = nbytes;
+    usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_data_length);
 }
 
 void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
@@ -150,6 +151,7 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
         /* send zlp */
         usbd_ep_start_write(0, ep, NULL, 0);
     } else {
+        usbd_cdc_ecm_data_send_done(g_cdc_ecm_tx_data_length);
         g_cdc_ecm_tx_data_length = 0;
     }
 }
@@ -160,14 +162,20 @@ void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
     (void)ep;
     (void)nbytes;
 
-    if (g_current_net_status == 1) {
-        g_current_net_status = 2;
-        usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
+    if (g_current_net_status == 2) {
+        g_current_net_status = 3;
+        usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE, 0, g_connect_speed_table);
+    } else {
+        g_current_net_status = 0;
     }
 }
 
 int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
 {
+    if (!usb_device_is_configured(0)) {
+        return -USB_ERR_NODEV;
+    }
+
     if (g_cdc_ecm_tx_data_length > 0) {
         return -USB_ERR_BUSY;
     }
@@ -175,14 +183,17 @@ int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
     g_cdc_ecm_tx_data_length = len;
 
     USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
-    return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
+    return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, len);
 }
 
-void usbd_cdc_ecm_start_read_next(void)
+int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len)
 {
+    if (!usb_device_is_configured(0)) {
+        return -USB_ERR_NODEV;
+    }
+
     g_cdc_ecm_rx_data_length = 0;
-    g_cdc_ecm_rx_data_buffer = NULL;
-    usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, usbd_get_ep_mps(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
+    return usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, buf, len);
 }
 
 #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
@@ -190,19 +201,19 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
 {
     struct pbuf *p;
 
-    if (g_cdc_ecm_rx_data_buffer == NULL) {
+    if (g_cdc_ecm_rx_data_length == 0) {
         return NULL;
     }
     p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
     if (p == NULL) {
-        usbd_cdc_ecm_start_read_next();
+        usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
         return NULL;
     }
     usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
     p->len = g_cdc_ecm_rx_data_length;
 
     USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
-    usbd_cdc_ecm_start_read_next();
+    usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
     return p;
 }
 
@@ -250,13 +261,24 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const
     return intf;
 }
 
-void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
+void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2])
+{
+    if (connect) {
+        g_current_net_status = 2;
+        memcpy(g_connect_speed_table, speed, 8);
+        usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
+    } else {
+        g_current_net_status = 1;
+        usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_DISCONNECTED, NULL);
+    }
+}
+
+__WEAK void usbd_cdc_ecm_data_recv_done(uint32_t len)
 {
-    memcpy(g_connect_speed_table, speed, 8);
+    (void)len;
 }
 
-__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
+__WEAK void usbd_cdc_ecm_data_send_done(uint32_t len)
 {
-    (void)buf;
     (void)len;
 }

+ 4 - 10
components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h

@@ -12,21 +12,15 @@
 extern "C" {
 #endif
 
-/* Ethernet Maximum Segment size, typically 1514 bytes */
-#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
-
 /* Init cdc ecm interface driver */
 struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
 
-/* Setup request command callback api */
-void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
+void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]);
 
-/* Api for eth only without any net stack */
-uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
-void usbd_cdc_ecm_send_done(void);
+void usbd_cdc_ecm_data_recv_done(uint32_t len);
+void usbd_cdc_ecm_data_send_done(uint32_t len);
 int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
-void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
-void usbd_cdc_ecm_start_read_next(void);
+int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len);
 
 #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
 #include "lwip/netif.h"

+ 6 - 6
components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c

@@ -267,18 +267,18 @@ const struct usbh_class_driver cdc_data_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
-    .class = USB_DEVICE_CLASS_CDC,
-    .subclass = CDC_ABSTRACT_CONTROL_MODEL,
-    .protocol = 0x00,
+    .bInterfaceClass = USB_DEVICE_CLASS_CDC,
+    .bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
+    .bInterfaceProtocol = 0x00,
     .id_table = NULL,
     .class_driver = &cdc_acm_class_driver
 };
 
 CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS,
-    .class = USB_DEVICE_CLASS_CDC_DATA,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = NULL,
     .class_driver = &cdc_data_class_driver
 };

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

@@ -323,9 +323,9 @@ const struct usbh_class_driver cdc_ecm_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_CDC,
-    .subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
-    .protocol = CDC_COMMON_PROTOCOL_NONE,
+    .bInterfaceClass = USB_DEVICE_CLASS_CDC,
+    .bInterfaceSubClass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
+    .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
     .id_table = NULL,
     .class_driver = &cdc_ecm_class_driver
 };

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

@@ -403,9 +403,9 @@ const struct usbh_class_driver cdc_ncm_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_CDC,
-    .subclass = CDC_NETWORK_CONTROL_MODEL,
-    .protocol = CDC_COMMON_PROTOCOL_NONE,
+    .bInterfaceClass = USB_DEVICE_CLASS_CDC,
+    .bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL,
+    .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
     .id_table = NULL,
     .class_driver = &cdc_ncm_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/hid/usbh_hid.c

@@ -303,9 +303,9 @@ const struct usbh_class_driver hid_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS,
-    .class = USB_DEVICE_CLASS_HID,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = USB_DEVICE_CLASS_HID,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = NULL,
     .class_driver = &hid_class_driver
 };

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

@@ -734,9 +734,9 @@ const struct usbh_class_driver hub_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS,
-    .class = USB_DEVICE_CLASS_HUB,
-    .subclass = 0,
-    .protocol = 0,
+    .bInterfaceClass = USB_DEVICE_CLASS_HUB,
+    .bInterfaceSubClass = 0,
+    .bInterfaceProtocol = 0,
     .id_table = NULL,
     .class_driver = &hub_class_driver
 };

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

@@ -443,9 +443,9 @@ const struct usbh_class_driver msc_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_MASS_STORAGE,
-    .subclass = MSC_SUBCLASS_SCSI,
-    .protocol = MSC_PROTOCOL_BULK_ONLY,
+    .bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass = MSC_SUBCLASS_SCSI,
+    .bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY,
     .id_table = NULL,
     .class_driver = &msc_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/template/usbh_xxx.c

@@ -89,9 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = 0,
-    .subclass = 0,
-    .protocol = 0,
+    .bInterfaceClass = 0,
+    .bInterfaceSubClass = 0,
+    .bInterfaceProtocol = 0,
     .id_table = NULL,
     .class_driver = &xxx_class_driver
 };

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

@@ -817,9 +817,9 @@ static const struct usbh_class_driver asix_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = asix_id_table,
     .class_driver = &asix_class_driver
 };

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

@@ -2272,9 +2272,9 @@ static const struct usbh_class_driver rtl8152_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info rtl8152_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = rtl_id_table,
     .class_driver = &rtl8152_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c

@@ -370,9 +370,9 @@ const struct usbh_class_driver ch34x_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = ch34x_id_table,
     .class_driver = &ch34x_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c

@@ -319,9 +319,9 @@ const struct usbh_class_driver cp210x_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = cp210x_id_table,
     .class_driver = &cp210x_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c

@@ -392,9 +392,9 @@ const struct usbh_class_driver ftdi_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = ftdi_id_table,
     .class_driver = &ftdi_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c

@@ -440,9 +440,9 @@ const struct usbh_class_driver pl2303_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = pl2303_id_table,
     .class_driver = &pl2303_class_driver
 };

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

@@ -504,9 +504,9 @@ static const struct usbh_class_driver bl616_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = bl616_id_table,
     .class_driver = &bl616_class_driver
 };

+ 3 - 3
components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c

@@ -220,9 +220,9 @@ static const uint16_t xbox_id_table[][2] = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_VEND_SPECIFIC,
-    .subclass = 0x5d,
-    .protocol = 0x01,
+    .bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC,
+    .bInterfaceSubClass = 0x5d,
+    .bInterfaceProtocol = 0x01,
     .id_table =  xbox_id_table,
     .class_driver = &xbox_class_driver
 };

+ 96 - 55
components/drivers/usb/cherryusb/class/video/usbd_video.c

@@ -18,10 +18,20 @@ struct usbd_video_priv {
     uint8_t power_mode;
     uint8_t error_code;
     struct video_entity_info info[3];
-    uint8_t *ep_buffer;
+    uint8_t *ep_buf0;
+    uint8_t *ep_buf1;
+    bool ep_buf0_ready;
+    bool ep_buf1_ready;
+    uint32_t ep_buf0_len;
+    uint32_t ep_buf1_len;
+    uint8_t ep_buf_idx;
+    bool stream_finish;
+    uint32_t max_packets;
     uint8_t *stream_buf;
     uint32_t stream_len;
     uint32_t stream_offset;
+    uint8_t stream_frameid;
+    uint32_t stream_headerlen;
 } g_usbd_video[CONFIG_USBDEV_MAX_BUS];
 
 static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -741,6 +751,43 @@ static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dw
     g_usbd_video[busid].commit.bPreferedVersion = 0;
     g_usbd_video[busid].commit.bMinVersion = 0;
     g_usbd_video[busid].commit.bMaxVersion = 0;
+
+    g_usbd_video[busid].stream_frameid = 0;
+    g_usbd_video[busid].stream_headerlen = 2;
+}
+
+static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
+{
+    struct video_payload_header *header;
+    uint32_t len;
+    uint32_t offset;
+
+    len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
+    offset = 0;
+    while (len > 0) {
+        header = (struct video_payload_header *)&ep_buf[offset];
+        header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
+        header->headerInfoUnion.bmheaderInfo = 0;
+        header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
+        header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
+        header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
+
+        uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
+
+        usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
+                   &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
+                   len2);
+
+        g_usbd_video[busid].stream_offset += len2;
+        len -= len2;
+        offset += (len2 + g_usbd_video[busid].stream_headerlen);
+
+        if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
+            header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
+        }
+    }
+
+    return offset;
 }
 
 struct usbd_interface *usbd_video_init_intf(uint8_t busid,
@@ -770,74 +817,68 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid,
 
 bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
 {
-    struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer;
     uint32_t remain;
-    uint32_t len;
-    bool last_packet = false;
-
-    header->bHeaderLength = 2;
-    header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
 
-    remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
-
-    len = MIN(remain, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - header->bHeaderLength);
-    memcpy(&g_usbd_video[busid].ep_buffer[header->bHeaderLength],
-           &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
-           len);
+    if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) {    /* callback: buf1 ready and buf0 was sent */
+        g_usbd_video[busid].ep_buf0_ready = false;
+        g_usbd_video[busid].ep_buf_idx = 1;
+        usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
+    } else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) {    /* callback: buf0 ready and buf1 was sent */
+        g_usbd_video[busid].ep_buf1_ready = false;
+        g_usbd_video[busid].ep_buf_idx = 0;
+        usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
+    } else {
+        if (g_usbd_video[busid].stream_finish) {
+            return true;
+        }
+    }
 
-    g_usbd_video[busid].stream_offset += len;
+    if (!g_usbd_video[busid].ep_buf0_ready) {
+        remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
+        if (remain == 0) {
+            g_usbd_video[busid].stream_frameid ^= 1;
+            g_usbd_video[busid].stream_finish = true;
+        } else {
+            g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
+            g_usbd_video[busid].ep_buf0_ready = true;
+            if (!g_usbd_video[busid].ep_buf1_ready) {
+                g_usbd_video[busid].ep_buf_idx = 0;
+                usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
+            }
+        }
+    }
 
-    if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
-        last_packet = true;
-        header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
+    if (!g_usbd_video[busid].ep_buf1_ready) {
+        remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
+        if (remain == 0) {
+            g_usbd_video[busid].stream_frameid ^= 1;
+            g_usbd_video[busid].stream_finish = true;
+        } else {
+            g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
+            g_usbd_video[busid].ep_buf1_ready = true;
+        }
     }
 
-    usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buffer, len + header->bHeaderLength);
-    return last_packet;
+    return false;
 }
 
-int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len)
+int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
 {
-    if (usb_device_is_configured(busid) == 0) {
+    if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
         return -1;
     }
 
-    g_usbd_video[busid].ep_buffer = ep_buffer;
-    g_usbd_video[busid].stream_buf = buf;
-    g_usbd_video[busid].stream_len = len;
+    g_usbd_video[busid].ep_buf0 = ep_buf0;
+    g_usbd_video[busid].ep_buf1 = ep_buf1;
+    g_usbd_video[busid].ep_buf0_ready = false;
+    g_usbd_video[busid].ep_buf1_ready = false;
+    g_usbd_video[busid].ep_buf_idx = 0;
+    g_usbd_video[busid].stream_finish = false;
+    g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
+    g_usbd_video[busid].stream_buf = stream_buf;
+    g_usbd_video[busid].stream_len = stream_len;
     g_usbd_video[busid].stream_offset = 0;
 
-    struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer;
-
-    header->headerInfoUnion.headerInfoBits.frameIdentifier ^= 1;
-    header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
-
     usbd_video_stream_split_transfer(busid, ep);
     return 0;
 }
-
-uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
-{
-    uint32_t packets;
-    uint32_t last_packet_size;
-    uint32_t picture_pos = 0;
-    static uint8_t uvc_header[2] = { 0x02, 0x80 };
-
-    packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
-    last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
-
-    for (size_t i = 0; i < packets; i++) {
-        output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
-        output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
-        if (i == (packets - 1)) {
-            memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
-            output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
-        } else {
-            memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
-            picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
-        }
-    }
-    uvc_header[1] ^= 1;
-    *out_len = (input_len + 2 * packets);
-    return packets;
-}

+ 1 - 3
components/drivers/usb/cherryusb/class/video/usbd_video.h

@@ -22,9 +22,7 @@ void usbd_video_open(uint8_t busid, uint8_t intf);
 void usbd_video_close(uint8_t busid, uint8_t intf);
 
 bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
-int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len);
-
-uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
+int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len);
 
 #ifdef __cplusplus
 }

+ 6 - 6
components/drivers/usb/cherryusb/class/video/usbh_video.c

@@ -531,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_VIDEO,
-    .subclass = VIDEO_SC_VIDEOCONTROL,
-    .protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
+    .bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
+    .bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL,
+    .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
     .id_table = NULL,
     .class_driver = &video_ctrl_class_driver
 };
 
 CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_VIDEO,
-    .subclass = VIDEO_SC_VIDEOSTREAMING,
-    .protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
+    .bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
+    .bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING,
+    .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
     .id_table = NULL,
     .class_driver = &video_streaming_class_driver
 };

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

@@ -478,7 +478,7 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
     g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
     g_rndis_rx_data_length = hdr->DataLength;
 
-    usbd_rndis_data_recv_done();
+    usbd_rndis_data_recv_done(g_rndis_rx_data_length);
 }
 
 void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
@@ -489,6 +489,7 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
         /* send zlp */
         usbd_ep_start_write(0, ep, NULL, 0);
     } else {
+        usbd_rndis_data_send_done(g_rndis_tx_data_length);
         g_rndis_tx_data_length = 0;
     }
 }
@@ -592,3 +593,13 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
 
     return intf;
 }
+
+__WEAK void usbd_rndis_data_recv_done(uint32_t len)
+{
+    (void)len;
+}
+
+__WEAK void usbd_rndis_data_send_done(uint32_t len)
+{
+    (void)len;
+}

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

@@ -18,7 +18,8 @@ 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_data_recv_done(void);
+void usbd_rndis_data_recv_done(uint32_t len);
+void usbd_rndis_data_send_done(uint32_t len);
 
 #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
 struct pbuf *usbd_rndis_eth_rx(void);

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

@@ -393,18 +393,18 @@ static const uint16_t bluetooth_id_table[][2] = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
     .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
-    .class = 0xff,
-    .subclass = 0x00,
-    .protocol = 0x00,
+    .bInterfaceClass = 0xff,
+    .bInterfaceSubClass = 0x00,
+    .bInterfaceProtocol = 0x00,
     .id_table = bluetooth_id_table,
     .class_driver = &bluetooth_class_driver
 };
 #else
 CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_WIRELESS,
-    .subclass = 0x01,
-    .protocol = 0x01,
+    .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
+    .bInterfaceSubClass = 0x01,
+    .bInterfaceProtocol = 0x01,
     .id_table = NULL,
     .class_driver = &bluetooth_class_driver
 };

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

@@ -600,9 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = {
 
 CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
     .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
-    .class = USB_DEVICE_CLASS_WIRELESS,
-    .subclass = 0x01,
-    .protocol = 0x03,
+    .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
+    .bInterfaceSubClass = 0x01,
+    .bInterfaceProtocol = 0x03,
     .id_table = NULL,
     .class_driver = &rndis_class_driver
 };

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

@@ -88,6 +88,8 @@ static inline void usb_hexdump(const void *ptr, uint32_t buflen)
     unsigned char *buf = (unsigned char *)ptr;
     uint32_t i, j;
 
+    (void)buf;
+
     for (i = 0; i < buflen; i += 16) {
         CONFIG_USB_PRINTF("%08X:", i);
 

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

@@ -15,7 +15,7 @@
 #undef CHERRYUSB_VERSION_STR
 #endif
 
-#define CHERRYUSB_VERSION     0x010401
-#define CHERRYUSB_VERSION_STR "v1.4.1"
+#define CHERRYUSB_VERSION     0x010402
+#define CHERRYUSB_VERSION_STR "v1.4.2"
 
 #endif

+ 16 - 7
components/drivers/usb/cherryusb/core/usbd_core.c

@@ -64,6 +64,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
     bool test_req;
 #endif
     struct usbd_interface *intf[16];
+    uint8_t intf_altsetting[16];
     uint8_t intf_offset;
 
     struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM];
@@ -98,6 +99,7 @@ static bool is_device_configured(uint8_t busid)
  * This function sets endpoint configuration according to one specified in USB
  * endpoint descriptor and then enables it for data transfers.
  *
+ * @param [in]  busid busid
  * @param [in]  ep Endpoint descriptor byte array
  *
  * @return true if successfully configured and enabled
@@ -125,6 +127,7 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto
  * This function cancels transfers that are associated with endpoint and
  * disabled endpoint itself.
  *
+ * @param [in]  busid busid
  * @param [in]  ep Endpoint descriptor byte array
  *
  * @return true if successfully deconfigured and disabled
@@ -144,6 +147,7 @@ static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descrip
  * This function parses the list of installed USB descriptors and attempts
  * to find the specified USB descriptor.
  *
+ * @param [in]  busid busid
  * @param [in]  type_index Type and index of the descriptor
  * @param [out] data       Descriptor data
  * @param [out] len        Descriptor length
@@ -370,6 +374,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
  * index and alternate setting by parsing the installed USB descriptor list.
  * A configuration index of 0 unconfigures the device.
  *
+ * @param [in] busid busid
  * @param [in] config_index Configuration index
  * @param [in] alt_setting  Alternate setting number
  *
@@ -439,6 +444,7 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t
 /**
  * @brief set USB interface
  *
+ * @param [in] busid busid
  * @param [in] iface Interface index
  * @param [in] alt_setting  Alternate setting number
  *
@@ -494,7 +500,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
                         goto find_end;
                     } else if (cur_alt_setting == alt_setting) {
                         ret = usbd_set_endpoint(busid, ep_desc);
-                        goto find_end;
                     } else {
                     }
                 }
@@ -522,6 +527,7 @@ find_end:
 /**
  * @brief handle a standard device request
  *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -617,6 +623,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
 /**
  * @brief handle a standard interface request
  *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -703,11 +710,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
             ret = false;
             break;
         case USB_REQUEST_GET_INTERFACE:
-            (*data)[0] = 0;
+            (*data)[0] = g_usbd_core[busid].intf_altsetting[intf_num];
             *len = 1;
             break;
 
         case USB_REQUEST_SET_INTERFACE:
+            g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue);
             usbd_set_interface(busid, setup->wIndex, setup->wValue);
             *len = 0;
             break;
@@ -723,6 +731,7 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
 /**
  * @brief handle a standard endpoint request
  *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -787,6 +796,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
 /**
  * @brief handle standard requests (list in chapter 9)
  *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -830,8 +840,7 @@ static int usbd_standard_request_handler(uint8_t busid, struct usb_setup_packet
 /**
  * @brief handler for class requests
  *
- * If a custom request handler was installed, this handler is called first.
- *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -863,8 +872,7 @@ static int usbd_class_request_handler(uint8_t busid, struct usb_setup_packet *se
 /**
  * @brief handler for vendor requests
  *
- * If a custom request handler was installed, this handler is called first.
- *
+ * @param [in]     busid    busid
  * @param [in]     setup    The setup packet
  * @param [in,out] data     Data buffer
  * @param [in,out] len      Pointer to data length
@@ -1006,6 +1014,7 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
 /**
  * @brief handle setup request( standard/class/vendor/other)
  *
+ * @param [in]     busid busid
  * @param [in]     setup The setup packet
  * @param [in,out] data  Data buffer
  * @param [in,out] len   Pointer to data length
@@ -1167,7 +1176,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
 #ifdef CONFIG_USBDEV_EP0_INDATA_NO_COPY
         g_usbd_core[busid].ep0_data_buf = buf;
 #else
-        memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue);
+        usb_memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue);
 #endif
     } else {
         /* use memcpy(*data, xxx, len); has copied into ep0 buffer, we do nothing */

+ 55 - 4
components/drivers/usb/cherryusb/core/usbh_core.c

@@ -93,19 +93,22 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
     struct usbh_class_info *index = NULL;
 
     for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
-        if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) {
+        if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->bInterfaceClass == class)) {
             continue;
         }
-        if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) {
+        if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->bInterfaceSubClass == subclass)) {
             continue;
         }
-        if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) {
+        if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) {
             continue;
         }
         if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) {
             /* scan id table */
             uint32_t i;
-            for (i = 0; index->id_table[i][0] && index->id_table[i][0] != vid && index->id_table[i][1] != pid; i++) {
+            for (i = 0; index->id_table[i][0]; i++) {
+                if (index->id_table[i][0] == vid && index->id_table[i][1] == pid) {
+                    break;
+                }
             }
             /* do not match, continue next */
             if (!index->id_table[i][0]) {
@@ -831,6 +834,37 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *
     }
 }
 
+static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port)
+{
+    struct usbh_hubport *hport;
+    struct usbh_hub *hub_next;
+
+    if (hub->index == hub_index) {
+        hport = &hub->child[hub_port - 1];
+        return hport;
+    } else {
+        for (uint8_t port = 0; port < hub->nports; port++) {
+            hport = &hub->child[port];
+            if (hport->connected) {
+                for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
+                    if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
+                        if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
+                            hub_next = hport->config.intf[itf].priv;
+
+                            if (hub_next && hub_next->connected) {
+                                hport = usbh_list_all_hubport(hub_next, hub_index, hub_port);
+                                if (hport) {
+                                    return hport;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return NULL;
+}
 void *usbh_find_class_instance(const char *devname)
 {
     usb_slist_t *bus_list;
@@ -855,6 +889,23 @@ void *usbh_find_class_instance(const char *devname)
     return NULL;
 }
 
+struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port)
+{
+    struct usbh_hub *hub;
+    struct usbh_bus *bus;
+    struct usbh_hubport *hport;
+    size_t flags;
+
+    flags = usb_osal_enter_critical_section();
+
+    bus = &g_usbhost_bus[busid];
+    hub = &bus->hcd.roothub;
+
+    hport = usbh_list_all_hubport(hub, hub_index, hub_port);
+    usb_osal_leave_critical_section(flags);
+    return hport;
+}
+
 int lsusb(int argc, char **argv)
 {
     usb_slist_t *bus_list;

+ 4 - 3
components/drivers/usb/cherryusb/core/usbh_core.h

@@ -61,9 +61,9 @@ extern "C" {
 
 struct usbh_class_info {
     uint8_t match_flags;           /* Used for product specific matches; range is inclusive */
-    uint8_t class;                 /* Base device class code */
-    uint8_t subclass;              /* Sub-class, depends on base class. Eg. */
-    uint8_t protocol;              /* Protocol, depends on base class. Eg. */
+    uint8_t bInterfaceClass;       /* Base device class code */
+    uint8_t bInterfaceSubClass;    /* Sub-class, depends on base class. Eg. */
+    uint8_t bInterfaceProtocol;    /* Protocol, depends on base class. Eg. */
     const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
     const struct usbh_class_driver *class_driver;
 };
@@ -275,6 +275,7 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett
 int usbh_initialize(uint8_t busid, uintptr_t reg_base);
 int usbh_deinitialize(uint8_t busid);
 void *usbh_find_class_instance(const char *devname);
+struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port);
 
 int lsusb(int argc, char **argv);
 

+ 5 - 4
components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c

@@ -332,14 +332,15 @@ void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
   */
 void hid_mouse_test(uint8_t busid)
 {
+    if(usb_device_is_configured(busid) == false) {
+        return;
+    }
     /*!< move mouse pointer */
     mouse_cfg.x += 10;
     mouse_cfg.y = 0;
-    int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
-    if (ret < 0) {
-        return;
-    }
+
     hid_state = HID_STATE_BUSY;
+    usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
     while (hid_state == HID_STATE_BUSY) {
     }
 }

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

@@ -6,6 +6,10 @@
 #include "usbd_core.h"
 #include "usbd_cdc_ecm.h"
 
+#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP
+#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo"
+#endif
+
 /*!< endpoint address */
 #define CDC_IN_EP          0x81
 #define CDC_OUT_EP         0x02
@@ -222,12 +226,12 @@ void cdc_ecm_lwip_init(void)
     while (!netif_is_up(netif)) {
     }
 
-    // while (dhserv_init(&dhcp_config)) {}
+    while (dhserv_init(&dhcp_config)) {}
 
-    // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
+    while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
 }
 
-void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
+void usbd_cdc_ecm_data_recv_done(uint32_t len)
 {
 }
 

+ 8 - 4
components/drivers/usb/cherryusb/demo/cdc_rndis_template.c

@@ -6,6 +6,10 @@
 #include "usbd_core.h"
 #include "usbd_rndis.h"
 
+#ifndef CONFIG_USBDEV_RNDIS_USING_LWIP
+#error "Please enable CONFIG_USBDEV_RNDIS_USING_LWIP for this demo"
+#endif
+
 /*!< endpoint address */
 #define CDC_IN_EP  0x81
 #define CDC_OUT_EP 0x02
@@ -170,7 +174,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
     return usbd_rndis_eth_tx(p);
 }
 
-void usbd_rndis_data_recv_done(void)
+void usbd_rndis_data_recv_done(uint32_t len)
 {
     eth_device_ready(&rndis_dev);
 }
@@ -258,12 +262,12 @@ void rndis_lwip_init(void)
     while (!netif_is_up(netif)) {
     }
 
-    // while (dhserv_init(&dhcp_config)) {}
+    while (dhserv_init(&dhcp_config)) {}
 
-    // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
+    while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
 }
 
-void usbd_rndis_data_recv_done(void)
+void usbd_rndis_data_recv_done(uint32_t len)
 {
 }
 

+ 4 - 3
components/drivers/usb/cherryusb/demo/hid_keyboard_template.c

@@ -236,12 +236,13 @@ void hid_keyboard_test(uint8_t busid)
 {
     const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    memcpy(write_buffer, sendbuffer, 8);
-    int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
-    if (ret < 0) {
+    if(usb_device_is_configured(busid) == false) {
         return;
     }
+
+    memcpy(write_buffer, sendbuffer, 8);
     hid_state = HID_STATE_BUSY;
+    usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
     while (hid_state == HID_STATE_BUSY) {
     }
 }

+ 5 - 4
components/drivers/usb/cherryusb/demo/hid_mouse_template.c

@@ -304,14 +304,15 @@ void draw_circle(uint8_t *buf)
 /* https://cps-check.com/cn/polling-rate-check */
 void hid_mouse_test(uint8_t busid)
 {
+    if(usb_device_is_configured(busid) == false) {
+        return;
+    }
+
     int counter = 0;
     while (counter < 1000) {
         draw_circle((uint8_t *)&mouse_cfg);
-        int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
-        if (ret < 0) {
-            return;
-        }
         hid_state = HID_STATE_BUSY;
+        usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
         while (hid_state == HID_STATE_BUSY) {
         }
 

+ 5 - 4
components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c

@@ -307,6 +307,10 @@ void hid_mouse_test(uint8_t busid)
     static uint32_t count = 1000;
     int ret;
 
+    if(usb_device_is_configured(busid) == false) {
+        return;
+    }
+
     // if (gpio_read_pin(GPIO_PIN) == 1) {
     //     ret = usbd_send_remote_wakeup(busid);
     //     if (ret < 0) {
@@ -317,11 +321,8 @@ void hid_mouse_test(uint8_t busid)
 
     while (count) {
         draw_circle((uint8_t *)&mouse_cfg);
-        int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
-        if (ret < 0) {
-            return;
-        }
         hid_state = HID_STATE_BUSY;
+        usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
         while (hid_state == HID_STATE_BUSY) {
         }
 

+ 29 - 6
components/drivers/usb/cherryusb/demo/usb_host.c

@@ -254,38 +254,38 @@ delete:
 }
 #endif
 
+#if TEST_USBH_CDC_ACM
 void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
 {
-#if TEST_USBH_CDC_ACM
     usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, cdc_acm_class);
-#endif
 }
 
 void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
 {
 }
+#endif
 
+#if TEST_USBH_HID
 void usbh_hid_run(struct usbh_hid *hid_class)
 {
-#if TEST_USBH_HID
     usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class);
-#endif
 }
 
 void usbh_hid_stop(struct usbh_hid *hid_class)
 {
 }
+#endif
 
+#if TEST_USBH_MSC
 void usbh_msc_run(struct usbh_msc *msc_class)
 {
-#if TEST_USBH_MSC
     usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
-#endif
 }
 
 void usbh_msc_stop(struct usbh_msc *msc_class)
 {
 }
+#endif
 
 #if TEST_USBH_AUDIO
 #error "commercial charge"
@@ -294,3 +294,26 @@ void usbh_msc_stop(struct usbh_msc *msc_class)
 #if TEST_USBH_VIDEO
 #error "commercial charge"
 #endif
+
+#if 0
+#include "usbh_aoa.h"
+
+static struct aoa_string_info deviceinfo = {
+    .acc_manufacturer = "CherryUSB",
+    .acc_model = "CherryUSB",
+    .acc_description = "Android Open Accessory CherryUSB",
+    .acc_version = "1.0",
+    .acc_uri = "http://developer.android.com/tools/adk/index.html",
+    .acc_serial = "CherryUSB"
+};
+
+int aoa_switch(int argc, char **argv)
+{
+    struct usbh_hubport *hport = usbh_find_hubport(0, 1, 1);
+
+    usbh_aoa_switch(hport, &deviceinfo);
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(aoa_switch, aoa_switch, aoa_switch);
+#endif

+ 13 - 35
components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c

@@ -9,6 +9,8 @@
 #include "usbd_hid.h"
 #include "cherryusb_mjpeg.h"
 
+#define MAX_PACKETS_IN_ONE_TRANSFER 1
+
 #define VIDEO_IN_EP  0x81
 #define VIDEO_INT_EP 0x86
 
@@ -267,7 +269,7 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET];
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_write_buffer[AUDIO_IN_PACKET];
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[40 * 1024];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
 
 volatile bool video_tx_flag = 0;
 volatile bool audio_tx_flag = 0;
@@ -331,8 +333,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
 
 void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
-    //USB_LOG_RAW("actual in len:%d\r\n", nbytes);
-    video_iso_tx_busy = false;
+    if (usbd_video_stream_split_transfer(busid, ep)) {
+        /* one frame has done */
+        video_iso_tx_busy = false;
+    }
 }
 
 static struct usbd_endpoint video_in_ep = {
@@ -458,56 +462,30 @@ void hid_keyboard_test(uint8_t busid)
 {
     const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    memcpy(hid_write_buffer, sendbuffer, 8);
-    int ret = usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8);
-    if (ret < 0) {
+    if(usb_device_is_configured(busid) == false) {
         return;
     }
+
+    memcpy(hid_write_buffer, sendbuffer, 8);
     hid_state = HID_STATE_BUSY;
+    usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8);
     while (hid_state == HID_STATE_BUSY) {
     }
 }
 
 void video_test(uint8_t busid)
 {
-    uint32_t out_len;
-    uint32_t packets;
+    memset(video_packet_buffer, 0, sizeof(video_packet_buffer));
 
-    (void)packets;
-    memset(video_packet_buffer, 0, 40 * 1024);
     while (1) {
         if (video_tx_flag) {
-            packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), video_packet_buffer, &out_len);
-#if 1
             video_iso_tx_busy = true;
-            usbd_ep_start_write(busid, VIDEO_IN_EP, video_packet_buffer, out_len);
+            usbd_video_stream_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[0][0], &video_packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
             while (video_iso_tx_busy) {
                 if (video_tx_flag == 0) {
                     break;
                 }
             }
-#else
-            /* dwc2 must use this method */
-            for (uint32_t i = 0; i < packets; i++) {
-                if (i == (packets - 1)) {
-                    video_iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
-                    while (video_iso_tx_busy) {
-                        if (video_tx_flag == 0) {
-                            break;
-                        }
-                    }
-                } else {
-                    video_iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
-                    while (video_iso_tx_busy) {
-                        if (video_tx_flag == 0) {
-                            break;
-                        }
-                    }
-                }
-            }
-#endif
         }
     }
 }

+ 9 - 29
components/drivers/usb/cherryusb/demo/video_static_h264_template.c

@@ -7,6 +7,8 @@
 #include "usbd_video.h"
 #include "cherryusb_h264.h"
 
+#define MAX_PACKETS_IN_ONE_TRANSFER 1
+
 #define VIDEO_IN_EP  0x81
 #define VIDEO_INT_EP 0x83
 
@@ -180,8 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
 
 void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
-    //USB_LOG_RAW("actual in len:%d\r\n", nbytes);
-    iso_tx_busy = false;
+    if (usbd_video_stream_split_transfer(busid, ep)) {
+        /* one frame has done */
+        iso_tx_busy = false;
+    }
 }
 
 static struct usbd_endpoint video_in_ep = {
@@ -202,7 +206,7 @@ void video_init(uint8_t busid, uintptr_t reg_base)
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
 
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][40 * 1024];
 
 void video_test(uint8_t busid)
 {
@@ -210,40 +214,16 @@ void video_test(uint8_t busid)
     uint32_t packets;
 
     (void)packets;
-    memset(packet_buffer, 0, 40 * 1024);
+    memset(packet_buffer, 0, sizeof(packet_buffer));
     while (1) {
         if (tx_flag) {
-            packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264), packet_buffer, &out_len);
-#if 1
             iso_tx_busy = true;
-            usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
+            usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264));
             while (iso_tx_busy) {
                 if (tx_flag == 0) {
                     break;
                 }
             }
-#else
-            /* dwc2 must use this method */
-            for (uint32_t i = 0; i < packets; i++) {
-                if (i == (packets - 1)) {
-                    iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
-                    while (iso_tx_busy) {
-                        if (tx_flag == 0) {
-                            break;
-                        }
-                    }
-                } else {
-                    iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
-                    while (iso_tx_busy) {
-                        if (tx_flag == 0) {
-                            break;
-                        }
-                    }
-                }
-            }
-#endif
         }
     }
 }

+ 3 - 28
components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c

@@ -7,7 +7,7 @@
 #include "usbd_video.h"
 #include "cherryusb_mjpeg.h"
 
-#define VIDEO_STREAM_SPLIT_ENABLE 1
+#define MAX_PACKETS_IN_ONE_TRANSFER 1
 
 #define VIDEO_IN_EP  0x81
 #define VIDEO_INT_EP 0x83
@@ -182,14 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
 
 void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
-#if VIDEO_STREAM_SPLIT_ENABLE
     if (usbd_video_stream_split_transfer(busid, ep)) {
         /* one frame has done */
         iso_tx_busy = false;
     }
-#else
-    iso_tx_busy = false;
-#endif
 }
 
 static struct usbd_endpoint video_in_ep = {
@@ -210,42 +206,21 @@ void video_init(uint8_t busid, uintptr_t reg_base)
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
 
-#if VIDEO_STREAM_SPLIT_ENABLE
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
-#else
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
-#endif
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
 
 void video_test(uint8_t busid)
 {
-    uint32_t out_len;
-    uint32_t packets;
-
-    (void)packets;
-    (void)out_len;
     memset(packet_buffer, 0, sizeof(packet_buffer));
 
     while (1) {
         if (tx_flag) {
-#if VIDEO_STREAM_SPLIT_ENABLE
             iso_tx_busy = true;
-            usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
+            usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
             while (iso_tx_busy) {
                 if (tx_flag == 0) {
                     break;
                 }
             }
-#else
-            packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len);
-
-            iso_tx_busy = true;
-            usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
-            while (iso_tx_busy) {
-                if (tx_flag == 0) {
-                    break;
-                }
-            }
-#endif
         }
     }
 }

+ 9 - 32
components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c

@@ -7,6 +7,8 @@
 #include "usbd_video.h"
 #include "cherryusb_yuyv.h"
 
+#define MAX_PACKETS_IN_ONE_TRANSFER 1
+
 #define VIDEO_IN_EP  0x81
 #define VIDEO_INT_EP 0x83
 
@@ -182,8 +184,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
 
 void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
 {
-    //USB_LOG_RAW("actual in len:%d\r\n", nbytes);
-    iso_tx_busy = false;
+    if (usbd_video_stream_split_transfer(busid, ep)) {
+        /* one frame has done */
+        iso_tx_busy = false;
+    }
 }
 
 static struct usbd_endpoint video_in_ep = {
@@ -204,48 +208,21 @@ void video_init(uint8_t busid, uintptr_t reg_base)
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
 
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
 
 void video_test(uint8_t busid)
 {
-    uint32_t out_len;
-    uint32_t packets;
+    memset(packet_buffer, 0, sizeof(packet_buffer));
 
-    (void)packets;
-    memset(packet_buffer, 0, 40 * 1024);
     while (1) {
         if (tx_flag) {
-            packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv), packet_buffer, &out_len);
-#if 1
             iso_tx_busy = true;
-            usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
+            usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv));
             while (iso_tx_busy) {
                 if (tx_flag == 0) {
                     break;
                 }
             }
-#else
-            /* dwc2 must use this method */
-            for (uint32_t i = 0; i < packets; i++) {
-                if (i == (packets - 1)) {
-                    iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
-                    while (iso_tx_busy) {
-                        if (tx_flag == 0) {
-                            break;
-                        }
-                    }
-                } else {
-                    iso_tx_busy = true;
-                    usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
-                    while (iso_tx_busy) {
-                        if (tx_flag == 0) {
-                            break;
-                        }
-                    }
-                }
-            }
-#endif
         }
     }
 }

+ 4 - 3
components/drivers/usb/cherryusb/demo/webusb_hid_template.c

@@ -371,12 +371,13 @@ void hid_keyboard_test(uint8_t busid)
 {
     const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    memcpy(write_buffer, sendbuffer, 8);
-    int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
-    if (ret < 0) {
+    if(usb_device_is_configured(busid) == false) {
         return;
     }
+
+    memcpy(write_buffer, sendbuffer, 8);
     hid_state = HID_STATE_BUSY;
+    usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
     while (hid_state == HID_STATE_BUSY) {
     }
 }

+ 25 - 0
components/drivers/usb/cherryusb/idf_component.yml

@@ -0,0 +1,25 @@
+version: "1.4.2"
+description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
+tags:
+  - usb
+  - usb-device
+  - usb-host
+  - cdc_acm
+  - cdc_ecm
+  - cdc_ncm
+  - hid
+  - msc
+  - rndis
+  - uvc
+  - uac
+  - winusb
+url: https://github.com/cherry-embedded/CherryUSB
+repository: https://github.com/cherry-embedded/CherryUSB.git
+documentation: https://cherryusb.readthedocs.io/
+issues: https://github.com/cherry-embedded/CherryUSB/issues
+dependencies:
+  idf: ">=5.0"
+targets:
+  - esp32s2
+  - esp32s3
+  - esp32p4

+ 0 - 4
components/drivers/usb/cherryusb/platform/rtthread/usb_check.c

@@ -6,10 +6,6 @@
 #error must enable RT_USING_TIMER_SOFT to support timer callback in thread
 #endif
 
-#if IDLE_THREAD_STACK_SIZE < 2048
-#error "IDLE_THREAD_STACK_SIZE must be >= 2048"
-#endif
-
 #if RT_TIMER_THREAD_STACK_SIZE < 2048
 #error "RT_TIMER_THREAD_STACK_SIZE must be >= 2048"
 #endif

+ 5 - 0
components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c

@@ -101,6 +101,11 @@ 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;

+ 5 - 0
components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c

@@ -101,6 +101,11 @@ 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_HIGH;

+ 11 - 0
components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c

@@ -1,3 +1,14 @@
+/*
+ * Copyright (c) 2021-2024 HPMicro
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include "usbd_core.h"
 #include "usb_chipidea_reg.h"
 

+ 5 - 0
components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c

@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include "usbd_core.h"
 #include "fsl_common.h"
 

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

@@ -20,6 +20,11 @@ If you are using more than one port, all ip parameters must be the same(like fif
 
 ## GD32
 
+CONFIG_USBDEV_EP_NUM 必须为4 或者 6,并删除 usb_dc_dwc2.c 中 while(1){}
+
+当 CONFIG_USBDEV_EP_NUM 为4 时,fifo_num 不得大于 320 字
+当 CONFIG_USBDEV_EP_NUM 为6 时,fifo_num 不得大于 1280 字
+
 - GD32F30X_CL
 - GD32F405、GD32F407
 - GD32F450

+ 9 - 7
components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c

@@ -136,10 +136,12 @@ static inline int dwc2_reset(uint8_t busid)
 
     do {
         if (++count > 200000U) {
-            return -1;
+            break;
         }
     } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
 
+    USB_OTG_GLB->GRSTCTL &= ~USB_OTG_GRSTCTL_CSRST;
+
     return 0;
 }
 
@@ -478,7 +480,7 @@ static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum)
 
     msk = USB_OTG_DEV->DIEPMSK;
     emp = USB_OTG_DEV->DIEPEMPMSK;
-    msk |= ((emp >> (epnum & 0x07)) & 0x1U) << 7;
+    msk |= ((emp >> (epnum & 0x0F)) & 0x1U) << 7;
 
     tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT;
     USB_OTG_INEP((uint32_t)epnum)->DIEPINT = tmpreg;
@@ -790,7 +792,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep)
             } while ((USB_OTG_OUTEP(ep_idx)->DOEPINT & USB_OTG_DOEPINT_EPDISD) != USB_OTG_DOEPINT_EPDISD);
 
             /* Clear and unmask endpoint disabled interrupt */
-            USB_OTG_OUTEP(ep_idx)->DOEPINT |= USB_OTG_DOEPINT_EPDISD;
+            USB_OTG_OUTEP(ep_idx)->DOEPINT = USB_OTG_DOEPINT_EPDISD;
         }
 
         USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep_idx & 0x07)) << 16));
@@ -810,7 +812,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep)
             } while ((USB_OTG_INEP(ep_idx)->DIEPINT & USB_OTG_DIEPINT_EPDISD) != USB_OTG_DIEPINT_EPDISD);
 
             /* Clear and unmask endpoint disabled interrupt */
-            USB_OTG_INEP(ep_idx)->DIEPINT |= USB_OTG_DIEPINT_EPDISD;
+            USB_OTG_INEP(ep_idx)->DIEPINT = USB_OTG_DIEPINT_EPDISD;
         }
 
         USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07)));
@@ -1161,17 +1163,17 @@ void USBD_IRQHandler(uint8_t busid)
             dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
         }
         if (gint_status & USB_OTG_GINTSTS_ENUMDNE) {
-            USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE;
+            USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_ENUMDNE;
             dwc2_set_turnaroundtime(busid, SystemCoreClock, dwc2_get_devspeed(busid));
 
             USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK;
         }
         if (gint_status & USB_OTG_GINTSTS_PXFR_INCOMPISOOUT) {
-            USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_PXFR_INCOMPISOOUT;
+            USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_PXFR_INCOMPISOOUT;
         }
 
         if (gint_status & USB_OTG_GINTSTS_IISOIXFR) {
-            USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_IISOIXFR;
+            USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_IISOIXFR;
         }
 
         if (gint_status & USB_OTG_GINTSTS_SOF) {

+ 5 - 0
components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c

@@ -7,6 +7,9 @@
 #include "stdint.h"
 #include "usb_dwc2_reg.h"
 
+extern unsigned int system_core_clock;
+
+uint32_t SystemCoreClock;
 /* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example:
  *
  *  usbx->gccfg_bit.pwrdown = TRUE;
@@ -17,6 +20,7 @@
 
 uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
 {
+    SystemCoreClock = system_core_clock;
 #ifdef CONFIG_USB_HS
     return ((1 << 16) | (1 << 21));
 #else
@@ -35,6 +39,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
 
 uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
 {
+    SystemCoreClock = system_core_clock;
 #ifdef CONFIG_USB_HS
     return ((1 << 16) | (1 << 21));
 #else

+ 4 - 0
components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c

@@ -7,6 +7,10 @@
 #include "stdint.h"
 #include "usb_dwc2_reg.h"
 
+#if CONFIG_USBDEV_EP_NUM != 4 && CONFIG_USBDEV_EP_NUM != 6
+#error "gd32 only has 4 endpoints for pa11/pa12 and 6 endpoints for pb14/pb15"
+#endif
+
 /* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example:
  *
  *  usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;

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

@@ -166,6 +166,8 @@ uint32_t usbd_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
@@ -192,6 +194,8 @@ 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

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

@@ -215,6 +215,12 @@ static inline void dwc2_chan_char_init(struct usbh_bus *bus, uint8_t ch_num, uin
         regval |= USB_OTG_HCCHAR_EPDIR;
     }
 
+    if ((usbh_get_port_speed(bus, 0) == USB_SPEED_HIGH) && (speed != USB_SPEED_HIGH)) {
+        USB_LOG_ERR("Do not support LS/FS device on HS hub\r\n");
+        while (1) {
+        }
+    }
+
     /* LS device plugged to HUB */
     if ((speed == USB_SPEED_LOW) && (usbh_get_port_speed(bus, 0) != USB_SPEED_LOW)) {
         regval |= USB_OTG_HCCHAR_LSDEV;
@@ -1131,4 +1137,4 @@ void USBH_IRQHandler(uint8_t busid)
             USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT;
         }
     }
-}
+}

+ 17 - 19
components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c

@@ -9,6 +9,19 @@
 #include <hal_syscfg.h>
 #include "usbh_core.h"
 #include "usb_hc_ehci.h"
+#include "usb_hc_ohci.h"
+
+#if !defined(CONFIG_USB_EHCI_CONFIGFLAG)
+#error "aic ehci must define CONFIG_USB_EHCI_CONFIGFLAG"
+#endif
+
+#if !defined(CONFIG_USB_EHCI_WITH_OHCI)
+#error "aic must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device"
+#endif
+
+#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400
+#error "aic CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400"
+#endif
 
 extern void USBH_IRQHandler(uint8_t busid);
 
@@ -117,21 +130,12 @@ void usb_hc_low_level_init(struct usbh_bus *bus)
     aicos_request_irq(config[i].irq_num + 1, (irq_handler_t)aic_ohci_isr,
                       0, "usb_host_ohci", bus);
     aicos_irq_enable(config[i].irq_num);
+    aicos_irq_enable(config[i].irq_num + 1);
 }
 
 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;
+    return USB_SPEED_HIGH;
 }
 
 void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len)
@@ -149,7 +153,7 @@ void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len)
     aicos_dcache_clean_invalid_range((size_t *)addr, len);
 }
 
-int usbh_init(void)
+int __usbh_init(void)
 {
 #if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB1_HOST)
     int bus_id = 0;
@@ -171,11 +175,5 @@ int usbh_init(void)
 #include <rtthread.h>
 #include <rtdevice.h>
 
-INIT_ENV_EXPORT(usbh_init);
-
-#if defined (RT_USING_FINSH)
-#include <finsh.h>
-
-MSH_CMD_EXPORT_ALIAS(lsusb, lsusb, list usb device);
-#endif
+INIT_ENV_EXPORT(__usbh_init);
 #endif

+ 8 - 3
components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c

@@ -35,6 +35,11 @@ static void usb_host_mode_init(USB_Type *ptr)
     /* Set parallel transceiver width */
     ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK;
 
+#ifdef CONFIG_USB_HOST_FORCE_FULL_SPEED
+    /* Set usb forced to full speed mode */
+    ptr->PORTSC1 |= USB_PORTSC1_PFSC_MASK;
+#endif
+
     /* Not use interrupt threshold. */
     ptr->USBCMD &= ~USB_USBCMD_ITC_MASK;
 }
@@ -53,7 +58,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus)
 #endif
     }
 
-    usb_phy_init((USB_Type *)(bus->hcd.reg_base));
+    usb_phy_init((USB_Type *)(bus->hcd.reg_base), true);
     intc_m_enable_irq(_hcd_irqnum[bus->hcd.hcd_id]);
 }
 
@@ -86,18 +91,18 @@ uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
 
 extern void USBH_IRQHandler(uint8_t busid);
 
+SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0)
 void isr_usbh0(void)
 {
     USBH_IRQHandler(_hcd_busid[0]);
 }
-SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0)
 
 #ifdef HPM_USB1_BASE
+SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1)
 void isr_usbh1(void)
 {
     USBH_IRQHandler(_hcd_busid[1]);
 }
-SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1)
 #endif
 
 #endif

+ 5 - 0
components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c

@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include "usbh_core.h"
 #include "fsl_common.h"
 #include "usb_chipidea_reg.h"

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

@@ -952,6 +952,7 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
 
         while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) {
         }
+        USB_LOG_INFO("Switch port %u to OHCI\r\n", port);
         return ohci_roothub_control(bus, setup, buf);
     }
 #endif
@@ -1063,7 +1064,9 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
 
                             while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) {
                             }
-                            return ohci_roothub_control(bus, setup, buf);
+
+                            USB_LOG_INFO("Switch port %u to OHCI\r\n", port);
+                            return -USB_ERR_NOTSUPP;
                         }
 #endif
                         break;

+ 2 - 1
components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c

@@ -154,7 +154,8 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
 
         case USB_ENDPOINT_TYPE_ISOCHRONOUS:
             wEpRegVal = USB_EP_ISOCHRONOUS;
-            break;
+            USB_LOG_ERR("Do not support iso in fsdev\r\n");
+            return -1;
 
         default:
             break;

+ 2 - 4
components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c

@@ -128,8 +128,6 @@ int usbd_set_remote_wakeup(uint8_t busid)
     }
 
     usb_force_port_resume(ptr);
-    while (ptr->PORTSC1 & USB_PORTSC1_FPR_MASK) {
-    }
 
     return 0;
 }
@@ -362,18 +360,18 @@ void USBD_IRQHandler(uint8_t busid)
 
 #if !defined(USBD_USE_CUSTOM_ISR) || !USBD_USE_CUSTOM_ISR
 
+SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0)
 void isr_usbd0(void)
 {
     USBD_IRQHandler(_dcd_busid[0]);
 }
-SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0)
 
 #ifdef HPM_USB1_BASE
+SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1)
 void isr_usbd1(void)
 {
     USBD_IRQHandler(_dcd_busid[1]);
 }
-SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1)
 #endif
 
 #endif

+ 9 - 4
components/drivers/usb/cherryusb/port/ohci/README.md

@@ -1,18 +1,23 @@
 # Note
 
-This OHCI is a companion controller of EHCI.
+This OHCI is a companion controller of EHCI. But you can use OHCI only without CONFIG_USB_EHCI_WITH_OHCI definition.
+
+**And you need to pay for using OHCI driver**.
 
 ## Support Chip List
 
 ### AllwinnerTech
 
-- F133
+- F133(EHCI + OHCI)
 
 ### Nuvoton
 
-- Nuvoton all series
+- Nuvoton all series(EHCI + OHCI, OHCI only)
 
 ### Artinchip
 
-- d13x, d21x
+- d13x, d21x(EHCI + OHCI)
+
+### NXP
 
+- LPC4X/LPC5X(OHCI only)

+ 45 - 0
components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "fsl_device_registers.h"
+#include "fsl_power.h"
+#include "usbh_core.h"
+
+#if defined(CONFIG_USB_EHCI_WITH_OHCI)
+#error "lpc does not have ehci"
+#endif
+
+void usb_hc_low_level_init(struct usbh_bus *bus)
+{
+#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT))
+    SYSMPU_Enable(SYSMPU, 0);
+#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
+
+    NVIC_ClearPendingIRQ(USB0_IRQn);
+    NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn);
+
+    POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB0 Phy */
+
+    RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn);
+    RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn);
+    RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn);
+
+    CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U);
+
+    NVIC_SetPriority(USB0_IRQn, 3);
+    EnableIRQ(USB0_IRQn);
+}
+
+
+void usb_hc_low_level_deinit(struct usbh_bus *bus)
+{
+    DisableIRQ(USB0_IRQn);
+}
+
+void USB0_IRQHandler(void)
+{
+    extern void USBH_IRQHandler(uint8_t busid);
+    USBH_IRQHandler(0);
+}

+ 157 - 44
components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c

@@ -4,18 +4,58 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 #include "usb_hc_ohci.h"
-#include "usb_hc_ehci.h"
+
+/* Frame Interval / Periodic Start.
+ *
+ * At 12Mbps, there are 12000 bit time in each 1Msec frame.
+ */
+
+#define OHCI_FMINTERVAL_FI    (12000 - 1)
+#define OHCI_FMINTERVAL_FSMPS ((6 * (OHCI_FMINTERVAL_FI - 210)) / 7)
+#define DEFAULT_FMINTERVAL    ((OHCI_FMINTERVAL_FSMPS << OHCI_FMINT_FSMPS_SHIFT) | OHCI_FMINTERVAL_FI)
+#define DEFAULT_PERSTART      ((OHCI_FMINTERVAL_FI * 9) / 10)
+
+struct ohci_hcd g_ohci_hcd[CONFIG_USBHOST_MAX_BUS];
+
+USB_NOCACHE_RAM_SECTION struct ohci_ed_hw g_ohci_ed_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_OHCI_ED_NUM];
+USB_NOCACHE_RAM_SECTION struct ohci_hcca ohci_hcca[CONFIG_USBHOST_MAX_BUS];
 
 int ohci_init(struct usbh_bus *bus)
 {
     volatile uint32_t timeout = 0;
     uint32_t regval;
+    struct ohci_ed_hw *ed;
+
+    memset(&g_ohci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ohci_hcd));
+    memset(g_ohci_ed_pool[bus->hcd.hcd_id], 0, sizeof(struct ohci_ed_hw) * CONFIG_USB_OHCI_ED_NUM);
+
+    for (uint32_t i = 0; i < 32; i++) {
+        ohci_hcca[bus->hcd.hcd_id].inttbl[i] = 0;
+    }
+
+    for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
+        ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
+        if ((uint32_t)&ed->hw % 32) {
+            USB_LOG_ERR("struct ohci_ed_hw is not align 32\r\n");
+            return -USB_ERR_INVAL;
+        }
+        for (uint8_t i = 0; i < CONFIG_USB_OHCI_TD_NUM; i++) {
+            if ((uint32_t)&ed->td_pool[i] % 32) {
+                USB_LOG_ERR("struct ohci_td_hw is not align 32\r\n");
+                return -USB_ERR_INVAL;
+            }
+        }
+    }
+
+    for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
+        ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
+        ed->waitsem = usb_osal_sem_create(0);
+    }
 
     USB_LOG_INFO("OHCI hcrevision:0x%02x\r\n", (unsigned int)OHCI_HCOR->hcrevision);
 
+    OHCI_HCOR->hcintdis = OHCI_INT_MIE;
     OHCI_HCOR->hccontrol = 0;
-    OHCI_HCOR->hccontrolheaded = 0;
-    OHCI_HCOR->hcbulkheaded = 0;
 
     OHCI_HCOR->hccmdsts = OHCI_CMDST_HCR;
     while (OHCI_HCOR->hccmdsts & OHCI_CMDST_HCR) {
@@ -26,45 +66,39 @@ int ohci_init(struct usbh_bus *bus)
         }
     }
 
-    /* Frame Interval / Periodic Start.
-    *
-    * At 12Mbps, there are 12000 bit time in each 1Msec frame.
-    */
-
-#define BITS_PER_FRAME     12000
-#define FI                 (BITS_PER_FRAME - 1)
-#define FSMPS              ((6 * (FI - 210)) / 7)
-#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
-#define DEFAULT_PERSTART   (((9 * BITS_PER_FRAME) / 10) - 1)
-
     OHCI_HCOR->hcfminterval = DEFAULT_FMINTERVAL;
     OHCI_HCOR->hcperiodicstart = DEFAULT_PERSTART;
+    OHCI_HCOR->hclsthreshold = 0x628;
+
+    OHCI_HCOR->hccontrolheaded = 0;
+    OHCI_HCOR->hcbulkheaded = 0;
+    OHCI_HCOR->hchcca = (uintptr_t)&ohci_hcca[bus->hcd.hcd_id];
+
+    /* Clear pending interrupts */
+    regval = OHCI_HCOR->hcintsts;
+    OHCI_HCOR->hcintsts = regval;
 
     /* Put HC in operational state */
     regval = OHCI_HCOR->hccontrol;
+    regval &= ~OHCI_CTRL_CBSR;
     regval &= ~OHCI_CTRL_HCFS_MASK;
     regval |= OHCI_CTRL_HCFS_OPER;
+    regval |= OHCI_CTRL_CBSR;
+    regval |= OHCI_CTRL_CLE;
     OHCI_HCOR->hccontrol = regval;
 
-    /* Set global power in HcRhStatus */
-    OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
+    g_ohci_hcd[bus->hcd.hcd_id].n_ports = OHCI_HCOR->hcrhdescriptora & OHCI_RHDESCA_NDP_MASK;
+    USB_LOG_INFO("OHCI n_ports:%d\r\n", g_ohci_hcd[bus->hcd.hcd_id].n_ports);
 
-    /* Set HCCA base address */
-    OHCI_HCOR->hchcca = 0;
+    OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_PSM;
+    OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_NPS;
 
-    /* Clear pending interrupts */
-    regval = OHCI_HCOR->hcintsts;
-    OHCI_HCOR->hcintsts = regval;
-
-    for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) {
-        regval = OHCI_HCOR->hcrhportsts[port];
-        regval |= OHCI_RHPORTST_PPS;
-        OHCI_HCOR->hcrhportsts[port] = regval;
-    }
+    /* Set global power in HcRhStatus */
+    OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
+    usb_osal_msleep(20);
 
     /* Enable OHCI interrupts */
-    OHCI_HCOR->hcinten = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC |
-                         OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
+    OHCI_HCOR->hcinten = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
 
     return 0;
 }
@@ -72,15 +106,25 @@ int ohci_init(struct usbh_bus *bus)
 int ohci_deinit(struct usbh_bus *bus)
 {
     uint32_t regval;
+    struct ohci_ed_hw *ed;
 
     /* Disable OHCI interrupts */
-    OHCI_HCOR->hcintdis = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC |
-                          OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
+    OHCI_HCOR->hcintdis = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
+
+    /* Clear pending interrupts */
+    regval = OHCI_HCOR->hcintsts;
+    OHCI_HCOR->hcintsts = regval;
+
+    OHCI_HCOR->hcrhsts &= ~OHCI_RHSTATUS_SGP;
+
+    regval = OHCI_HCOR->hccontrol;
+    regval &= ~OHCI_CTRL_HCFS_MASK;
+    regval |= OHCI_CTRL_HCFS_SUSPEND;
+    OHCI_HCOR->hccontrol = regval;
 
-    for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) {
-        regval = OHCI_HCOR->hcrhportsts[port];
-        regval &= ~OHCI_RHPORTST_PPS;
-        OHCI_HCOR->hcrhportsts[port] = regval;
+    for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
+        ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
+        usb_osal_sem_delete(ed->waitsem);
     }
 
     return 0;
@@ -97,7 +141,7 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
     uint8_t port;
     uint32_t temp;
 
-    nports = g_ehci_hcd[bus->hcd.hcd_id].n_pcc;
+    nports = g_ohci_hcd[bus->hcd.hcd_id].n_ports;
 
     port = setup->wIndex;
     if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
@@ -139,28 +183,46 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
 
                 switch (setup->wValue) {
                     case HUB_PORT_FEATURE_ENABLE:
+                        temp = OHCI_RHPORTST_CCS;
                         break;
                     case HUB_PORT_FEATURE_SUSPEND:
+                        temp = OHCI_HCOR->hccontrol;
+                        temp &= ~OHCI_CTRL_HCFS_MASK;
+                        temp |= OHCI_CTRL_HCFS_RESUME;
+                        OHCI_HCOR->hccontrol = temp;
+
+                        usb_osal_msleep(20);
 
+                        temp = OHCI_HCOR->hccontrol;
+                        temp &= ~OHCI_CTRL_HCFS_MASK;
+                        temp |= OHCI_CTRL_HCFS_OPER;
+                        OHCI_HCOR->hccontrol = temp;
+
+                        temp = OHCI_RHPORTST_POCI;
+                        break;
                     case HUB_PORT_FEATURE_C_SUSPEND:
+                        temp = OHCI_RHPORTST_PSSC;
                         break;
                     case HUB_PORT_FEATURE_POWER:
+                        OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_CGP;
+                        temp = OHCI_RHPORTST_LSDA;
                         break;
                     case HUB_PORT_FEATURE_C_CONNECTION:
-                        OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_CSC;
+                        temp = OHCI_RHPORTST_CSC;
                         break;
                     case HUB_PORT_FEATURE_C_ENABLE:
-                        OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PESC;
+                        temp = OHCI_RHPORTST_PESC;
                         break;
                     case HUB_PORT_FEATURE_C_OVER_CURREN:
-                        OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_OCIC;
+                        temp = OHCI_RHPORTST_OCIC;
                         break;
                     case HUB_PORT_FEATURE_C_RESET:
-                        OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRSC;
+                        temp = OHCI_RHPORTST_PRSC;
                         break;
                     default:
                         return -USB_ERR_NOTSUPP;
                 }
+                OHCI_HCOR->hcrhportsts[port - 1] = temp;
                 break;
             case HUB_REQUEST_SET_FEATURE:
                 if (!port || port > nports) {
@@ -169,11 +231,17 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
 
                 switch (setup->wValue) {
                     case HUB_PORT_FEATURE_SUSPEND:
+                        temp = OHCI_HCOR->hccontrol;
+                        temp &= ~OHCI_CTRL_HCFS_MASK;
+                        temp |= OHCI_CTRL_HCFS_SUSPEND;
+                        OHCI_HCOR->hccontrol = temp;
+
                         break;
                     case HUB_PORT_FEATURE_POWER:
+                        OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
                         break;
                     case HUB_PORT_FEATURE_RESET:
-                        OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRS;
+                        OHCI_HCOR->hcrhportsts[port - 1] = OHCI_RHPORTST_PRS;
 
                         while (OHCI_HCOR->hcrhportsts[port - 1] & OHCI_RHPORTST_PRS) {
                         }
@@ -188,7 +256,6 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
                     return -USB_ERR_INVAL;
                 }
                 temp = OHCI_HCOR->hcrhportsts[port - 1];
-
                 memcpy(buf, &temp, 4);
                 break;
             default:
@@ -216,9 +283,9 @@ void OHCI_IRQHandler(uint8_t busid)
     bus = &g_usbhost_bus[busid];
 
     usbsts = OHCI_HCOR->hcintsts & OHCI_HCOR->hcinten;
-    OHCI_HCOR->hcintsts = usbsts;
 
     if (usbsts & OHCI_INT_RHSC) {
+        OHCI_HCOR->hcintsts = OHCI_INT_RHSC;
         for (int port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) {
             uint32_t portsc = OHCI_HCOR->hcrhportsts[port];
 
@@ -236,5 +303,51 @@ void OHCI_IRQHandler(uint8_t busid)
         }
     }
     if (usbsts & OHCI_INT_WDH) {
+        OHCI_HCOR->hcintsts = OHCI_INT_WDH;
     }
-}
+}
+
+#ifndef CONFIG_USB_EHCI_WITH_OHCI
+__WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
+{
+    (void)bus;
+}
+
+__WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus)
+{
+    (void)bus;
+}
+
+int usb_hc_init(struct usbh_bus *bus)
+{
+    usb_hc_low_level_init(bus);
+    return ohci_init(bus);
+}
+
+int usb_hc_deinit(struct usbh_bus *bus)
+{
+    ohci_deinit(bus);
+    usb_hc_low_level_deinit(bus);
+    return 0;
+}
+
+int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
+{
+    return ohci_roothub_control(bus, setup, buf);
+}
+
+int usbh_submit_urb(struct usbh_urb *urb)
+{
+    return ohci_submit_urb(urb);
+}
+
+int usbh_kill_urb(struct usbh_urb *urb)
+{
+    return ohci_kill_urb(urb);
+}
+
+void USBH_IRQHandler(uint8_t busid)
+{
+    OHCI_IRQHandler(busid);
+}
+#endif

+ 32 - 0
components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h

@@ -12,6 +12,38 @@
 
 #define OHCI_HCOR ((struct ohci_hcor *)(uintptr_t)(bus->hcd.reg_base + CONFIG_USB_OHCI_HCOR_OFFSET))
 
+#define OHCI_PTR2ADDR(x) ((uint32_t)(uintptr_t)(x) & ~0x0F)
+#define OHCI_ADDR2ED(x)  ((struct ohci_ed_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F))
+#define OHCI_ADDR2TD(x) ((struct ohci_td_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F))
+
+#ifndef CONFIG_USB_OHCI_ED_NUM
+#define CONFIG_USB_OHCI_ED_NUM CONFIG_USBHOST_PIPE_NUM
+#endif
+#ifndef CONFIG_USB_OHCI_TD_NUM
+#define CONFIG_USB_OHCI_TD_NUM 3
+#endif
+
+struct ohci_ed_hw;
+struct ohci_td_hw {
+    struct ohci_gtd hw;
+    struct usbh_urb *urb;
+    uint32_t buf_start;
+    uint32_t length;
+} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
+
+struct ohci_ed_hw {
+    struct ohci_ed hw;
+    struct ohci_td_hw td_pool[CONFIG_USB_OHCI_TD_NUM];
+    uint32_t td_count;
+    uint8_t ed_type;
+    usb_osal_sem_t waitsem;
+} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
+
+struct ohci_hcd {
+    bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM];
+    uint8_t n_ports;
+};
+
 int ohci_init(struct usbh_bus *bus);
 int ohci_deinit(struct usbh_bus *bus);
 uint16_t ohci_get_frame_number(struct usbh_bus *bus);

+ 11 - 11
components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h

@@ -95,10 +95,10 @@
 /* HcControl: HC control (7.1.2) */
 
 #define OHCI_CTRL_CBSR              (3 << 0)  /* Bit 0:  Control/bulk service ratio */
-#define OHCI_CTRL_PLE               (1 << 2)  /* Bit 1:  Periodic list enable */
-#define OHCI_CTRL_IE                (1 << 3)  /* Bit 2:  Isochronous enable */
-#define OHCI_CTRL_CLE               (1 << 4)  /* Bit 3:  Control list enable */
-#define OHCI_CTRL_BLE               (1 << 5)  /* Bit 4:  Bulk list enable */
+#define OHCI_CTRL_PLE               (1 << 2)  /* Bit 2:  Periodic list enable */
+#define OHCI_CTRL_IE                (1 << 3)  /* Bit 3:  Isochronous enable */
+#define OHCI_CTRL_CLE               (1 << 4)  /* Bit 4:  Control list enable */
+#define OHCI_CTRL_BLE               (1 << 5)  /* Bit 5:  Bulk list enable */
 #define OHCI_CTRL_HCFS_SHIFT        (6)       /* Bits 6-7: Host controller functional state */
 #define OHCI_CTRL_HCFS_MASK         (3 << OHCI_CTRL_HCFS_SHIFT)
 #  define OHCI_CTRL_HCFS_RESET      (0 << OHCI_CTRL_HCFS_SHIFT)
@@ -261,9 +261,9 @@
 #  define ED_CONTROL_D_IN          (2 << ED_CONTROL_D_SHIFT) /* IN */
 #  define ED_CONTROL_D_TD2         (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */
 
-#define ED_CONTROL_S               (1 << 13)  /* Bit 13: Speed (low) */
-#define ED_CONTROL_K               (1 << 14)  /* Bit 14: Skip */
-#define ED_CONTROL_F               (1 << 15)  /* Bit 15: Format (isochronous) */
+#define ED_CONTROL_SPPED_LOW       (1 << 13)  /* Bit 13: Speed (low) */
+#define ED_CONTROL_SKIP            (1 << 14)  /* Bit 14: Skip */
+#define ED_CONTROL_FORMAT_ISO      (1 << 15)  /* Bit 15: Format (isochronous) */
 #define ED_CONTROL_MPS_SHIFT       (16)       /* Bits 16-26: Maximum packet size */
 #define ED_CONTROL_MPS_MASK        (0x7ff << ED_CONTROL_MPS_SHIFT)
 
@@ -406,7 +406,7 @@ struct ohci_hcor
 
 /* Endpoint Descriptor Offsets (4.2.1) */
 
-struct ohci_ed_s
+struct ohci_ed
 {
   volatile  uint32_t ctrl;         /* ED status/control bits */
   volatile  uint32_t tailp;        /* TD Queue Tail Pointer (TailP) */
@@ -416,7 +416,7 @@ struct ohci_ed_s
 
 /* General Transfer Descriptor (4.3.1) */
 
-struct ohci_gtd_s
+struct ohci_gtd
 {
   volatile uint32_t ctrl;          /* TD status/control bits */
   volatile uint32_t cbp;           /* Current Buffer Pointer (CBP) */
@@ -426,7 +426,7 @@ struct ohci_gtd_s
 
 /* Isochronous Transfer Descriptor Offsets (4.3.2) */
 
-struct ohci_itd_s
+struct ohci_itd
 {
   volatile uint32_t ctrl;          /* TD status/control bits */
   volatile uint32_t bp0;           /* Buffer page 0 (BP0 */
@@ -437,7 +437,7 @@ struct ohci_itd_s
 
 /* Host Controller Communications Area Format (4.4.1) */
 
-struct ohci_hcca_s
+struct ohci_hcca
 {
   /* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */
 

Some files were not shown because too many files changed in this diff