Преглед изворни кода

Update cherryusb to v1.6.1#11362

sakumisu пре 2 часа
родитељ
комит
3d2dc22c58
98 измењених фајлова са 2111 додато и 3063 уклоњено
  1. 1 1
      bsp/bouffalo_lab/bl61x/board/cherryusb_port.c
  2. 6 1
      bsp/bouffalo_lab/bl61x/board/usb_config.h
  3. 0 41
      bsp/hpmicro/hpm6750evk/board/cherryusb_port.c
  4. 1 1
      bsp/hpmicro/hpm6750evk2/board/cherryusb_port.c
  5. 6 1
      bsp/hpmicro/hpm6750evk2/board/usb_config.h
  6. 1 1
      bsp/nxp/mcx/mcxn/frdm-mcxn947/board/cherryusb_port.c
  7. 6 1
      bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb_config.h
  8. 28 10
      components/drivers/usb/cherryusb/Kconfig
  9. 67 73
      components/drivers/usb/cherryusb/README.md
  10. 49 61
      components/drivers/usb/cherryusb/README_zh.md
  11. 18 6
      components/drivers/usb/cherryusb/SConscript
  12. 1 1
      components/drivers/usb/cherryusb/VERSION
  13. 9 15
      components/drivers/usb/cherryusb/cherryusb.cmake
  14. 1 0
      components/drivers/usb/cherryusb/cherryusb_config_template.h
  15. 2 4
      components/drivers/usb/cherryusb/class/adb/usbd_adb.c
  16. 4 4
      components/drivers/usb/cherryusb/class/audio/usb_audio.h
  17. 4 12
      components/drivers/usb/cherryusb/class/audio/usbd_audio.c
  18. 23 2
      components/drivers/usb/cherryusb/class/audio/usbh_audio.c
  19. 22 4
      components/drivers/usb/cherryusb/class/cdc/usb_cdc.h
  20. 1 2
      components/drivers/usb/cherryusb/class/cdc/usbd_cdc_acm.c
  21. 0 1
      components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c
  22. 30 27
      components/drivers/usb/cherryusb/class/dfu/usb_dfu.h
  23. 296 440
      components/drivers/usb/cherryusb/class/dfu/usbd_dfu.c
  24. 8 6
      components/drivers/usb/cherryusb/class/dfu/usbd_dfu.h
  25. 5 5
      components/drivers/usb/cherryusb/class/gamepad/usbd_gamepad.c
  26. 0 1
      components/drivers/usb/cherryusb/class/hid/usbd_hid.c
  27. 129 293
      components/drivers/usb/cherryusb/class/hid/usbh_hid.c
  28. 25 68
      components/drivers/usb/cherryusb/class/hid/usbh_hid.h
  29. 29 20
      components/drivers/usb/cherryusb/class/hub/usbh_hub.c
  30. 5 7
      components/drivers/usb/cherryusb/class/msc/usbd_msc.c
  31. 1 1
      components/drivers/usb/cherryusb/class/serial/usbh_ch34x.c
  32. 1 1
      components/drivers/usb/cherryusb/class/serial/usbh_ftdi.c
  33. 8 98
      components/drivers/usb/cherryusb/class/serial/usbh_serial.c
  34. 1 8
      components/drivers/usb/cherryusb/class/serial/usbh_serial.h
  35. 172 0
      components/drivers/usb/cherryusb/class/vendor/display/usbd_display.c
  36. 51 0
      components/drivers/usb/cherryusb/class/vendor/display/usbd_display.h
  37. 0 23
      components/drivers/usb/cherryusb/class/video/usbd_video.c
  38. 18 1
      components/drivers/usb/cherryusb/class/video/usbh_video.c
  39. 10 2
      components/drivers/usb/cherryusb/class/video/usbh_video.h
  40. 0 5
      components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c
  41. 148 0
      components/drivers/usb/cherryusb/common/usb_mempool.h
  42. 1 0
      components/drivers/usb/cherryusb/common/usb_osal.h
  43. 494 0
      components/drivers/usb/cherryusb/common/usb_ringbuffer.h
  44. 2 2
      components/drivers/usb/cherryusb/common/usb_version.h
  45. 3 4
      components/drivers/usb/cherryusb/core/usbd_core.c
  46. 2 0
      components/drivers/usb/cherryusb/core/usbd_core.h
  47. 8 7
      components/drivers/usb/cherryusb/core/usbh_core.c
  48. 3 1
      components/drivers/usb/cherryusb/core/usbh_core.h
  49. 1 1
      components/drivers/usb/cherryusb/core/usbotg_core.c
  50. 1 1
      components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c
  51. 1 1
      components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c
  52. 1 1
      components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c
  53. 1 1
      components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c
  54. 1 1
      components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c
  55. 1 1
      components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c
  56. 1 1
      components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c
  57. 36 44
      components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c
  58. 1 1
      components/drivers/usb/cherryusb/demo/cdc_acm_mavlink_template.c
  59. 1 1
      components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c
  60. 1 1
      components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c
  61. 1 1
      components/drivers/usb/cherryusb/demo/cdc_acm_rttchardev_template.c
  62. 1 1
      components/drivers/usb/cherryusb/demo/cdc_acm_template.c
  63. 2 2
      components/drivers/usb/cherryusb/demo/cdc_ecm_template.c
  64. 1 1
      components/drivers/usb/cherryusb/demo/cdc_rndis_template.c
  65. 0 372
      components/drivers/usb/cherryusb/demo/dfu_st_cubemx_main.c
  66. 52 9
      components/drivers/usb/cherryusb/demo/dfu_template.c
  67. 3 0
      components/drivers/usb/cherryusb/demo/display/README.md
  68. 145 0
      components/drivers/usb/cherryusb/demo/display/usbdisplay_template.c
  69. 1 1
      components/drivers/usb/cherryusb/demo/gamepad_template.c
  70. 1 1
      components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c
  71. 1 1
      components/drivers/usb/cherryusb/demo/hid_keyboard_template.c
  72. 37 45
      components/drivers/usb/cherryusb/demo/hid_mouse_template.c
  73. 36 44
      components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c
  74. 1 1
      components/drivers/usb/cherryusb/demo/midi_template.c
  75. 7 46
      components/drivers/usb/cherryusb/demo/msc_ram_template.c
  76. 1 1
      components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c
  77. 1 1
      components/drivers/usb/cherryusb/demo/video_static_h264_template.c
  78. 1 1
      components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c
  79. 1 1
      components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c
  80. 1 1
      components/drivers/usb/cherryusb/demo/webusb_hid_template.c
  81. 1 1
      components/drivers/usb/cherryusb/demo/winusb1.0_template.c
  82. 1 1
      components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c
  83. 1 1
      components/drivers/usb/cherryusb/demo/winusb2.0_template.c
  84. 1 1
      components/drivers/usb/cherryusb/idf_component.yml
  85. 5 0
      components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c
  86. 0 35
      components/drivers/usb/cherryusb/platform/rtthread/usb_check.c
  87. 0 53
      components/drivers/usb/cherryusb/platform/rtthread/usb_msh.c
  88. 0 156
      components/drivers/usb/cherryusb/platform/rtthread/usbd_adb_shell.c
  89. 0 275
      components/drivers/usb/cherryusb/platform/rtthread/usbd_serial.c
  90. 0 191
      components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c
  91. 0 469
      components/drivers/usb/cherryusb/platform/rtthread/usbh_lwip.c
  92. 1 1
      components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c
  93. 10 4
      components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c
  94. 2 2
      components/drivers/usb/cherryusb/port/dwc2/usb_glue_infineon.c
  95. 10 3
      components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c
  96. 33 12
      components/drivers/usb/cherryusb/port/hpmicro/usb_dc_hpm.c
  97. 1 0
      components/drivers/usb/cherryusb/port/musb/README.md
  98. 4 11
      components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c

+ 1 - 1
bsp/bouffalo_lab/bl61x/board/cherryusb_port.c

@@ -30,7 +30,7 @@ INIT_COMPONENT_EXPORT(cherryusb_devinit);
 
 int cherryusb_hostinit(void)
 {
-    usbh_initialize(0, 0x20072000);
+    usbh_initialize(0, 0x20072000, NULL);
     return 0;
 }
 INIT_COMPONENT_EXPORT(cherryusb_hostinit);

+ 6 - 1
bsp/bouffalo_lab/bl61x/board/usb_config.h

@@ -160,11 +160,12 @@
 #define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
 #define CONFIG_USBHOST_MAX_ENDPOINTS        4
 
-#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
+#define CONFIG_USBHOST_MAX_SERIAL_CLASS  4
 #define CONFIG_USBHOST_MAX_HID_CLASS     4
 #define CONFIG_USBHOST_MAX_MSC_CLASS     2
 #define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
 #define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+//#define CONFIG_USBHOST_MAX_XBOX_CLASS    2
 
 #define CONFIG_USBHOST_DEV_NAMELEN 16
 
@@ -191,6 +192,10 @@
 #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
 #endif
 
+#ifndef CONFIG_USBHOST_SERIAL_RX_SIZE
+#define CONFIG_USBHOST_SERIAL_RX_SIZE 2048
+#endif
+
 #ifndef CONFIG_USBHOST_MSC_TIMEOUT
 #define CONFIG_USBHOST_MSC_TIMEOUT 5000
 #endif

+ 0 - 41
bsp/hpmicro/hpm6750evk/board/cherryusb_port.c

@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2024/04/23     sakumisu    first version
- */
-#include <rtthread.h>
-#include <board.h>
-
-/* low level init here, this has implemented in cherryusb */
-
-/* low level deinit here, this has implemented in cherryusb */
-
-#ifdef RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
-int cherryusb_devinit(void)
-{
-    extern void msc_ram_init(uint8_t busid, uintptr_t reg_base);
-
-    board_init_usb_pins();
-
-    msc_ram_init(0, HPM_USB0_BASE);
-    return 0;
-}
-INIT_COMPONENT_EXPORT(cherryusb_devinit);
-#endif
-
-#ifdef RT_CHERRYUSB_HOST
-#include "usbh_core.h"
-
-int cherryusb_hostinit(void)
-{
-    board_init_usb_pins();
-
-    usbh_initialize(0, HPM_USB0_BASE);
-    return 0;
-}
-INIT_COMPONENT_EXPORT(cherryusb_hostinit);
-#endif

+ 1 - 1
bsp/hpmicro/hpm6750evk2/board/cherryusb_port.c

@@ -34,7 +34,7 @@ int cherryusb_hostinit(void)
 {
     board_init_usb_pins();
 
-    usbh_initialize(0, HPM_USB0_BASE);
+    usbh_initialize(0, HPM_USB0_BASE, NULL);
     return 0;
 }
 INIT_COMPONENT_EXPORT(cherryusb_hostinit);

+ 6 - 1
bsp/hpmicro/hpm6750evk2/board/usb_config.h

@@ -157,11 +157,12 @@
 #define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
 #define CONFIG_USBHOST_MAX_ENDPOINTS        4
 
-#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
+#define CONFIG_USBHOST_MAX_SERIAL_CLASS  4
 #define CONFIG_USBHOST_MAX_HID_CLASS     4
 #define CONFIG_USBHOST_MAX_MSC_CLASS     2
 #define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
 #define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+//#define CONFIG_USBHOST_MAX_XBOX_CLASS    2
 
 #define CONFIG_USBHOST_DEV_NAMELEN 16
 
@@ -188,6 +189,10 @@
 #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
 #endif
 
+#ifndef CONFIG_USBHOST_SERIAL_RX_SIZE
+#define CONFIG_USBHOST_SERIAL_RX_SIZE 2048
+#endif
+
 #ifndef CONFIG_USBHOST_MSC_TIMEOUT
 #define CONFIG_USBHOST_MSC_TIMEOUT 5000
 #endif

+ 1 - 1
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/cherryusb_port.c

@@ -30,7 +30,7 @@ INIT_COMPONENT_EXPORT(cherryusb_devinit);
 
 int cherryusb_hostinit(void)
 {
-    usbh_initialize(0, USBHS1__USBC_BASE);
+    usbh_initialize(0, USBHS1__USBC_BASE, NULL);
     return 0;
 }
 INIT_COMPONENT_EXPORT(cherryusb_hostinit);

+ 6 - 1
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb_config.h

@@ -155,11 +155,12 @@
 #define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
 #define CONFIG_USBHOST_MAX_ENDPOINTS        4
 
-#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
+#define CONFIG_USBHOST_MAX_SERIAL_CLASS  4
 #define CONFIG_USBHOST_MAX_HID_CLASS     4
 #define CONFIG_USBHOST_MAX_MSC_CLASS     2
 #define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
 #define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+//#define CONFIG_USBHOST_MAX_XBOX_CLASS    2
 
 #define CONFIG_USBHOST_DEV_NAMELEN 16
 
@@ -186,6 +187,10 @@
 #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
 #endif
 
+#ifndef CONFIG_USBHOST_SERIAL_RX_SIZE
+#define CONFIG_USBHOST_SERIAL_RX_SIZE 2048
+#endif
+
 #ifndef CONFIG_USBHOST_MSC_TIMEOUT
 #define CONFIG_USBHOST_MSC_TIMEOUT 5000
 #endif

+ 28 - 10
components/drivers/usb/cherryusb/Kconfig

@@ -139,11 +139,26 @@ if RT_USING_CHERRYUSB
             prompt "Enable usb dfu device"
             default n
 
+        config RT_CHERRYUSB_DEVICE_DISPLAY
+            bool
+            prompt "Enable usb display device"
+            default n
+
         config RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
             bool
             prompt "Enable chardev for cdc acm device"
             default n
 
+        config RT_CHERRYUSB_DEVICE_MSC_BLKDEV
+            bool
+            prompt "Enable blkdev for msc device"
+            default n
+
+        config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
+            string "usb device msc block device name"
+            depends on RT_CHERRYUSB_DEVICE_MSC_BLKDEV
+            default "sd0"
+
         config CONFIG_USBDEV_REQUEST_BUFFER_LEN
             int
             prompt "Set device control transfer max buffer size"
@@ -184,7 +199,7 @@ if RT_USING_CHERRYUSB
             config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
                 bool
                 prompt "msc_blkdev"
-                depends on RT_CHERRYUSB_DEVICE_MSC
+                depends on RT_CHERRYUSB_DEVICE_MSC && RT_CHERRYUSB_DEVICE_MSC_BLKDEV
             config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
                 bool
                 prompt "hid_keyboard"
@@ -221,6 +236,10 @@ if RT_USING_CHERRYUSB
                 bool
                 prompt "cdc_ncm"
                 depends on RT_CHERRYUSB_DEVICE_CDC_NCM
+            config RT_CHERRYUSB_DEVICE_TEMPLATE_DFU
+                bool
+                prompt "dfu"
+                depends on RT_CHERRYUSB_DEVICE_DFU
             config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
                 bool
                 prompt "cdc_acm_msc"
@@ -243,6 +262,10 @@ if RT_USING_CHERRYUSB
                 bool
                 prompt "webusb_hid"
                 depends on RT_CHERRYUSB_DEVICE_HID
+            config RT_CHERRYUSB_DEVICE_TEMPLATE_DISPLAY
+                bool
+                prompt "display"
+                depends on RT_CHERRYUSB_DEVICE_DISPLAY
             config RT_CHERRYUSB_DEVICE_TEMPLATE_ADB
                 bool
                 prompt "adb"
@@ -253,11 +276,6 @@ if RT_USING_CHERRYUSB
                 depends on RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
         endchoice
 
-        config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
-            string "usb device msc block device name"
-            depends on RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
-            default "sd0"
-
     endif
 
     menuconfig RT_CHERRYUSB_HOST
@@ -470,22 +488,22 @@ if RT_USING_CHERRYUSB
             default "/"
 
         menu "Select USB host template, please select class driver first"
-            config CONFIG_TEST_USBH_SERIAL
+            config RT_TEST_USBH_SERIAL
                 bool
                 prompt "demo for test seial, cannot enable this demo, you can use rt-thread device api to test"
                 default n
                 depends on CONFIG_USBHOST_SERIAL
-            config CONFIG_TEST_USBH_HID
+            config RT_TEST_USBH_HID
                 int
                 prompt "demo for test hid"
                 default 0
                 depends on RT_CHERRYUSB_HOST_HID
-            config CONFIG_TEST_USBH_MSC
+            config RT_TEST_USBH_MSC
                 bool
                 prompt "demo for test msc, cannot enable this demo, you can use rt-thread dfs api to test"
                 default n
                 depends on RT_CHERRYUSB_HOST_MSC
-            config CONFIG_TEST_USBH_NET
+            config RT_TEST_USBH_NET
                 bool
                 prompt "demo for test net, cannot enable this demo, you can use lwip api to test"
                 default n

+ 67 - 73
components/drivers/usb/cherryusb/README.md

@@ -14,31 +14,31 @@ CherryUSB is a tiny and beautiful, high performance and portable USB host and de
 
 ## Why choose CherryUSB
 
-### Easy to study USB
+### Easy to Learn USB
 
-In order to make it easier for users to learn USB basics, enumeration, driver loading and IP drivers, the code has been written with the following advantages:
+To facilitate user learning of USB fundamentals, enumeration, driver loading, and IP drivers, the written code has the following advantages:
 
-- Lean code, simple logic, no complex C syntax
-- Tree-based programming with cascading code
-- Class-drivers and porting-drivers are templating and simplification
-- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
+- Streamlined code with simple logic and no complex C language syntax
+- Tree-structured programming with progressive code layers
+- Templated and simplified Class drivers and porting drivers
+- Clear API categorization (Device: initialization, class registration, command callbacks, data transmission; Host: initialization, class discovery, data transmission)
 
-### Easy to use USB
+### Easy to Use USB
 
-In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
+To facilitate user interaction with USB interfaces, considering users’ familiarity with UART and DMA, the designed data transmission interface has the following advantages:
 
-- Equivalent to using uart tx dma/uart rx dma
-- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does it)
+- Equivalent to using UART TX DMA/UART RX DMA
+- No length restrictions on transmission/reception; users don’t need to worry about USB packetization (porting drivers handle packetization)
 
-### Easy to bring out USB performance
+### Easy to Achieve USB Performance
 
-Taking into account USB performance issues and trying to achieve the theoretical bandwidth of the USB hardware, the design of the data transceiver class interface has the following advantages:
+Considering USB performance requirements to reach theoretical USB hardware bandwidth, the designed data transmission interface has the following advantages:
 
-- Porting drivers directly to registers, no abstraction layer encapsulation
+- Porting drivers directly interface with registers without abstraction layer encapsulation
 - Memory zero copy
-- If IP has DMA then uses DMA mode (DMA with hardware packetization)
-- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
-- Packetization is handled in interrupt
+- DMA mode used when IP supports DMA (DMA provides hardware packetization functionality)
+- No length restrictions, facilitating hardware DMA interfacing and maximizing DMA advantages
+- Packetization handled in interrupt context
 
 Performance show:https://cherryusb.cherry-embedded.org/show/
 
@@ -70,11 +70,13 @@ CherryUSB Device Stack has the following functions:
 - Support Mass Storage Class (MSC)
 - Support USB VIDEO CLASS (UVC1.0, UVC1.5)
 - Support USB AUDIO CLASS (UAC1.0, UAC2.0)
+- Support Remote NDIS (RNDIS)
 - Support Device Firmware Upgrade CLASS (DFU)
 - Support USB MIDI CLASS (MIDI)
-- Support Remote NDIS (RNDIS)
 - Support Media Transfer Protocol (MTP)
+- Support Test and Measurement Class (TMC)
 - Support WINUSB1.0, WINUSB2.0, WEBUSB, BOS
+- Support Vendor display ([xfz1986_usb_graphic_driver](https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display))
 - Support Vendor class
 - Support UF2
 - Support Android Debug Bridge (Only support shell)
@@ -84,15 +86,18 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2, disable log):
 
 |   file        |  FLASH (Byte)  |  No Cache RAM (Byte)      |  RAM (Byte)   |  Heap (Byte)     |
 |:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
-|usbd_core.c    |  ~4500          | (512(default) + 320) * bus | 0           | 0                |
-|usbd_cdc_acm.c |  ~900           | 0                         | 0            | 0                |
-|usbd_msc.c     |  ~5000          | (128 + 512(default)) * bus | 16 * bus    | 0                |
-|usbd_hid.c     |  ~300           | 0                         | 0            | 0                |
-|usbd_audio.c   |  ~4000          | 0                         | 0            | 0                |
-|usbd_video.c   |  ~7000          | 0                         | 132 * bus    | 0                |
-|usbd_rndis.c   |  ~2500          | 2 * 1580(default)+156+8   | 80           | 0                |
-|usbd_cdc_ecm.c |  ~900           | 2 * 1514(default)+16      | 42           | 0                |
+|usbd_core.c    |  ~4000          | (512(default) + 320) * bus | 8           | 0                |
+|usbd_cdc_acm.c |  ~400           | 0                         | 0            | 0                |
+|usbd_msc.c     |  ~3200          | (128 + 512(default)) * bus | 16 * bus    | 0                |
+|usbd_hid.c     |  ~200           | 0                         | 0            | 0                |
+|usbd_audio.c   |  ~1300          | 0                         | 8 * bus      | 0                |
+|usbd_video.c   |  ~2500          | 0                         | 124 * bus    | 0                |
+|usbd_rndis.c   |  ~2000          | 2 * 1580(default)+156+8   | 76           | 0                |
+|usbd_cdc_ecm.c |  ~1500          | 2 * 1514(default)+16      | 42           | 0                |
 |usbd_mtp.c     |  ~9000          | 2048(default)+128         | sizeof(struct mtp_object) * n| 0 |
+|usbd_dfu.c     |  ~800           | 0                         | 1                           | 0 |
+
+![usbdevice_usage](docs/assets/usbdevice_usage.png)
 
 ## Host Stack Overview
 
@@ -111,6 +116,7 @@ CherryUSB Host Stack has the following functions:
 - Support USB Video CLASS (UVC1.0, UVC1.5)
 - Support USB Audio CLASS (UAC1.0)
 - Support Remote NDIS (RNDIS)
+- Support Device Firmware Upgrade CLASS (DFU)
 - Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
 - Support Vendor Serial Class(CH34X、CP210X、PL2303、FTDI、GSM)
 - Support Vendor network Class(RTL8152、AX88772)
@@ -124,19 +130,27 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2, disable log):
 
 |   file        |  FLASH (Byte)  |  No Cache RAM (Byte)            |  RAM (Byte)                 |  Heap (Byte) |
 |:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
-|usbh_core.c    |  ~4500 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus     | raw_config_desc |
-|usbh_hub.c     |  ~3500          | (32 + 4 * (1+x)) * bus    | 12 + sizeof(struct usbh_hub) * x   | 0          |
-|usbh_cdc_acm.c |  ~600           | 7 * x            | 4  + sizeof(struct usbh_cdc_acm) * x        | 0          |
-|usbh_msc.c     |  ~2000          | 128 * x            | 4  + sizeof(struct usbh_msc) * x          | 0          |
-|usbh_hid.c     |  ~800           | 64 * x           | 4  + sizeof(struct usbh_hid) * x            | 0          |
-|usbh_video.c   |  ~5000          | 128 * x           | 4  + sizeof(struct usbh_video) * x         | 0          |
-|usbh_audio.c   |  ~4000          | 128 * x           | 4  + sizeof(struct usbh_audio) * x         | 0          |
+|usbh_core.c    |  ~4000 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus     | raw_config_desc |
+|usbh_hub.c     |  ~3000          | (32 + 4 * (1+x)) * bus    | 12 + sizeof(struct usbh_hub) * x   | 0          |
+|usbh_msc.c     |  ~1500          | 128 * x            | 4  + sizeof(struct usbh_msc) * x          | 0          |
+|usbh_hid.c     |  ~2000          | 64 * x           | 4  + sizeof(struct usbh_hid) * x            | 0          |
+|usbh_video.c   |  ~2500          | 128 * x           | 4  + sizeof(struct usbh_video) * x         | 0          |
+|usbh_audio.c   |  ~3000          | 128 * x           | 4  + sizeof(struct usbh_audio) * x         | 0          |
 |usbh_rndis.c   |  ~3000          | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1         | 0          |
 |usbh_cdc_ecm.c |  ~1500          | 2 * 1514 + 16           | sizeof(struct usbh_cdc_ecm) * 1      | 0          |
 |usbh_cdc_ncm.c |  ~2000          | 2 * 2048(default) + 16 + 32   | sizeof(struct usbh_cdc_ncm) * 1| 0          |
 |usbh_bluetooth.c |  ~1000        | 2 * 2048(default)   | sizeof(struct usbh_bluetooth) * 1        | 0          |
-|usbh_asix.c    |  ~7000          | 2 * 2048(default) + 16 + 32  | sizeof(struct usbh_asix) * 1    | 0          |
-|usbh_rtl8152.c |  ~9000          | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1    | 0          |
+|usbh_asix.c    |  ~3500          | 2 * 2048(default) + 16 + 32  | sizeof(struct usbh_asix) * 1    | 0          |
+|usbh_rtl8152.c |  ~5500          | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1    | 0          |
+|usbh_serial.c  |  ~3000          | (512 * 2 + 32 * 2) * x            | sizeof(struct usbh_serial) * x (2048 default)       | 0          |
+|usbh_cdc_acm.c |  ~1000          | 0            | 0        | 0          |
+|usbh_ch340.c   |  ~1200          | 0            | 0        | 0          |
+|usbh_ftdi.c    |  ~1200          | 0            | 0        | 0          |
+|usbh_cp2102.c  |  ~2200          | 0            | 0        | 0          |
+|usbh_pl2303.c  |  ~2500          | 0            | 0        | 0          |
+|usbh_gsm.c     |  ~300           | 0            | 0        | 0          |
+
+![usbhost_usage](docs/assets/usbhost_usage.png)
 
 Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
 
@@ -176,55 +190,35 @@ Only standard and commercial USB IP are listed.
 |  CDNS3(cadence)  |  CDNS3     | XHCI     |  ×   |
 |  DWC3(synopsys)  |  DWC3      | XHCI     |  ×   |
 
-## Documentation Tutorial
-
-Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/).
-
-## Video Tutorial
-
-CherryUSB Cheese (>= V1.4.3): https://www.bilibili.com/cheese/play/ss707687201 .
-
-## Descriptor Generator Tool
+## Resources
 
-Cherry Descriptor: https://desc.cherry-embedded.org/en
+### Getting Started
 
-## Demo Repo
+- 📖 [CherryUSB Documentation](https://cherryusb.readthedocs.io/en/latest/)
+- 💻 [CherryUSB Demo Repo](https://cherryusb.readthedocs.io/en/latest/quick_start/demo.html)
+- 📺 [CherryUSB Cheese(>= V1.4.3)](https://www.bilibili.com/cheese/play/ss707687201)
 
-|   Manufacturer       |  CHIP or Series    | USB IP| Repo Url | Support version     | Note |
-|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
-|Bouffalolab    |  BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Official |
-|ST             |  STM32F1x/STM32F4/STM32H7 | fsdev/dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Community |
-|HPMicro        |  HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Official |
-|Essemi         |  ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Official |
-|Phytium        |  e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0  | Official |
-|Artinchip      |  d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest  | Official |
-|Espressif      |  esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)/[espressif](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb)|<= latest | Official |
-|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Official |
-|Actionstech    |  ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Official |
-|SiFli          |  SF32LB5x | musb |[SiFli_sdk](https://github.com/OpenSiFli/SiFli-SDK)|>=1.5.0 | Official |
-|NXP            |  mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Community |
-|Nationstech    |  n32h4x | dwc2 |[nation_repo](https://github.com/CherryUSB/cherryusb_nation)|>=1.5.0 | Official ongoing |
-|Raspberry pi   |  rp2040/rp2350 | rp2040 |[pico-sdk](https://github.com/CherryUSB/pico-sdk)|<= latest | Official ongoing |
-|AllwinnerTech  |  F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | no more update |
-|Bekencorp      |  bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | Official |
-|Sophgo         |  cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | Official |
-|WCH            |  CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2/>=v1.5.0 | no more update |
+### Tools
 
-## Package Support
+- 🌐 [Cherry Descriptor Generator](https://desc.cherry-embedded.org/en)
+- 🔧 [CDC Speed Test](https://github.com/cherry-embedded/CherryUSB/blob/master/tools/test_srcipts/test_cdc_speed.py)
+- 🔧 [HID Custom Test](https://github.com/cherry-embedded/CherryUSB/blob/master/tools/test_srcipts/test_hid_inout.py)
 
-CherryUSB package is available as follows:
+### Community Or Commercial Support
 
-- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
-- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
-- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
+- 💬 [CherryUSB QQ Group](https://qm.qq.com/q/w3GnM4bkfA)
+- 💬 [CherryUSB discord](https://discord.com/invite/wFfvrSAey8)
+- 🙋🏽 [Commercial Support](https://cherryusb.readthedocs.io/en/latest/support/index.html)
 
-## Commercial Support
+### Package Support
 
-Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
+- 🌐 [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
+- 🌐 [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
+- 🌐 [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
 
-## Contact
+### Mirror URL
 
-CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
+- [AtomGit](https://atomgit.com/cherry-embedded/CherryUSB)
 
 ## Company Support
 

+ 49 - 61
components/drivers/usb/cherryusb/README_zh.md

@@ -70,11 +70,13 @@ CherryUSB Device 协议栈当前实现以下功能:
 - 支持 Mass Storage Class (MSC)
 - 支持 USB VIDEO CLASS (UVC1.0、UVC1.5)
 - 支持 USB AUDIO CLASS (UAC1.0、UAC2.0)
+- 支持 Remote NDIS (RNDIS)
 - 支持 Device Firmware Upgrade CLASS (DFU)
 - 支持 USB MIDI CLASS (MIDI)
-- 支持 Remote NDIS (RNDIS)
 - 支持 Media Transfer Protocol (MTP)
+- 支持 Test and Measurement Class (TMC)
 - 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
+- 支持 Vendor display ([xfz1986_usb_graphic_driver](https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display))
 - 支持 Vendor 类 class
 - 支持 UF2
 - 支持 Android Debug Bridge (Only support shell)
@@ -84,15 +86,16 @@ CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
 
 |   file        |  FLASH (Byte)  |  No Cache RAM (Byte)      |  RAM (Byte)   |  Heap (Byte)     |
 |:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
-|usbd_core.c    |  ~4500          | (512(default) + 320) * bus | 0           | 0                |
-|usbd_cdc_acm.c |  ~900           | 0                         | 0            | 0                |
-|usbd_msc.c     |  ~5000          | (128 + 512(default)) * bus | 16 * bus    | 0                |
-|usbd_hid.c     |  ~300           | 0                         | 0            | 0                |
-|usbd_audio.c   |  ~4000          | 0                         | 0            | 0                |
-|usbd_video.c   |  ~7000          | 0                         | 132 * bus    | 0                |
-|usbd_rndis.c   |  ~2500          | 2 * 1580(default)+156+8   | 80           | 0                |
-|usbd_cdc_ecm.c |  ~900           | 2 * 1514(default)+16      | 42           | 0                |
+|usbd_core.c    |  ~4000          | (512(default) + 320) * bus | 8           | 0                |
+|usbd_cdc_acm.c |  ~400           | 0                         | 0            | 0                |
+|usbd_msc.c     |  ~3200          | (128 + 512(default)) * bus | 16 * bus    | 0                |
+|usbd_hid.c     |  ~200           | 0                         | 0            | 0                |
+|usbd_audio.c   |  ~1300          | 0                         | 8 * bus      | 0                |
+|usbd_video.c   |  ~2500          | 0                         | 124 * bus    | 0                |
+|usbd_rndis.c   |  ~2000          | 2 * 1580(default)+156+8   | 76           | 0                |
+|usbd_cdc_ecm.c |  ~1500          | 2 * 1514(default)+16      | 42           | 0                |
 |usbd_mtp.c     |  ~9000          | 2048(default)+128         | sizeof(struct mtp_object) * n| 0 |
+|usbd_dfu.c     |  ~800           | 0                         | 1                           | 0 |
 
 ## Host 协议栈简介
 
@@ -108,9 +111,10 @@ CherryUSB Host 协议栈当前实现以下功能:
 - 支持 Communication Device Class (CDC_ACM, CDC_ECM, CDC_NCM)
 - 支持 Human Interface Device (HID)
 - 支持 Mass Storage Class (MSC)
-- Support USB Video CLASS (UVC1.0、UVC1.5)
-- Support USB Audio CLASS (UAC1.0)
+- 支持 USB Video CLASS (UVC1.0、UVC1.5)
+- 支持 USB Audio CLASS (UAC1.0)
 - 支持 Remote NDIS (RNDIS)
+- 支持 Device Firmware Upgrade CLASS (DFU)
 - 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
 - 支持 Vendor Serial 类(CH34X、CP210X、PL2303、FTDI、GSM)
 - 支持 Vendor network 类(RTL8152、AX88772)
@@ -124,19 +128,25 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2,关闭 log)
 
 |   file        |  FLASH (Byte)  |  No Cache RAM (Byte)            |  RAM (Byte)                 |  Heap (Byte) |
 |:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
-|usbh_core.c    |  ~4500 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus     | raw_config_desc |
-|usbh_hub.c     |  ~3500          | (32 + 4 * (1+x)) * bus    | 12 + sizeof(struct usbh_hub) * x   | 0          |
-|usbh_cdc_acm.c |  ~600           | 7 * x            | 4  + sizeof(struct usbh_cdc_acm) * x        | 0          |
-|usbh_msc.c     |  ~2000          | 128 * x            | 4  + sizeof(struct usbh_msc) * x          | 0          |
-|usbh_hid.c     |  ~800           | 64 * x           | 4  + sizeof(struct usbh_hid) * x            | 0          |
-|usbh_video.c   |  ~5000          | 128 * x           | 4  + sizeof(struct usbh_video) * x         | 0          |
-|usbh_audio.c   |  ~4000          | 128 * x           | 4  + sizeof(struct usbh_audio) * x         | 0          |
+|usbh_core.c    |  ~4000 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus     | raw_config_desc |
+|usbh_hub.c     |  ~3000          | (32 + 4 * (1+x)) * bus    | 12 + sizeof(struct usbh_hub) * x   | 0          |
+|usbh_msc.c     |  ~1500          | 128 * x            | 4  + sizeof(struct usbh_msc) * x          | 0          |
+|usbh_hid.c     |  ~2000          | 64 * x           | 4  + sizeof(struct usbh_hid) * x            | 0          |
+|usbh_video.c   |  ~2500          | 128 * x           | 4  + sizeof(struct usbh_video) * x         | 0          |
+|usbh_audio.c   |  ~3000          | 128 * x           | 4  + sizeof(struct usbh_audio) * x         | 0          |
 |usbh_rndis.c   |  ~3000          | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1         | 0          |
 |usbh_cdc_ecm.c |  ~1500          | 2 * 1514 + 16           | sizeof(struct usbh_cdc_ecm) * 1      | 0          |
 |usbh_cdc_ncm.c |  ~2000          | 2 * 2048(default) + 16 + 32   | sizeof(struct usbh_cdc_ncm) * 1| 0          |
 |usbh_bluetooth.c |  ~1000        | 2 * 2048(default)   | sizeof(struct usbh_bluetooth) * 1        | 0          |
-|usbh_asix.c    |  ~7000          | 2 * 2048(default) + 16 + 32  | sizeof(struct usbh_asix) * 1    | 0          |
-|usbh_rtl8152.c |  ~9000          | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1    | 0          |
+|usbh_asix.c    |  ~3500          | 2 * 2048(default) + 16 + 32  | sizeof(struct usbh_asix) * 1    | 0          |
+|usbh_rtl8152.c |  ~5500          | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1    | 0          |
+|usbh_serial.c  |  ~3000          | (512 * 2 + 32 * 2) * x            | sizeof(struct usbh_serial) * x (2048 default)       | 0          |
+|usbh_cdc_acm.c |  ~1000          | 0            | 0        | 0          |
+|usbh_ch340.c   |  ~1200          | 0            | 0        | 0          |
+|usbh_ftdi.c    |  ~1200          | 0            | 0        | 0          |
+|usbh_cp2102.c  |  ~2200          | 0            | 0        | 0          |
+|usbh_pl2303.c  |  ~2500          | 0            | 0        | 0          |
+|usbh_gsm.c     |  ~300           | 0            | 0        | 0          |
 
 其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
 
@@ -176,57 +186,35 @@ x 受以下宏影响:
 |  CDNS3(cadence)  |  CDNS3     | XHCI     |  ×   |
 |  DWC3(synopsys)  |  DWC3      | XHCI     |  ×   |
 
-## 文档教程
-
-CherryUSB 快速入门、USB 基本概念、API 手册、Class 基本概念和例程,参考 [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)。
-
-## 视频教程
-
-CherryUSB 课程(>= V1.4.3):https://www.bilibili.com/cheese/play/ss707687201 。
-
-## 描述符生成工具
-
-Cherry Descriptor: https://desc.cherry-embedded.org/zh
+## Resources
 
-## 示例仓库
+### 快速开始
 
-|   Manufacturer       |  CHIP or Series    | USB IP| Repo Url | Support version     | Note |
-|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
-|Bouffalolab    |  BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Official |
-|ST             |  STM32F1x/STM32F4/STM32H7 | fsdev/dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Community |
-|HPMicro        |  HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Official |
-|Essemi         |  ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Official |
-|Phytium        |  e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0  | Official |
-|Artinchip      |  d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest  | Official |
-|Espressif      |  esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)/[espressif](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb)|<= latest | Official |
-|Kendryte       |  k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Official |
-|Actionstech    |  ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Official |
-|SiFli          |  SF32LB5x | musb |[SiFli_sdk](https://github.com/OpenSiFli/SiFli-SDK)|>=1.5.0 | Official |
-|NXP            |  mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Community |
-|Nationstech    |  n32h4x | dwc2 |[nation_repo](https://github.com/CherryUSB/cherryusb_nation)|>=1.5.0 | Official ongoing |
-|Raspberry pi   |  rp2040/rp2350 | rp2040 |[pico-sdk](https://github.com/CherryUSB/pico-sdk)|<= latest | Official ongoing |
-|AllwinnerTech  |  F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | no more update |
-|Bekencorp      |  bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | Official |
-|Sophgo         |  cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | Official |
-|WCH            |  CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2/>=v1.5.0 | no more update |
+- 📖 [CherryUSB Documentation](https://cherryusb.readthedocs.io/zh-cn/latest/)
+- 💻 [CherryUSB Demo Repo](https://cherryusb.readthedocs.io/zh-cn/latest/quick_start/demo.html)
+- 📺 [CherryUSB Cheese(>= V1.4.3)](https://www.bilibili.com/cheese/play/ss707687201)
 
-## 软件包支持
+### 工具
 
-CherryUSB 软件包可以通过以下方式获取:
+- 🌐 [Cherry Descriptor Generator](https://desc.cherry-embedded.org/zh)
+- 🔧 [CDC Speed Test](https://github.com/cherry-embedded/CherryUSB/blob/master/tools/test_srcipts/test_cdc_speed.py)
+- 🔧 [HID Custom Test](https://github.com/cherry-embedded/CherryUSB/blob/master/tools/test_srcipts/test_hid_inout.py)
 
-- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
-- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
-- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
+### 社区 Or 商业支持
 
-## 商业支持
+- 💬 [CherryUSB QQ Group](https://qm.qq.com/q/w3GnM4bkfA)
+- 💬 [CherryUSB discord](https://discord.com/invite/wFfvrSAey8)
+- 🙋🏽 [Commercial Support](https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html)
 
-参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html 。
+### 软件包
 
-## 联系
+- 🌐 [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
+- 🌐 [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
+- 🌐 [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
 
-CherryUSB QQ群:642693751
+### 镜像仓库
 
-CherryUSB 微信群:与我联系后邀请加入
+- [AtomGit](https://atomgit.com/cherry-embedded/CherryUSB)
 
 ## 支持企业
 

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

@@ -17,6 +17,8 @@ path += [cwd + '/class/dfu']
 path += [cwd + '/class/serial']
 path += [cwd + '/class/vendor/net']
 path += [cwd + '/class/vendor/wifi']
+path += [cwd + '/class/vendor/display']
+path += [cwd + '/class/vendor/xbox']
 src = []
 
 LIBS    = []
@@ -136,13 +138,17 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
         src += Glob('class/cdc/usbd_cdc_ncm.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_DFU']):
         src += Glob('class/dfu/usbd_dfu.c')
+    if GetDepend(['RT_CHERRYUSB_DEVICE_DISPLAY']):
+        src += Glob('class/vendor/display/usbd_display.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_ADB']):
         src += Glob('class/adb/usbd_adb.c')
         src += Glob('platform/rtthread/usbd_adb_shell.c')
 
     if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV']):
-        src += Glob('platform/rtthread/usbd_serial.c')
+        src += Glob('platform/rtthread/rt_usbd_serial.c')
 
+    if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_BLKDEV']):
+        src += Glob('platform/rtthread/rt_usbd_msc.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
         src += Glob('demo/cdc_acm_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC']) or GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
@@ -165,6 +171,8 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
         src += Glob('demo/cdc_ecm_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
         src += Glob('demo/cdc_ncm_template.c')
+    if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_DFU']):
+        src += Glob('demo/dfu_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
         src += Glob('demo/cdc_acm_msc_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
@@ -177,6 +185,8 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
         src += Glob('demo/winusb2.0_cdc_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_WEBUSB_HID']):
         src += Glob('demo/webusb_hid_template.c')
+    if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_DISPLAY']):
+        src += Glob('demo/display/usbdisplay_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_ADB']):
         src += Glob('demo/adb/usbd_adb_template.c')
     if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV']):
@@ -313,6 +323,8 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
         src += Glob('class/serial/usbh_cp210x.c')
     if GetDepend(['RT_CHERRYUSB_HOST_PL2303']):
         src += Glob('class/serial/usbh_pl2303.c')
+    if GetDepend(['RT_CHERRYUSB_HOST_XBOX']):
+        src += Glob('class/vendor/xbox/usbh_xbox.c')
 
     if GetDepend(['RT_TEST_USBH_HID']):
         CPPDEFINES+=['CONFIG_TEST_USBH_HID']
@@ -325,20 +337,20 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
         or GetDepend(['RT_CHERRYUSB_HOST_PL2303']) \
         or GetDepend(['RT_CHERRYUSB_HOST_GSM']):
         src += Glob('class/serial/usbh_serial.c')
-        src += Glob('platform/rtthread/usbh_rtserial.c')
+        src += Glob('platform/rtthread/rt_usbh_serial.c')
 
     if GetDepend('RT_USING_DFS') and GetDepend(['RT_CHERRYUSB_HOST_MSC']):
-       src += Glob('platform/rtthread/usbh_dfs.c')
+       src += Glob('platform/rtthread/rt_usbh_msc.c')
 
     if GetDepend('RT_CHERRYUSB_HOST_CDC_ECM') \
         or GetDepend('RT_CHERRYUSB_HOST_CDC_RNDIS') \
         or GetDepend('RT_CHERRYUSB_HOST_CDC_NCM') \
         or GetDepend('RT_CHERRYUSB_HOST_ASIX') \
         or GetDepend('RT_CHERRYUSB_HOST_RTL8152'):
-       src += Glob('platform/rtthread/usbh_lwip.c')
+       src += Glob('platform/rtthread/rt_usbh_lwip.c')
 
-src += Glob('platform/rtthread/usb_msh.c')
-src += Glob('platform/rtthread/usb_check.c')
+src += Glob('platform/rtthread/rt_usb_msh.c')
+src += Glob('platform/rtthread/rt_usb_check.c')
 
 group = DefineGroup('UsbStack', src, depend = ['RT_USING_CHERRYUSB'], LIBS = LIBS, LIBPATH=LIBPATH, CPPPATH = path, CPPDEFINES = CPPDEFINES)
 

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

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

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

@@ -27,6 +27,7 @@
 # set(CONFIG_CHERRYUSB_HOST_ASIX 1)
 # set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
 # set(CONFIG_CHERRYUSB_HOST_DWC2_ST 1)
+# set(CONFIG_CHERRYUSB_HOST_XBOX 1)
 
 # set(CONFIG_CHERRYUSB_OSAL "freertos")
 # cmake-format: on
@@ -50,6 +51,8 @@ list(
     ${CMAKE_CURRENT_LIST_DIR}/class/serial
     ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
     ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
+    ${CMAKE_CURRENT_LIST_DIR}/class/vendor/display
+    ${CMAKE_CURRENT_LIST_DIR}/class/vendor/xbox
     ${CMAKE_CURRENT_LIST_DIR}/class/aoa
     ${CMAKE_CURRENT_LIST_DIR}/class/gamepad
 )
@@ -89,6 +92,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
     if(CONFIG_CHERRYUSB_DEVICE_GAMEPAD)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/gamepad/usbd_gamepad.c)
     endif()
+    if(CONFIG_CHERRYUSB_DEVICE_DISPLAY)
+        list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/display/usbd_display.c)
+    endif()
 
     if(CONFIG_CHERRYUSB_DEVICE_FSDEV_ST)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
@@ -256,6 +262,9 @@ if(CONFIG_CHERRYUSB_HOST)
     if(CONFIG_CHERRYUSB_HOST_AOA)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c)
     endif()
+    if(CONFIG_CHERRYUSB_HOST_XBOX)
+        list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/xbox/usbh_xbox.c)
+    endif()
 
     if(CONFIG_CHERRYUSB_HOST_CDC_ACM
     OR CONFIG_CHERRYUSB_HOST_CH34X
@@ -371,18 +380,3 @@ if(DEFINED CONFIG_CHERRYUSB_OSAL)
         list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_zephyr.c)
     endif()
 endif()
-
-if(CONFIG_CHERRYRB)
-    list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
-    list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
-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()

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

@@ -162,6 +162,7 @@
 #define CONFIG_USBHOST_MAX_MSC_CLASS     2
 #define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
 #define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+//#define CONFIG_USBHOST_MAX_XBOX_CLASS    2
 
 #define CONFIG_USBHOST_DEV_NAMELEN 16
 

+ 2 - 4
components/drivers/usb/cherryusb/class/adb/usbd_adb.c

@@ -114,10 +114,8 @@ void usbd_adb_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
     (void)ep;
 
     if (adb_client.common_state == ADB_STATE_READ_MSG) {
-        if (nbytes != sizeof(struct adb_msg)) {
-            USB_LOG_ERR("invalid adb msg size:%d\r\n", (unsigned int)nbytes);
-            return;
-        }
+        USB_ASSERT(nbytes == sizeof(struct adb_msg));
+        USB_ASSERT(rx_packet.msg.data_length <= sizeof(rx_packet.payload));
 
         USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
                      rx_packet.msg.command,

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

@@ -642,7 +642,7 @@ struct audio_cs_if_ac_feature_unit_descriptor {
     uint8_t bUnitID;
     uint8_t bSourceID;
     uint8_t bControlSize;
-    uint8_t bmaControls[1];
+    uint8_t bmaControls[33]; // variable
     uint8_t iFeature;
 } __PACKED;
 
@@ -1318,10 +1318,10 @@ struct audio_v2_control_range3_param_block {
 
 // clang-format on
 
-#define AUDIO_V2_AS_DESCRIPTOR_LEN            (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
+#define AUDIO_V2_AS_DESCRIPTOR_LEN             (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
 #define AUDIO_V2_AS_ALTSETTING0_DESCRIPTOR_LEN (0x09)
-#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_LEN (0x09 + 0x10 + 0x06 + 0x07 + 0x08)
-#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_LEN   (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
+#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_LEN  (0x09 + 0x10 + 0x06 + 0x07 + 0x08)
+#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_LEN    (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
 
 #define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
 #define AUDIO_SAMPLE_FREQ_3B(frq)  (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

+ 4 - 12
components/drivers/usb/cherryusb/class/audio/usbd_audio.c

@@ -32,7 +32,7 @@ static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_
         case AUDIO_EP_CONTROL_SAMPLING_FEQ:
             switch (setup->bRequest) {
                 case AUDIO_REQUEST_SET_CUR:
-                    memcpy((uint8_t *)&sampling_freq, *data, *len);
+                    memcpy((uint8_t *)&sampling_freq, *data, 3);
                     USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
                     usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
                     break;
@@ -49,7 +49,6 @@ static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_
 
             break;
         default:
-            USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
             return -1;
     }
     return 0;
@@ -109,7 +108,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 *len = 1;
                                 break;
                             default:
-                                USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
                                 return -1;
                         }
                     } else {
@@ -124,7 +122,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 }
                                 break;
                             default:
-                                //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
                                 return -1;
                         }
                     }
@@ -133,7 +130,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                     if (g_usbd_audio[busid].uac_version < 0x0200) {
                         switch (setup->bRequest) {
                             case AUDIO_REQUEST_SET_CUR:
-                                memcpy(&volume, *data, *len);
+                                memcpy(&volume, *data, 2);
                                 if (volume < 0x8000) {
                                     volume_db = volume / 256;
                                 } else {
@@ -169,7 +166,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 *len = 2;
                                 break;
                             default:
-                                USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
                                 return -1;
                         }
                     } else {
@@ -186,7 +182,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                     memcpy(*data, &volume, 2);
                                     *len = 2;
                                 } else {
-                                    memcpy(&volume, *data, *len);
+                                    memcpy(&volume, *data, 2);
                                     if (volume < 0x8000) {
                                         volume_db = volume / 256;
                                     } else {
@@ -207,14 +203,12 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 }
                                 break;
                             default:
-                                //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
                                 return -1;
                         }
                     }
                     break;
 
                 default:
-                    USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
                     return -1;
             }
             break;
@@ -229,7 +223,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                                 USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
                                 *len = 4;
                             } else {
-                                memcpy(&sampling_freq, *data, setup->wLength);
+                                memcpy(&sampling_freq, *data, 4);
                                 USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
                                 usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
                             }
@@ -247,7 +241,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                             }
                             break;
                         default:
-                            //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
                             return -1;
                     }
                     break;
@@ -261,7 +254,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
                     break;
 
                 default:
-                    //USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
                     return -1;
             }
             break;

+ 23 - 2
components/drivers/usb/cherryusb/class/audio/usbh_audio.c

@@ -59,7 +59,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
     uint16_t mps;
     int ret;
     uint8_t intf = 0xff;
-    uint8_t altsetting = 1;
+    uint8_t altsetting = 0xff;
 
     if (!audio_class || !audio_class->hport) {
         return -USB_ERR_INVAL;
@@ -88,9 +88,11 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
             }
         }
     }
-    return -USB_ERR_NODEV;
 
 freq_found:
+    if(altsetting == 0xff) {
+        return -USB_ERR_NODEV;
+    }
 
     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
     setup->bRequest = USB_REQUEST_SET_INTERFACE;
@@ -150,9 +152,11 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
     for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
         if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
             intf = audio_class->as_msg_table[i].stream_intf;
+            goto intf_found;
         }
     }
 
+intf_found:
     if (intf == 0xff) {
         return -USB_ERR_NODEV;
     }
@@ -208,9 +212,11 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
         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;
+            goto feature_found;
         }
     }
 
+feature_found:
     if (feature_id == 0xff) {
         return -USB_ERR_NODEV;
     }
@@ -322,9 +328,11 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
         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;
+            goto feature_found;
         }
     }
 
+feature_found:
     if (feature_id == 0xff) {
         return -USB_ERR_NODEV;
     }
@@ -404,6 +412,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
         switch (p[DESC_bDescriptorType]) {
             case USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
                 cur_iface_count = p[3];
+                USB_ASSERT(cur_iface_count <= CONFIG_USBHOST_AUDIO_MAX_STREAMS);
                 break;
             case USB_DESCRIPTOR_TYPE_INTERFACE:
                 cur_iface = p[INTF_DESC_bInterfaceNumber];
@@ -422,18 +431,26 @@ 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;
 
+                            USB_ASSERT(input_offset < CONFIG_USBHOST_AUDIO_MAX_STREAMS);
+
                             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;
 
+                            USB_ASSERT(output_offset < CONFIG_USBHOST_AUDIO_MAX_STREAMS);
+
                             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;
 
+                            USB_ASSERT(feature_unit_offset < CONFIG_USBHOST_AUDIO_MAX_STREAMS);
+                            USB_ASSERT(desc->bControlSize == 1);
+                            USB_ASSERT(desc->bLength <= sizeof(struct audio_cs_if_ac_feature_unit_descriptor));
+
                             memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
                             feature_unit_offset++;
                         } break;
@@ -452,6 +469,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                         } break;
                         case AUDIO_STREAMING_FORMAT_TYPE: {
                             struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
+
+                            USB_ASSERT(desc->bSamFreqType == 1);
+
                             audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].num_of_altsetting = (cur_alt_setting + 1);
                             memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, desc->bLength);
                         } break;
@@ -464,6 +484,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                 if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
                     if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) {
                         struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p;
+
                         audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].ep_attr = desc->bmAttributes;
                     }
                 }

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

@@ -550,8 +550,8 @@ struct cdc_ncm_ndp16 {
 
 #define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
 
-/*Length of template descriptor: 71 bytes*/
-#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
+/*Length of template descriptor: 79 bytes*/
+#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 9 + 7 + 7)
 // clang-format off
 #define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
     /* Interface Associate */                                                                  \
@@ -600,6 +600,15 @@ struct cdc_ncm_ndp16 {
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
     0x00,                                                  /* bAlternateSetting */             \
+    0x00,                                                  /* bNumEndpoints */                 \
+    CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
+    0x00,                                                  /* bInterfaceSubClass */            \
+    0x00,                                                  /* bInterfaceProtocol */            \
+    0x00,                                                  /* iInterface */                    \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
+    0x01,                                                  /* bAlternateSetting */             \
     0x02,                                                  /* bNumEndpoints */                 \
     CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
     0x00,                                                  /* bInterfaceSubClass */            \
@@ -619,8 +628,8 @@ struct cdc_ncm_ndp16 {
     0x00                                                   /* bInterval */
 // clang-format on
 
-/*Length of template descriptor: 77 bytes*/
-#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 7 + 7)
+/*Length of template descriptor: 86 bytes*/
+#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 9 + 7 + 7)
 // clang-format off
 #define CDC_NCM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
     /* Interface Associate */                                                                  \
@@ -674,6 +683,15 @@ struct cdc_ncm_ndp16 {
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
     0x00,                                                  /* bAlternateSetting */             \
+    0x00,                                                  /* bNumEndpoints */                 \
+    CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
+    0x00,                                                  /* bInterfaceSubClass */            \
+    0x00,                                                  /* bInterfaceProtocol */            \
+    0x00,                                                  /* iInterface */                    \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
+    0x01,                                                  /* bAlternateSetting */             \
     0x02,                                                  /* bNumEndpoints */                 \
     CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
     0x00,                                                  /* bInterfaceSubClass */            \

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

@@ -39,7 +39,7 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
             /*                                        4 - Space                            */
             /* 6      | bDataBits  |   1   | Number Data bits (5, 6, 7, 8 or 16).          */
             /*******************************************************************************/
-            memcpy(&line_coding, *data, setup->wLength);
+            memcpy(&line_coding, *data, 7);
             USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
                         intf_num,
                         (unsigned int)line_coding.dwDTERate,
@@ -76,7 +76,6 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
             usbd_cdc_acm_send_break(busid, intf_num);
             break;
         default:
-            USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
             return -1;
     }
 

+ 0 - 1
components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c

@@ -106,7 +106,6 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
 #endif
             break;
         default:
-            USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
             return -1;
     }
 

+ 30 - 27
components/drivers/usb/cherryusb/class/dfu/usb_dfu.h

@@ -23,7 +23,7 @@
 #define DFU_PROTOCOL_RUNTIME 0x01
 
 /** DFU Class DFU mode Protocol */
-#define DFU_PROTOCOL_MODE 0x02
+#define DFU_PROTOCOL_DFU 0x02
 
 /**
  * @brief DFU Class Specific Requests
@@ -76,21 +76,23 @@
 #define DFU_STATE_DFU_UPLOAD_IDLE         9U
 #define DFU_STATE_DFU_ERROR               10U
 
-/** DFU Manifestation State  */
-#define DFU_MANIFEST_COMPLETE    0U
-#define DFU_MANIFEST_IN_PROGRESS 1U
+/* Define DFU application notification signals.  */
+#define DFU_NOTIFICATION_BEGIN_DOWNLOAD 0x1u
+#define DFU_NOTIFICATION_END_DOWNLOAD   0x2u
+#define DFU_NOTIFICATION_ABORT_DOWNLOAD 0x3u
+#define DFU_NOTIFICATION_BEGIN_UPLOAD   0x5u
+#define DFU_NOTIFICATION_END_UPLOAD     0x6u
+#define DFU_NOTIFICATION_ABORT_UPLOAD   0x7u
 
-/** Special Commands  with Download Request  */
-#define DFU_CMD_GETCOMMANDS       0U
-#define DFU_CMD_SETADDRESSPOINTER 0x21U
-#define DFU_CMD_ERASE             0x41U
-#define DFU_MEDIA_ERASE           0x00U
-#define DFU_MEDIA_PROGRAM         0x01U
+/* Define DFU application notification signals.  */
+#define DFU_MEDIA_STATUS_OK    0
+#define DFU_MEDIA_STATUS_BUSY  1
+#define DFU_MEDIA_STATUS_ERROR 2
 
-/** Other defines  */
-/* Bit Detach capable = bit 3 in bmAttributes field */
-#define DFU_DETACH_MASK   (1U << 3)
-#define DFU_MANIFEST_MASK (1U << 2)
+/** Special Commands with Download Request for STM32, wValue = 0 */
+#define DFU_SPECIAL_CMD_SET_ADDRESS_POINTER 0x21U
+#define DFU_SPECIAL_CMD_ERASE               0x41U
+#define DFU_SPECIAL_READ_UNPROTECT          0x92U
 
 /** Run-Time Functional Descriptor */
 struct dfu_runtime_descriptor {
@@ -103,35 +105,36 @@ struct dfu_runtime_descriptor {
 } __PACKED;
 
 /**\brief Payload packet to response in DFU_GETSTATUS request */
-struct dfu_info {
-    uint8_t bStatus;       /**<\brief An indication of the status resulting from the
+struct dfu_status {
+    uint8_t bStatus;        /**<\brief An indication of the status resulting from the
                                      * execution of the most recent request.*/
-    uint8_t bPollTimeout;  /**<\brief Minimum time (LSB) in ms, that the host should wait
+    uint32_t bwPollTimeout; /**<\brief Minimum time in ms, that the host should wait
                                      * before sending a subsequent DFU_GETSTATUS request.*/
-    uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait
-                                     * before sending a subsequent DFU_GETSTATUS request.*/
-    uint8_t bState;        /**<\brief An indication of the state that the device is going
+    uint8_t bState;         /**<\brief An indication of the state that the device is going
                                      * to enter immediately following transmission of this response.*/
-    uint8_t iString;       /**<\brief Index of the status string descriptor.*/
+    uint8_t iString;        /**<\brief Index of the status string descriptor.*/
 };
 
+#define DFU_DESCRIPTOR_LEN 18
+
 // clang-format off
-#define DFU_DESCRIPTOR_INIT()                                                            \
+#define DFU_DESCRIPTOR_INIT(str_idx)                                                     \
     0x09,                          /* bLength */                                         \
     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */                                 \
     0x00,                          /* bInterfaceNumber */                                \
     0x00,                          /* bAlternateSetting */                               \
     0x00,                          /* bNumEndpoints Default Control Pipe only */         \
     USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */                                 \
-    0x01,                          /* bInterfaceSubClass Device Firmware Upgrade */      \
-    0x02,                          /* bInterfaceProtocol DFU mode */                     \
-    0x04, /* iInterface */         /*!< Device Firmware Update Functional Descriptor  */ \
+    DFU_SUBCLASS_DFU,              /* bInterfaceSubClass Device Firmware Upgrade */      \
+    DFU_PROTOCOL_DFU,              /* bInterfaceProtocol DFU mode */                     \
+    str_idx,                       /* iInterface */                                      \
+    /*!< Device Firmware Update Functional Descriptor  */                                \
     0x09,                          /* bLength */                                         \
     0x21,                          /* DFU Functional Descriptor */                       \
     0x0B,                          /* bmAttributes */                                    \
     WBVAL(0x00ff),                 /* wDetachTimeOut */                                  \
-    WBVAL(USBD_DFU_XFER_SIZE),     /* wTransferSize */                                   \
-    WBVAL(0x011a)                  /* bcdDFUVersion */
+    WBVAL(CONFIG_USBDEV_REQUEST_BUFFER_LEN),     /* wTransferSize */                     \
+    WBVAL(DFU_VERSION)             /* bcdDFUVersion */
 // clang-format on
 
 #endif /* USB_DFU_H */

+ 296 - 440
components/drivers/usb/cherryusb/class/dfu/usbd_dfu.c

@@ -1,465 +1,313 @@
 /*
- * Copyright (c) 2022, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 #include "usbd_core.h"
 #include "usbd_dfu.h"
 
-/** Modify the following three parameters according to different platforms */
-#ifndef USBD_DFU_XFER_SIZE
-#define USBD_DFU_XFER_SIZE 1024
-#endif
-
-#ifndef USBD_DFU_APP_DEFAULT_ADD
-#define USBD_DFU_APP_DEFAULT_ADD 0x8004000
-#endif
-
-#ifndef FLASH_PROGRAM_TIME
-#define FLASH_PROGRAM_TIME 50
-#endif
-
-#ifndef FLASH_ERASE_TIME
-#define FLASH_ERASE_TIME 50
-#endif
-
 struct usbd_dfu_priv {
-    struct dfu_info info;
-    union {
-        uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
-        uint8_t d8[USBD_DFU_XFER_SIZE];
-    } buffer;
-
-    uint32_t wblock_num;
-    uint32_t wlength;
-    uint32_t data_ptr;
-    uint32_t alt_setting;
-
-    uint8_t dev_status[6];
-    uint8_t ReservedForAlign[2];
-    uint8_t dev_state;
-    uint8_t manif_state;
-    uint8_t firmwar_flag;
+    uint8_t dfu_state;
 } g_usbd_dfu;
 
-static void dfu_reset(void)
-{
-    memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
-
-    g_usbd_dfu.alt_setting = 0U;
-    g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
-    g_usbd_dfu.wblock_num = 0U;
-    g_usbd_dfu.wlength = 0U;
-
-    g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
-    g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-
-    g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
-    g_usbd_dfu.dev_status[1] = 0U;
-    g_usbd_dfu.dev_status[2] = 0U;
-    g_usbd_dfu.dev_status[3] = 0U;
-    g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
-    g_usbd_dfu.dev_status[5] = 0U;
-}
-
-static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
-{
-    switch (cmd) {
-        case DFU_MEDIA_PROGRAM:
-            buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
-            buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
-            buffer[3] = 0;
-            break;
-
-        case DFU_MEDIA_ERASE:
-            buffer[1] = (uint8_t)FLASH_ERASE_TIME;
-            buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
-            buffer[3] = 0;
-        default:
-
-            break;
-    }
-    return (0);
-}
+const char *usbd_dfu_state_string[] = {
+    "APP_IDLE",
+    "APP_DETACH",
+    "DFU_IDLE",
+    "DFU_DNLOAD_SYNC",
+    "DFU_DNLOAD_BUSY",
+    "DFU_DNLOAD_IDLE",
+    "DFU_MANIFEST_SYNC",
+    "DFU_MANIFEST",
+    "DFU_MANIFEST_WAIT_RESET",
+    "DFU_UPLOAD_IDLE",
+    "DFU_ERROR"
+};
 
-static void dfu_request_detach(void)
+static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
 {
-    if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
-        /* Update the state machine */
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-        g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-        g_usbd_dfu.dev_status[5] = 0U; /*iString*/
-        g_usbd_dfu.wblock_num = 0U;
-        g_usbd_dfu.wlength = 0U;
-    }
-}
+    USB_LOG_DBG("DFU Class request: "
+                "bRequest 0x%02x\r\n",
+                setup->bRequest);
 
-static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
-    struct usb_setup_packet *req = setup;
-    uint32_t addr;
-    /* Data setup request */
-    if (req->wLength > 0U) {
-        if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
-            /* Update the global length and block number */
-            g_usbd_dfu.wblock_num = req->wValue;
-            g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
-
-            /* DFU Get Command */
-            if (g_usbd_dfu.wblock_num == 0U) {
-                /* Update the state machine */
-                g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
-
-                g_usbd_dfu.dev_status[1] = 0U;
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
-                /* Store the values of all supported commands */
-                g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
-                g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
-                g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
-
-                /* Send the status data over EP0 */
-                memcpy(*data, g_usbd_dfu.buffer.d8, 3);
-                *len = 3;
-            } else if (g_usbd_dfu.wblock_num > 1U) {
-                g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
-
-                g_usbd_dfu.dev_status[1] = 0U;
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
-                addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
-
-                /* Return the physical address where data are stored */
-                dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
-
-                /* Send the status data over EP0 */
-                memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
-                *len = g_usbd_dfu.wlength;
-            } else /* unsupported g_usbd_dfu.wblock_num */
-            {
-                g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
-
-                g_usbd_dfu.dev_status[1] = 0U;
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
-                /* Call the error management function (command will be NAKed */
-                USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
+    USB_LOG_DBG("dfu state:%s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
+
+    switch (g_usbd_dfu.dfu_state) {
+        case DFU_STATE_APP_IDLE:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_DETACH:
+                    break;
+                case DFU_REQUEST_GETSTATUS:
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
             }
-        }
-        /* Unsupported state */
-        else {
-            g_usbd_dfu.wlength = 0U;
-            g_usbd_dfu.wblock_num = 0U;
-
-            /* Call the error management function (command will be NAKed */
-            USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
-        }
-    }
-    /* No Data setup request */
-    else {
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U;
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-    }
-}
-
-static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
-    /* Data setup request */
-    struct usb_setup_packet *req = setup;
-    if (req->wLength > 0U) {
-        if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
-            /* Update the global length and block number */
-            g_usbd_dfu.wblock_num = req->wValue;
-            g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
-
-            /* Update the state machine */
-            g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
-            g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
-            /*!< Data has received complete */
-            memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
-            /*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
-            g_usbd_dfu.firmwar_flag = 1;
-        }
-        /* Unsupported state */
-        else {
-            USB_LOG_ERR("Dfu_request_dnload unsupported state\r\n");
-        }
-    }
-    /* 0 Data DNLOAD request */
-    else {
-        /* End of DNLOAD operation*/
-        if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
-            g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
-            g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
-            g_usbd_dfu.dev_status[1] = 0U;
-            g_usbd_dfu.dev_status[2] = 0U;
-            g_usbd_dfu.dev_status[3] = 0U;
-            g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-        } else {
-            /* Call the error management function (command will be NAKed */
-            USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
-        }
-    }
-}
-
-static int8_t dfu_getstatus_special_handler(void)
-{
-    uint32_t addr;
-    if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
-        /* Decode the Special Command */
-        if (g_usbd_dfu.wblock_num == 0U) {
-            if (g_usbd_dfu.wlength == 1U) {
-                if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
-                    /* Nothing to do */
-                }
-            } else if (g_usbd_dfu.wlength == 5U) {
-                if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
-                    g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
-                } else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
-                    g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
-                    g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
-
-                    USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
-                    /*!< Erase */
-                    dfu_erase_flash(g_usbd_dfu.data_ptr);
-                } else {
+            break;
+        case DFU_STATE_APP_DETACH:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_GETSTATUS:
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
                     return -1;
-                }
-            } else {
-                /* Reset the global length and block number */
-                g_usbd_dfu.wlength = 0U;
-                g_usbd_dfu.wblock_num = 0U;
-                /* Call the error management function (command will be NAKed) */
-                USB_LOG_ERR("Reset the global length and block number\r\n");
             }
-        }
-        /* Regular Download Command */
-        else {
-            if (g_usbd_dfu.wblock_num > 1U) {
-                /* Decode the required address */
-                addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
-
-                /* Perform the write operation */
-                /* Write flash */
-                USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
-                dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
+            break;
+        case DFU_STATE_DFU_IDLE:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_DNLOAD:
+                    /* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
+                    we are done with the transfer.  */
+                    if (setup->wLength == 0) {
+                        usbd_dfu_end_load();
+                        g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
+                    } else {
+                        usbd_dfu_begin_load();
+                        if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+                            return -1;
+                        } else {
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
+                        }
+                    }
+                    break;
+                case DFU_REQUEST_UPLOAD:
+                    usbd_dfu_begin_load();
+
+                    uint16_t actual_length;
+                    if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
+                        g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+                        return -1;
+                    } else {
+                        g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
+                    }
+                    *len = actual_length;
+                    break;
+                case DFU_REQUEST_ABORT:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+                    break;
+                case DFU_REQUEST_GETSTATUS:
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
             }
-        }
-
-        /* Reset the global length and block number */
-        g_usbd_dfu.wlength = 0U;
-        g_usbd_dfu.wblock_num = 0U;
-
-        /* Update the state machine */
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
-
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U;
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-    }
-    return 0;
-}
-
-static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
-    /*!< Determine whether to leave DFU mode */
-    if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
-        g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
-        g_usbd_dfu.dev_status[1] == 0U &&
-        g_usbd_dfu.dev_status[2] == 0U &&
-        g_usbd_dfu.dev_status[3] == 0U &&
-        g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
-        g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
-
-        if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
-            g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
-
-            g_usbd_dfu.dev_status[1] = 0U;
-            g_usbd_dfu.dev_status[2] = 0U;
-            g_usbd_dfu.dev_status[3] = 0U;
-            g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-            return;
-        } else {
-            g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
-
-            g_usbd_dfu.dev_status[1] = 0U;
-            g_usbd_dfu.dev_status[2] = 0U;
-            g_usbd_dfu.dev_status[3] = 0U;
-            g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-            /* Generate system reset to allow jumping to the user code */
-            dfu_leave();
-        }
-    }
-
-    switch (g_usbd_dfu.dev_state) {
+            break;
         case DFU_STATE_DFU_DNLOAD_SYNC:
-            if (g_usbd_dfu.wlength != 0U) {
-                g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
-
-                g_usbd_dfu.dev_status[1] = 0U;
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
-                if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
-                    dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
-                } else {
-                    dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
-                }
-            } else /* (g_usbd_dfu.wlength==0)*/
-            {
-                g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
-
-                g_usbd_dfu.dev_status[1] = 0U;
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
+            switch (setup->bRequest) {
+                case DFU_REQUEST_GETSTATUS:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_BUSY;
+
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
             }
             break;
-
-        case DFU_STATE_DFU_MANIFEST_SYNC:
-            if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
-                g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
-
-                g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
-                g_usbd_dfu.dev_status[2] = 0U;
-                g_usbd_dfu.dev_status[3] = 0U;
-                g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-            } else {
-                if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
-                    ((0x0B & DFU_MANIFEST_MASK) != 0U)) {
-                    g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-
-                    g_usbd_dfu.dev_status[1] = 0U;
-                    g_usbd_dfu.dev_status[2] = 0U;
-                    g_usbd_dfu.dev_status[3] = 0U;
-                    g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-                }
+        case DFU_STATE_DFU_DNLOAD_BUSY:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_GETSTATUS:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_IDLE;
+
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
             }
             break;
-
-        default:
-            break;
-    }
-
-    /* Send the status data over EP0 */
-    memcpy(*data, g_usbd_dfu.dev_status, 6);
-    *len = 6;
-
-    if (g_usbd_dfu.firmwar_flag == 1) {
-        if (dfu_getstatus_special_handler() != 0) {
-            USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
-        }
-        g_usbd_dfu.firmwar_flag = 0;
-    }
-}
-
-static void dfu_request_clrstatus(void)
-{
-    if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-        g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U;                     /* bwPollTimeout=0ms */
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
-        g_usbd_dfu.dev_status[5] = 0U;                     /* iString */
-    } else {
-        /* State Error */
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
-        g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U;                     /* bwPollTimeout=0ms */
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
-        g_usbd_dfu.dev_status[5] = 0U;                     /* iString */
-    }
-}
-
-static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
-    /* Return the current state of the DFU interface */
-    (*data)[0] = g_usbd_dfu.dev_state;
-    *len = 1;
-}
-
-void dfu_request_abort(void)
-{
-    if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
-        (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
-        g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-        g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
-        g_usbd_dfu.dev_status[1] = 0U;
-        g_usbd_dfu.dev_status[2] = 0U;
-        g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
-        g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-        g_usbd_dfu.dev_status[5] = 0U; /* iString */
-        g_usbd_dfu.wblock_num = 0U;
-        g_usbd_dfu.wlength = 0U;
-    }
-}
-
-static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
-    USB_LOG_DBG("DFU Class request: "
-                "bRequest 0x%02x\r\n",
-                setup->bRequest);
-
-    switch (setup->bRequest) {
-        case DFU_REQUEST_DETACH:
-            dfu_request_detach();
-            break;
-        case DFU_REQUEST_DNLOAD:
-            dfu_request_dnload(setup, data, len);
-            break;
-        case DFU_REQUEST_UPLOAD:
-            dfu_request_upload(setup, data, len);
+        case DFU_STATE_DFU_DNLOAD_IDLE:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_DNLOAD:
+                    /* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
+                    we are done with the transfer.  */
+                    if (setup->wLength == 0) {
+                        usbd_dfu_end_load();
+                        g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
+                    } else {
+                        if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+                            return -1;
+                        } else {
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
+                        }
+                    }
+
+                    break;
+                case DFU_REQUEST_ABORT:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+                    break;
+                case DFU_REQUEST_GETSTATUS:
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
+            }
             break;
-        case DFU_REQUEST_GETSTATUS:
-            dfu_request_getstatus(setup, data, len);
+        case DFU_STATE_DFU_UPLOAD_IDLE:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_UPLOAD: {
+                    uint16_t actual_length;
+                    if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
+                        g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+                        return -1;
+                    } else {
+                        if (actual_length < setup->wLength) {
+                            usbd_dfu_end_load();
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+                        } else {
+                            g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
+                        }
+                    }
+                } break;
+                case DFU_REQUEST_ABORT:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+                    break;
+                case DFU_REQUEST_GETSTATUS:
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
+            }
             break;
-        case DFU_REQUEST_CLRSTATUS:
-            dfu_request_clrstatus();
+        case DFU_STATE_DFU_MANIFEST_SYNC:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_GETSTATUS:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
+
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
+            }
             break;
-        case DFU_REQUEST_GETSTATE:
-            dfu_request_getstate(setup, data, len);
+        case DFU_STATE_DFU_MANIFEST_WAIT_RESET:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_GETSTATUS:
+
+                    (*data)[0] = DFU_STATUS_OK; /* bStatus */
+                    (*data)[1] = 0;
+                    (*data)[2] = 0;
+                    (*data)[3] = 0;
+                    (*data)[4] = g_usbd_dfu.dfu_state;
+                    (*data)[5] = 0; /* iString */
+                    *len = 6;
+
+                    usbd_dfu_reset();
+
+                    break;
+                case DFU_REQUEST_GETSTATE:
+                    (*data)[0] = g_usbd_dfu.dfu_state;
+                    *len = 1;
+                    break;
+
+                default:
+                    return -1;
+            }
             break;
-        case DFU_REQUEST_ABORT:
-            dfu_request_abort();
+        case DFU_STATE_DFU_ERROR:
+            switch (setup->bRequest) {
+                case DFU_REQUEST_CLRSTATUS:
+                    g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+                    break;
+
+                default:
+                    return -1;
+            }
             break;
+
         default:
-            USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest);
+            USB_LOG_WRN("Invalid dfu state %s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
             return -1;
     }
-
     return 0;
 }
 
@@ -467,7 +315,7 @@ static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
 {
     switch (event) {
         case USBD_EVENT_RESET:
-            dfu_reset();
+            g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
             break;
         default:
             break;
@@ -484,21 +332,29 @@ struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf)
     return intf;
 }
 
-__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+uint8_t usbd_dfu_get_state(void)
 {
-    return dest;
+    return g_usbd_dfu.dfu_state;
 }
 
-__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+__WEAK void usbd_dfu_begin_load(void)
 {
-    return 0;
 }
 
-__WEAK uint16_t dfu_erase_flash(uint32_t add)
+__WEAK void usbd_dfu_end_load(void)
+{
+}
+
+__WEAK void usbd_dfu_reset(void)
 {
-    return 0;
 }
 
-__WEAK void dfu_leave(void)
+__WEAK int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
 {
+    return 0;
 }
+
+__WEAK int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
+{
+    return 0;
+}

+ 8 - 6
components/drivers/usb/cherryusb/class/dfu/usbd_dfu.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -14,12 +14,14 @@ extern "C" {
 
 /* Init dfu interface driver */
 struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf);
+uint8_t usbd_dfu_get_state(void);
+
+void usbd_dfu_begin_load(void);
+void usbd_dfu_end_load(void);
+void usbd_dfu_reset(void);
+int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length);
+int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length);
 
-/* Interface functions that need to be implemented by the user */
-uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
-uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
-uint16_t dfu_erase_flash(uint32_t add);
-void dfu_leave(void);
 #ifdef __cplusplus
 }
 #endif

+ 5 - 5
components/drivers/usb/cherryusb/class/gamepad/usbd_gamepad.c

@@ -13,11 +13,11 @@ static int xinput_vendor_class_request_handler(uint8_t busid, struct usb_setup_p
 {
     struct xinput_in_report xinput_report;
 
-    memset(&xinput_report, 0, sizeof(xinput_report));
+    memset(&xinput_report, 0, sizeof(struct xinput_in_report));
     xinput_report.report_size = 20;
 
-    memcpy(*data, &xinput_report, sizeof(xinput_report));
-    *len = sizeof(xinput_report);
+    memcpy(*data, &xinput_report, sizeof(struct xinput_in_report));
+    *len = sizeof(struct xinput_in_report);
     return 0;
 }
 
@@ -26,7 +26,7 @@ int usbd_gamepad_xinput_send_report(uint8_t ep, struct usb_gamepad_report *repor
     struct xinput_in_report *xinput_report;
 
     xinput_report = (struct xinput_in_report *)gamepad_report_buffer;
-    memset(xinput_report, 0, sizeof(xinput_report));
+    memset(xinput_report, 0, sizeof(struct xinput_in_report));
     xinput_report->report_size = 20;
 
     if (report->buttons & USB_GAMEPAD_BUTTON_DU)
@@ -105,7 +105,7 @@ int usbd_gamepad_switch_send_report(uint8_t ep, struct usb_gamepad_report *repor
     struct switch_in_report *switch_report;
 
     switch_report = (struct switch_in_report *)gamepad_report_buffer;
-    memset(switch_report, 0, sizeof(switch_report));
+    memset(switch_report, 0, sizeof(struct switch_in_report));
 
     if (report->buttons & USB_GAMEPAD_BUTTON_S1)
         switch_report->buttons |= SWITCH_MASK_MINUS;

+ 0 - 1
components/drivers/usb/cherryusb/class/hid/usbd_hid.c

@@ -41,7 +41,6 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
             break;
 
         default:
-            USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest);
             return -1;
     }
 

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

@@ -296,40 +296,29 @@ static uint32_t hid_get_itemval(const uint8_t *data, unsigned int idx, unsigned
     return value;
 }
 
-struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_len, uint32_t max_usages)
+int usbh_hid_parse_report_descriptor(const uint8_t *report_data, uint32_t report_size, struct usbh_hid_report_info *report_info)
 {
+    struct usbh_hid_report_item_attribute current_item_attr = { 0 };
+    struct usbh_hid_report_item *current_item = NULL;
+    uint32_t itemtag, itemtype, itemsize, itemval;
+    uint16_t temp_usage;
+    uint32_t total_report_size[3] = { 0 }; /* input, output, feature */
     uint32_t i = 0;
-    uint32_t itemtag, itemtype, itemsize;
-    uint32_t itemval;
-    struct hid_report_field field;
-    uint32_t usage_page = 0, usage = 0, usage_min = 0, usage_max = 0, flags = 0;
-    uint32_t *usages;
-    struct hid_report *hid_report;
-
-    hid_report = usb_osal_malloc(sizeof(struct hid_report));
-    if (!hid_report) {
-        USB_LOG_ERR("hid report malloc failed\r\n");
-        return NULL;
-    }
-
-    usages = usb_osal_malloc(sizeof(uint32_t) * max_usages);
-    if (!usages) {
-        USB_LOG_ERR("hid usages malloc failed\r\n");
-        goto err;
-    }
 
-    memset(hid_report, 0, sizeof(struct hid_report));
-    memset(&field, 0, sizeof(struct hid_report_field));
+    memset(report_info, 0, sizeof(struct usbh_hid_report_info));
+    memset(&current_item_attr, 0, sizeof(struct usbh_hid_report_item_attribute));
+    current_item_attr.usage_min = 0xffff;
+    current_item_attr.usage_max = 0;
 
-    while (i < report_len) {
-        itemtag = data[i] & HID_TAG_MASK;
-        itemtype = data[i] & HID_TYPE_MASK;
-        itemsize = data[i] & HID_SIZE_MASK;
+    while (i < report_size) {
+        itemtag = report_data[i] & HID_TAG_MASK;
+        itemtype = report_data[i] & HID_TYPE_MASK;
+        itemsize = report_data[i] & HID_SIZE_MASK;
 
         if (itemsize == 3) /* HID spec: 6.2.2.2 - Short Items */
             itemsize = 4;
 
-        itemval = hid_get_itemval(data, i, itemsize);
+        itemval = hid_get_itemval(report_data, i, itemsize);
 
         USB_LOG_DBG("itemtype 0x%02x, itemtag 0x%02x, itemsize %d, itemval 0x%08x\r\n",
                     itemtype, itemtag, itemsize, itemval);
@@ -338,88 +327,37 @@ struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_le
             case HID_ITEMTYPE_MAIN:
                 switch (itemtag) {
                     case HID_MAINITEM_TAG_INPUT:
-                        if ((flags & HID_REPORT_FLAG_REQUIRED_MASK) != HID_REPORT_FLAG_REQUIRED_MASK)
-                            goto err;
-
-                        if (hid_report->input_count >= CONFIG_USBHOST_HID_MAX_INPUT) {
-                            USB_LOG_ERR("hid input fields exceed max limit\r\n");
+                    case HID_MAINITEM_TAG_OUTPUT:
+                    case HID_MAINITEM_TAG_FEATURE:
+                        if (report_info->report_item_count == CONFIG_USB_HID_MAX_REPORT_ITEMS) {
                             goto err;
                         }
 
-                        field.flags = flags;
-                        field.properties = itemval;
-                        field.usage_page = usage_page;
-                        memcpy(&hid_report->input_fields[hid_report->input_count], &field, sizeof(struct hid_report_field));
-                        if (field.usage_count > 0) {
-                            hid_report->input_fields[hid_report->input_count].usages = usb_osal_malloc(sizeof(uint32_t) * field.usage_count);
-                            if (!hid_report->input_fields[hid_report->input_count].usages) {
-                                USB_LOG_ERR("hid input usages malloc failed\r\n");
-                                goto err;
-                            }
-                            memcpy(hid_report->input_fields[hid_report->input_count].usages, usages, sizeof(uint32_t) * field.usage_count);
-                        }
-
-                        hid_report->input_count++;
-
-                        /* only keep the global items */
-                        flags &= HID_REPORT_FLAG_GLOBAL_MASK;
-                        memset(&field, 0, sizeof(struct hid_report_field));
-                        break;
-                    case HID_MAINITEM_TAG_OUTPUT:
-                        if ((flags & HID_REPORT_FLAG_REQUIRED_MASK) != HID_REPORT_FLAG_REQUIRED_MASK)
-                            goto err;
+                        current_item = &report_info->report_items[report_info->report_item_count];
+                        current_item->report_flags = itemval;
 
-                        if (hid_report->output_count >= CONFIG_USBHOST_HID_MAX_OUTPUT) {
-                            USB_LOG_ERR("hid output fields exceed max limit\r\n");
-                            goto err;
+                        if (itemtag == HID_MAINITEM_TAG_INPUT) {
+                            current_item->report_type = HID_REPORT_INPUT;
+                        } else if (itemtag == HID_MAINITEM_TAG_OUTPUT) {
+                            current_item->report_type = HID_REPORT_OUTPUT;
+                        } else {
+                            current_item->report_type = HID_REPORT_FEATURE;
                         }
 
-                        field.flags = flags;
-                        field.properties = itemval;
-                        field.usage_page = usage_page;
-                        memcpy(&hid_report->output_fields[hid_report->output_count], &field, sizeof(struct hid_report_field));
-                        if (field.usage_count > 0) {
-                            hid_report->output_fields[hid_report->output_count].usages = usb_osal_malloc(sizeof(uint32_t) * field.usage_count);
-                            if (!hid_report->output_fields[hid_report->output_count].usages) {
-                                USB_LOG_ERR("hid output usages malloc failed\r\n");
-                                goto err;
-                            }
-                            memcpy(hid_report->output_fields[hid_report->output_count].usages, usages, sizeof(uint32_t) * field.usage_count);
-                        }
+                        current_item->report_bit_offset = total_report_size[current_item->report_type - 1];
+                        total_report_size[current_item->report_type - 1] += current_item_attr.report_size * current_item_attr.report_count;
 
-                        hid_report->output_count++;
+                        memcpy(&current_item->attribute, &current_item_attr, sizeof(struct usbh_hid_report_item_attribute));
+                        report_info->report_item_count++;
 
-                        /* only keep the global items */
-                        flags &= HID_REPORT_FLAG_GLOBAL_MASK;
-                        memset(&field, 0, sizeof(struct hid_report_field));
+                        // reset for next item
+                        current_item_attr.usage_min = 0xffff;
+                        current_item_attr.usage_max = 0;
                         break;
                     case HID_MAINITEM_TAG_COLLECTION:
-                        memset(&field, 0, sizeof(struct hid_report_field));
-                        break;
-                    case HID_MAINITEM_TAG_FEATURE:
-
-                        if (hid_report->feature_count >= CONFIG_USBHOST_HID_MAX_FEATURE) {
-                            USB_LOG_ERR("hid feature fields exceed max limit\r\n");
-                            goto err;
-                        }
-
-                        field.flags = flags;
-                        field.properties = itemval;
-                        field.usage_page = usage_page;
-                        memcpy(&hid_report->feature_fields[hid_report->feature_count], &field, sizeof(struct hid_report_field));
-                        if (field.usage_count > 0) {
-                            hid_report->feature_fields[hid_report->feature_count].usages = usb_osal_malloc(sizeof(uint32_t) * field.usage_count);
-                            if (!hid_report->feature_fields[hid_report->feature_count].usages) {
-                                USB_LOG_ERR("hid feature usages malloc failed\r\n");
-                                goto err;
-                            }
-                            memcpy(hid_report->feature_fields[hid_report->feature_count].usages, usages, sizeof(uint32_t) * field.usage_count);
-                        }
-
-                        hid_report->feature_count++;
-
-                        memset(&field, 0, sizeof(struct hid_report_field));
-
+                        // reset for next item
+                        current_item_attr.usage_min = 0xffff;
+                        current_item_attr.usage_max = 0;
                         break;
                     case HID_MAINITEM_TAG_ENDCOLLECTION:
                         break;
@@ -430,33 +368,34 @@ struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_le
             case HID_ITEMTYPE_GLOBAL:
                 switch (itemtag) {
                     case HID_GLOBALITEM_TAG_USAGE_PAGE:
-                        usage_page = itemval;
-
-                        if (usage_page > UINT16_MAX)
-                            goto err;
-
-                        flags |= HID_REPORT_FLAG_USAGE_PAGE;
+                        current_item_attr.usage_page = (uint16_t)itemval;
                         break;
                     case HID_GLOBALITEM_TAG_LOGICAL_MIN:
-                        field.logical_min = (int32_t)itemval;
-                        flags |= HID_REPORT_FLAG_LOGICAL_MIN;
+                        current_item_attr.logical_min = itemval;
                         break;
                     case HID_GLOBALITEM_TAG_LOGICAL_MAX:
-                        field.logical_max = (int32_t)itemval;
-                        flags |= HID_REPORT_FLAG_LOGICAL_MAX;
+                        current_item_attr.logical_max = itemval;
+                        break;
+                    case HID_GLOBALITEM_TAG_PHYSICAL_MIN:
+                        current_item_attr.physical_min = itemval;
+                        break;
+                    case HID_GLOBALITEM_TAG_PHYSICAL_MAX:
+                        current_item_attr.physical_max = itemval;
+                        break;
+                    case HID_GLOBALITEM_TAG_UNIT_EXP:
+                        current_item_attr.unit_exponent = itemval;
+                        break;
+                    case HID_GLOBALITEM_TAG_UNIT:
+                        current_item_attr.unit = itemval;
                         break;
                     case HID_GLOBALITEM_TAG_REPORT_SIZE:
-                        field.report_size = itemval;
-                        flags |= HID_REPORT_FLAG_REPORT_SIZE;
+                        current_item_attr.report_size = itemval;
                         break;
                     case HID_GLOBALITEM_TAG_REPORT_COUNT:
-                        field.report_count = itemval;
-                        flags |= HID_REPORT_FLAG_REPORT_COUNT;
+                        current_item_attr.report_count = itemval;
                         break;
                     case HID_GLOBALITEM_TAG_REPORT_ID:
-                        hid_report->uses_report_id = true;
-                        field.report_id = itemval;
-                        flags |= HID_REPORT_FLAG_REPORT_ID;
+                        current_item_attr.report_id = itemval;
                         break;
                     default:
                         goto err;
@@ -465,64 +404,20 @@ struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_le
             case HID_ITEMTYPE_LOCAL:
                 switch (itemtag) {
                     case HID_LOCALITEM_TAG_USAGE:
-                        usage = itemval;
-                        /* Extended usage (size 4) combines both usage page and id */
-                        if (itemsize != 4) {
-                            if (!(flags & HID_REPORT_FLAG_USAGE_PAGE))
-                                goto err;
-                            usage |= usage_page << 16;
+                        if (itemsize == 4) {
+                            temp_usage = (uint16_t)(itemval >> 16);
+                        } else {
+                            temp_usage = (uint16_t)itemval;
                         }
-
-                        usages[field.usage_count++] = usage;
+                        current_item_attr.usage_min = MIN(current_item_attr.usage_min, temp_usage);
+                        current_item_attr.usage_max = MAX(current_item_attr.usage_max, temp_usage);
 
                         break;
                     case HID_LOCALITEM_TAG_USAGE_MIN:
-                        usage_min = itemval;
-                        if (itemsize == 4) {
-                            /* Usage max must be extended as well */
-                            flags |= HID_REPORT_FLAG_EXTENDED_USAGE;
-                        } else {
-                            if (!(flags & HID_REPORT_FLAG_USAGE_PAGE))
-                                goto err;
-                            usage_min |= usage_page << 16;
-                        }
-                        field.usage_min = usage_min;
-                        flags |= HID_REPORT_FLAG_USAGE_MIN;
+                        current_item_attr.usage_min = (uint16_t)itemval;
                         break;
                     case HID_LOCALITEM_TAG_USAGE_MAX:
-                        if (!(flags & HID_REPORT_FLAG_USAGE_MIN))
-                            goto err;
-
-                        usage_max = itemval;
-                        if (flags & HID_REPORT_FLAG_EXTENDED_USAGE) {
-                            /* Fail if max is not extended usage (HID spec 6.2.2.8) */
-                            if (itemsize != 4)
-                                goto err;
-                        } else if (itemsize == 4) {
-                            /* Fail because min wasn't extended, but max is */
-                            goto err;
-                        } else {
-                            if (!(flags & HID_REPORT_FLAG_USAGE_PAGE))
-                                goto err;
-                            usage_max |= usage_page << 16;
-                        }
-
-                        /* Usage min and max must be on the same page */
-                        if (USAGE_PAGE(usage_min) != USAGE_PAGE(usage_max)) {
-                            goto err;
-                        }
-
-                        if (usage_min > usage_max) {
-                            goto err;
-                        }
-
-                        for (uint32_t j = usage_min; j <= usage_max; j++) {
-                            usages[field.usage_count++] = j;
-                        }
-
-                        field.usage_max = usage_max;
-                        flags |= HID_REPORT_FLAG_USAGE_MAX;
-                        flags &= ~(HID_REPORT_FLAG_USAGE_MIN | HID_REPORT_FLAG_EXTENDED_USAGE);
+                        current_item_attr.usage_max = (uint16_t)itemval;
                         break;
                     default:
                         goto err;
@@ -534,127 +429,83 @@ struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_le
 
         i += (1 + itemsize);
     }
-    usb_osal_free(usages);
-    return hid_report;
+
+    return 0;
 err:
-    if (hid_report) {
-        usb_osal_free(hid_report);
+    return -1;
+}
 
-        for (uint32_t j = 0; j < hid_report->input_count; j++)
-            usb_osal_free(hid_report->input_fields[j].usages);
+int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len)
+{
+    const uint8_t *src;
+    uint32_t bits_len = item->attribute.report_size * item->attribute.report_count;
 
-        for (uint32_t j = 0; j < hid_report->output_count; j++)
-            usb_osal_free(hid_report->output_fields[j].usages);
+    if(bits_len == 0) {
+        return -1;
+    }
 
-        for (uint32_t j = 0; j < hid_report->feature_count; j++)
-            usb_osal_free(hid_report->feature_fields[j].usages);
+    if (item->report_flags & HID_MAINITEM_CONSTANT) {
+        return -1;
     }
 
-    if (usages)
-        usb_osal_free(usages);
-    return NULL;
-}
+    if (item->attribute.report_id > 0) {
+        if (report_buf[0] != item->attribute.report_id) {
+            return -2; /* report id mismatch */
+        }
 
-void usbh_hid_report_free(struct hid_report *hid_report)
-{
-    if (hid_report) {
-        for (uint32_t j = 0; j < hid_report->input_count; j++)
-            usb_osal_free(hid_report->input_fields[j].usages);
+        src = report_buf + 1; /* skip report id */
+    } else {
+        src = report_buf;
+    }
 
-        for (uint32_t j = 0; j < hid_report->output_count; j++)
-            usb_osal_free(hid_report->output_fields[j].usages);
+    if ((bits_len < 32) && (bits_len % 8 != 0)) {
+        *output1 = 0;
 
-        for (uint32_t j = 0; j < hid_report->feature_count; j++)
-            usb_osal_free(hid_report->feature_fields[j].usages);
+        for (uint32_t i = 0; i < bits_len; i++) {
+            *output1 |= ((src[item->report_bit_offset / 8] >> ((item->report_bit_offset % 8) + i)) & 0x01) << i;
+        }
+
+        *output2 = NULL;
+        *output_len = (bits_len + 7) / 8;
+        return 0;
+    } else if (bits_len % 8 == 0) {
+        if (item->report_bit_offset % 8 != 0) {
+            /* currently do not support item that is not byte aligned */
+            return -3;
+        }
 
-        usb_osal_free(hid_report);
+        uint32_t byte_len = bits_len / 8;
+        *output2 = (uint8_t *)src + item->report_bit_offset / 8;
+        *output_len = byte_len;
+        return 0;
     }
+    return -4;
 }
 
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_report_buf[2048];
-
-static const char *hid_property_string(uint32_t value)
+static void usbh_hid_item_info_print(struct usbh_hid_report_item *item)
 {
-    uint32_t off = 0;
-    static char buffer[160];
-
-    memset(buffer, 0, sizeof(buffer));
-
-    if (value & HID_MAINITEM_CONSTANT)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Constant, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Data, ");
-
-    if (value & HID_MAINITEM_VARIABLE)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Variable, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Array, ");
-
-    if (value & HID_MAINITEM_RELATIVE)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Relative, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Absolute, ");
-
-    if (value & HID_MAINITEM_WRAP)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Wrap, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NoWrap, ");
-
-    if (value & HID_MAINITEM_NONLINEAR)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NonLinear, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Linear, ");
-
-    if (value & HID_MAINITEM_NOPREFERRED)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NoPreferred, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Preferred, ");
-
-    if (value & HID_MAINITEM_NULLSTATE)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NullState, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NoNullState, ");
-
-    if (value & HID_MAINITEM_VOLATILE)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "Volatile, ");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "NonVolatile, ");
-
-    if (value & HID_MAINITEM_BUFFEREDBYTES)
-        off += snprintf(buffer + off, sizeof(buffer) - off, "BufferedBytes");
-    else
-        off += snprintf(buffer + off, sizeof(buffer) - off, "BitField");
-
-    return buffer;
-
+    USB_LOG_RAW("Item Type: %s\r\n", (unsigned int)item->report_type == HID_REPORT_INPUT  ? "Input" :
+                                     (unsigned int)item->report_type == HID_REPORT_OUTPUT ? "Output" :
+                                                                                            "Feature");
+    USB_LOG_RAW("Usage Page: 0x%04x\r\n", (unsigned int)item->attribute.usage_page);
+    USB_LOG_RAW("Report ID: 0x%04x\r\n", (unsigned int)item->attribute.report_id);
+    USB_LOG_RAW("Report Size: %ubit\r\n", (unsigned int)item->attribute.report_size);
+    USB_LOG_RAW("Report Count: %u\r\n", (unsigned int)item->attribute.report_count);
+    USB_LOG_RAW("Usages(0x%04x ~ 0x%04x)\r\n", (unsigned int)item->attribute.usage_min, (unsigned int)item->attribute.usage_max);
+    USB_LOG_RAW("Logical Min: %d\r\n", item->attribute.logical_min);
+    USB_LOG_RAW("Logical Max: %d\r\n", item->attribute.logical_max);
+    USB_LOG_RAW("Properties: 0x%04x\r\n", (unsigned int)item->report_flags);
+    USB_LOG_RAW("Bit Offset: 0x%04x\r\n", (unsigned int)item->report_bit_offset);
+    USB_LOG_RAW("\r\n");
 }
 
-static void usbh_hid_field_info_print(uint32_t idx, struct hid_report_field *field)
-{
-    USB_LOG_RAW("  Field %u:\r\n", idx);
-    USB_LOG_RAW("    Usage Page: 0x%04x\r\n", (unsigned int)field->usage_page);
-    USB_LOG_RAW("    Report ID: %u\r\n", (unsigned int)field->report_id);
-    USB_LOG_RAW("    Report Size: %ubit\r\n", (unsigned int)field->report_size);
-    USB_LOG_RAW("    Report Count: %u\r\n", (unsigned int)field->report_count);
-    USB_LOG_RAW("    Logical Min: %d\r\n", field->logical_min);
-    USB_LOG_RAW("    Logical Max: %d\r\n", field->logical_max);
-    USB_LOG_RAW("    Usage Count: %u\r\n", (unsigned int)field->usage_count);
-    if (field->usage_count > 0) {
-        if (field->usage_count == 1) {
-            USB_LOG_RAW("    Usage: 0x%04x\r\n", USAGE_ID(field->usages[0]));
-        } else {
-            USB_LOG_RAW("    Usages(0x%04x ~ 0x%04x)\r\n", USAGE_ID(field->usage_min), USAGE_ID(field->usage_max));
-        }
-    }
-    USB_LOG_RAW("    Flags: 0x%04x\r\n", (unsigned int)field->flags);
-    USB_LOG_RAW("    Properties: 0x%04x(%s)\r\n", (unsigned int)field->properties, hid_property_string(field->properties));
-}
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_report_desc_buf[2048];
 
 int lshid(int argc, char **argv)
 {
     struct usbh_hid *hid_class;
-    struct hid_report *hid_report;
     int ret;
+    struct usbh_hid_report_info report_info = { 0 };
 
     if (argc < 2) {
         USB_LOG_ERR("please input correct command: lshid path\r\n");
@@ -667,43 +518,28 @@ int lshid(int argc, char **argv)
         return -1;
     }
 
-    if (hid_class->report_size > sizeof(g_hid_report_buf)) {
+    if (hid_class->report_size > sizeof(g_hid_report_desc_buf)) {
         USB_LOG_ERR("hid report buffer is too small\r\n");
         return -1;
     }
 
-    ret = usbh_hid_get_report_descriptor(hid_class, g_hid_report_buf, hid_class->report_size);
+    ret = usbh_hid_get_report_descriptor(hid_class, g_hid_report_desc_buf, hid_class->report_size);
     if (ret < 0) {
         USB_LOG_ERR("get hid report descriptor failed, errcode: %d\r\n", ret);
         return -1;
     }
 
-    hid_report = usbh_hid_report_parse(g_hid_report_buf, hid_class->report_size, 1024);
-    if (hid_report) {
-        USB_LOG_RAW("HID report parsed successfully\r\n");
-
-        USB_LOG_RAW("Input fields: %u\r\n", (unsigned int)hid_report->input_count);
-        for (uint32_t i = 0; i < hid_report->input_count; i++) {
-            struct hid_report_field *field = &hid_report->input_fields[i];
-            usbh_hid_field_info_print(i, field);
-        }
-
-        USB_LOG_RAW("Output fields: %u\r\n", (unsigned int)hid_report->output_count);
-        for (uint32_t i = 0; i < hid_report->output_count; i++) {
-            struct hid_report_field *field = &hid_report->output_fields[i];
-            usbh_hid_field_info_print(i, field);
-        }
-
-        USB_LOG_RAW("Feature fields: %u\r\n", (unsigned int)hid_report->feature_count);
-        for (uint32_t i = 0; i < hid_report->feature_count; i++) {
-            struct hid_report_field *field = &hid_report->feature_fields[i];
-            usbh_hid_field_info_print(i, field);
-        }
+    ret = usbh_hid_parse_report_descriptor(g_hid_report_desc_buf, hid_class->report_size, &report_info);
+    if (ret < 0) {
+        USB_LOG_ERR("parse hid report descriptor failed\r\n");
+        return -1;
+    }
 
-        usbh_hid_report_free(hid_report);
-    } else {
-        USB_LOG_ERR("HID report parsed failed\r\n");
+    USB_LOG_INFO("HID report item count: %u\r\n", report_info.report_item_count);
+    for (uint32_t i = 0; i < report_info.report_item_count; i++) {
+        usbh_hid_item_info_print(&report_info.report_items[i]);
     }
+
     return 0;
 }
 

+ 25 - 68
components/drivers/usb/cherryusb/class/hid/usbh_hid.h

@@ -8,80 +8,37 @@
 
 #include "usb_hid.h"
 
-/* local items */
-#define HID_REPORT_FLAG_USAGE_MIN (1 << 0)
-#define HID_REPORT_FLAG_USAGE_MAX (1 << 1)
-
-/* global items */
-#define HID_REPORT_FLAG_REPORT_ID    (1 << 2)
-#define HID_REPORT_FLAG_REPORT_COUNT (1 << 3)
-#define HID_REPORT_FLAG_REPORT_SIZE  (1 << 4)
-#define HID_REPORT_FLAG_LOGICAL_MIN  (1 << 5)
-#define HID_REPORT_FLAG_LOGICAL_MAX  (1 << 6)
-#define HID_REPORT_FLAG_USAGE_PAGE   (1 << 7)
-
-/* main items */
-#define HID_REPORT_FLAG_INPUT   (1 << 8)
-#define HID_REPORT_FLAG_OUTPUT  (1 << 9)
-#define HID_REPORT_FLAG_FEATURE (1 << 10)
-
-#define HID_REPORT_FLAG_EXTENDED_USAGE (1 << 11)
-
-/* masks */
-
-#define HID_REPORT_FLAG_GLOBAL_MASK (HID_REPORT_FLAG_REPORT_ID |    \
-                                     HID_REPORT_FLAG_REPORT_COUNT | \
-                                     HID_REPORT_FLAG_REPORT_SIZE |  \
-                                     HID_REPORT_FLAG_LOGICAL_MIN |  \
-                                     HID_REPORT_FLAG_LOGICAL_MAX |  \
-                                     HID_REPORT_FLAG_USAGE_PAGE)
-
-#define HID_REPORT_FLAG_REQUIRED_MASK (HID_REPORT_FLAG_REPORT_COUNT | \
-                                       HID_REPORT_FLAG_REPORT_SIZE |  \
-                                       HID_REPORT_FLAG_LOGICAL_MIN |  \
-                                       HID_REPORT_FLAG_LOGICAL_MAX)
-
-#define USAGE_ID(usage)   (usage & 0x0000FFFF)
-#define USAGE_PAGE(usage) ((usage & 0xFFFF0000) >> 16)
-
-#ifndef CONFIG_USBHOST_HID_MAX_INPUT
-#define CONFIG_USBHOST_HID_MAX_INPUT 16
+#ifndef CONFIG_USB_HID_MAX_REPORT_ITEMS
+#define CONFIG_USB_HID_MAX_REPORT_ITEMS       16
 #endif
 
-#ifndef CONFIG_USBHOST_HID_MAX_OUTPUT
-#define CONFIG_USBHOST_HID_MAX_OUTPUT 16
-#endif
-
-#ifndef CONFIG_USBHOST_HID_MAX_FEATURE
-#define CONFIG_USBHOST_HID_MAX_FEATURE 16
-#endif
-
-struct hid_report_field {
-    uint32_t *usages; /* usage page + usage */
-    uint32_t usage_count;
-    uint32_t usage_page;
-
-    uint32_t report_id; /* optional */
-    uint32_t report_count;
-    uint32_t report_size;
+struct usbh_hid_report_item_attribute {
+    uint16_t usage_page;
+    uint16_t usage_min;
+    uint16_t usage_max;
     int32_t logical_min;
     int32_t logical_max;
-    uint32_t properties;
+    uint32_t physical_min;
+    uint32_t physical_max;
+    uint32_t unit_exponent;
+    uint32_t unit;
+    uint32_t report_count;
+    uint8_t report_size;
+    uint8_t report_id;
+};
 
-    uint32_t usage_min;
-    uint32_t usage_max;
+struct usbh_hid_report_item {
+    uint8_t report_type; /* input, output, feature */
+    uint16_t report_flags;
+    uint32_t report_bit_offset;
 
-    uint32_t flags;
+    struct usbh_hid_report_item_attribute attribute;
 };
 
-struct hid_report {
-    bool uses_report_id;
-    uint32_t input_count;
-    struct hid_report_field input_fields[CONFIG_USBHOST_HID_MAX_INPUT];
-    uint32_t output_count;
-    struct hid_report_field output_fields[CONFIG_USBHOST_HID_MAX_OUTPUT];
-    uint32_t feature_count;
-    struct hid_report_field feature_fields[CONFIG_USBHOST_HID_MAX_FEATURE];
+struct usbh_hid_report_info {
+    struct usbh_hid_report_item report_items[CONFIG_USB_HID_MAX_REPORT_ITEMS];
+    uint32_t report_item_count;
+    bool using_report_id;
 };
 
 struct usbh_hid {
@@ -112,8 +69,8 @@ int usbh_hid_get_protocol(struct usbh_hid *hid_class, uint8_t *protocol);
 int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
 int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
 
-struct hid_report *usbh_hid_report_parse(const uint8_t *data, uint32_t report_len, uint32_t max_usages);
-void usbh_hid_report_free(struct hid_report *hid_report);
+int usbh_hid_parse_report_descriptor(const uint8_t *report_data, uint32_t report_size, struct usbh_hid_report_info *report_info);
+int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len);
 
 void usbh_hid_run(struct usbh_hid *hid_class);
 void usbh_hid_stop(struct usbh_hid *hid_class);

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

@@ -642,6 +642,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
                     child->speed = speed;
                     child->bus = hub->bus;
                     child->mutex = usb_osal_mutex_create();
+                    USB_ASSERT(child->mutex != NULL);
 
                     USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
 
@@ -677,21 +678,35 @@ static void usbh_hub_events(struct usbh_hub *hub)
 static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
 {
     struct usbh_hub *hub;
+    struct usbh_hubport *hport;
     int ret = 0;
 
     struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
-    usb_hc_init(bus);
     bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_INIT);
+    usb_hc_init(bus);
+
     while (1) {
         ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
         if (ret < 0) {
             continue;
         }
-        usb_osal_mutex_take(bus->mutex);
+        if (hub == NULL) {
+            break;
+        }
         usbh_hub_events(hub);
-        usb_osal_mutex_give(bus->mutex);
     }
+
+    hub = &bus->hcd.roothub;
+    for (uint8_t port = 0; port < hub->nports; port++) {
+        hport = &hub->child[port];
+
+        usbh_hubport_release(hport);
+    }
+    usb_hc_deinit(bus);
+    usb_osal_mq_delete(bus->hub_mq);
+    usb_osal_sem_give(bus->hub_sem);
+    usb_osal_thread_delete(NULL);
 }
 
 void usbh_hub_thread_wakeup(struct usbh_hub *hub)
@@ -720,9 +735,9 @@ int usbh_hub_initialize(struct usbh_bus *bus)
         return -1;
     }
 
-    bus->mutex = usb_osal_mutex_create();
-    if (bus->mutex == NULL) {
-        USB_LOG_ERR("Failed to create bus mutex\r\n");
+    bus->hub_sem = usb_osal_sem_create(0);
+    if (bus->hub_sem == NULL) {
+        USB_LOG_ERR("Failed to create hub sem\r\n");
         return -1;
     }
 
@@ -737,24 +752,18 @@ int usbh_hub_initialize(struct usbh_bus *bus)
 
 int usbh_hub_deinitialize(struct usbh_bus *bus)
 {
-    struct usbh_hubport *hport;
-    struct usbh_hub *hub;
-
-    usb_osal_mutex_take(bus->mutex);
-    hub = &bus->hcd.roothub;
-    for (uint8_t port = 0; port < hub->nports; port++) {
-        hport = &hub->child[port];
-
-        usbh_hubport_release(hport);
+    if (!bus->hub_mq || !bus->hub_sem) {
+        return -USB_ERR_INVAL;
     }
 
-    usb_hc_deinit(bus);
+    usb_osal_mq_send(bus->hub_mq, (uintptr_t)NULL);
+    usb_osal_sem_take(bus->hub_sem, USB_OSAL_WAITING_FOREVER);
+    usb_osal_sem_delete(bus->hub_sem);
+    bus->hub_mq = NULL;
+    bus->hub_sem = NULL;
 
-    usb_osal_thread_delete(bus->hub_thread);
-    usb_osal_mq_delete(bus->hub_mq);
+    bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_DEINIT);
 
-    usb_osal_mutex_give(bus->mutex);
-    usb_osal_mutex_delete(bus->mutex);
     return 0;
 }
 

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

@@ -69,7 +69,6 @@ static void usdb_msc_set_max_lun(uint8_t busid)
 static void usbd_msc_reset(uint8_t busid)
 {
     g_usbd_msc[busid].stage = MSC_READ_CBW;
-    g_usbd_msc[busid].readonly = false;
 }
 
 static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -89,7 +88,6 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
             break;
 
         default:
-            USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest);
             return -1;
     }
 
@@ -153,8 +151,8 @@ static void usbd_msc_send_csw(uint8_t busid, uint8_t CSW_Status)
     g_usbd_msc[busid].csw.bStatus = CSW_Status;
 
     /* updating the State Machine , so that we wait CSW when this
-	 * transfer is complete, ie when we get a bulk in callback
-	 */
+    * transfer is complete, ie when we get a bulk in callback
+    */
     g_usbd_msc[busid].stage = MSC_WAIT_CSW;
 
     USB_LOG_DBG("Send csw\r\n");
@@ -166,8 +164,8 @@ static void usbd_msc_send_info(uint8_t busid, uint8_t *buffer, uint8_t size)
     size = MIN(size, g_usbd_msc[busid].cbw.dDataLength);
 
     /* updating the State Machine , so that we send CSW when this
-	 * transfer is complete, ie when we get a bulk in callback
-	 */
+    * transfer is complete, ie when we get a bulk in callback
+    */
     g_usbd_msc[busid].stage = MSC_SEND_CSW;
 
     usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, buffer, size);
@@ -290,7 +288,7 @@ static bool SCSI_inquiry(uint8_t busid, uint8_t **data, uint32_t *len)
         0x00,
         0x80,
         0x00,
-        0x08,
+        (0x08 - 4U),
         0x20, /* Put Product Serial number */
         0x20,
         0x20,

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

@@ -8,7 +8,7 @@
 #include "usbh_ch34x.h"
 
 #undef USB_DBG_TAG
-#define USB_DBG_TAG "usbh_ch43x"
+#define USB_DBG_TAG "usbh_ch34x"
 #include "usb_log.h"
 
 struct usbh_ch34x {

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

@@ -404,4 +404,4 @@ CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = {
     .bInterfaceProtocol = 0x00,
     .id_table = ftdi_id_table,
     .class_driver = &ftdi_class_driver
-};
+};

+ 8 - 98
components/drivers/usb/cherryusb/class/serial/usbh_serial.c

@@ -14,8 +14,6 @@
 #define DEV_FORMAT_VENDOR  "/dev/ttyUSB%d"
 #define DEV_FORMAT_CDC_ACM "/dev/ttyACM%d"
 
-#define CONFIG_USBHOST_MAX_SERIAL_CLASS 4
-
 static struct usbh_serial g_serial_class[CONFIG_USBHOST_MAX_SERIAL_CLASS];
 
 static uint32_t g_devinuse = 0;
@@ -23,94 +21,6 @@ static uint32_t g_cdcacm_devinuse = 0;
 
 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_serial_iobuffer[CONFIG_USBHOST_MAX_SERIAL_CLASS][USB_ALIGN_UP((USBH_SERIAL_RX2_NOCACHE_OFFSET + USBH_SERIAL_RX2_NOCACHE_SIZE), CONFIG_USB_ALIGN_SIZE)];
 
-/* refer to cherryrb */
-static int usbh_serial_ringbuffer_init(usbh_serial_ringbuf_t *rb, void *pool, uint32_t size)
-{
-    if (NULL == rb) {
-        return -1;
-    }
-
-    if (NULL == pool) {
-        return -1;
-    }
-
-    if ((size < 2) || (size & (size - 1))) {
-        return -1;
-    }
-
-    rb->in = 0;
-    rb->out = 0;
-    rb->mask = size - 1;
-    rb->pool = pool;
-
-    return 0;
-}
-
-static void usbh_serial_ringbuffer_reset(usbh_serial_ringbuf_t *rb)
-{
-    rb->in = 0;
-    rb->out = 0;
-}
-
-static uint32_t usbh_serial_ringbuffer_get_used(usbh_serial_ringbuf_t *rb)
-{
-    return rb->in - rb->out;
-}
-
-static uint32_t usbh_serial_ringbuffer_write(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
-{
-    uint32_t unused;
-    uint32_t offset;
-    uint32_t remain;
-
-    unused = (rb->mask + 1) - (rb->in - rb->out);
-
-    if (size > unused) {
-        size = unused;
-    }
-
-    offset = rb->in & rb->mask;
-
-    remain = rb->mask + 1 - offset;
-    remain = remain > size ? size : remain;
-
-    memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
-    memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
-
-    rb->in += size;
-
-    return size;
-}
-
-static uint32_t usbh_serial_ringbuffer_peek(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
-{
-    uint32_t used;
-    uint32_t offset;
-    uint32_t remain;
-
-    used = rb->in - rb->out;
-    if (size > used) {
-        size = used;
-    }
-
-    offset = rb->out & rb->mask;
-
-    remain = rb->mask + 1 - offset;
-    remain = remain > size ? size : remain;
-
-    memcpy(data, ((uint8_t *)(rb->pool)) + offset, remain);
-    memcpy((uint8_t *)data + remain, rb->pool, size - remain);
-
-    return size;
-}
-
-static uint32_t usbh_serial_ringbuffer_read(usbh_serial_ringbuf_t *rb, void *data, uint32_t size)
-{
-    size = usbh_serial_ringbuffer_peek(rb, data, size);
-    rb->out += size;
-    return size;
-}
-
 static struct usbh_serial *usbh_serial_alloc(bool is_cdcacm)
 {
     uint8_t devno;
@@ -193,9 +103,9 @@ static void usbh_serial_callback(void *arg, int nbytes)
             return;
         }
 
-        usbh_serial_ringbuffer_write(&serial->rx_rb,
-                                     &serial->iobuffer[(serial->rx_buf_index ? USBH_SERIAL_RX2_NOCACHE_OFFSET : USBH_SERIAL_RX_NOCACHE_OFFSET) + serial->driver->ignore_rx_header],
-                                     (nbytes - serial->driver->ignore_rx_header));
+        usb_ringbuffer_write(&serial->rx_rb,
+                             &serial->iobuffer[(serial->rx_buf_index ? USBH_SERIAL_RX2_NOCACHE_OFFSET : USBH_SERIAL_RX_NOCACHE_OFFSET) + serial->driver->ignore_rx_header],
+                             (nbytes - serial->driver->ignore_rx_header));
 
         if (serial->rx_complete_callback) {
             serial->rx_complete_callback(serial, nbytes - serial->driver->ignore_rx_header);
@@ -319,7 +229,7 @@ struct usbh_serial *usbh_serial_open(const char *devname, uint32_t open_flags)
         }
     }
 
-    usbh_serial_ringbuffer_init(&serial->rx_rb, serial->rx_rb_pool, CONFIG_USBHOST_SERIAL_RX_SIZE);
+    usb_ringbuffer_init(&serial->rx_rb, serial->rx_rb_pool, CONFIG_USBHOST_SERIAL_RX_SIZE);
 
     serial->ref_count++;
     serial->open_flags = open_flags;
@@ -454,7 +364,7 @@ int usbh_serial_control(struct usbh_serial *serial, int cmd, void *arg)
                 return ret;
             }
 
-            usbh_serial_ringbuffer_reset(&serial->rx_rb);
+            usb_ringbuffer_reset(&serial->rx_rb);
             usb_osal_sem_reset(serial->rx_complete_sem);
             serial->rx_buf_index = 0;
             usbh_bulk_urb_fill(&serial->bulkin_urb, serial->hport, serial->bulkin, &serial->iobuffer[serial->rx_buf_index ? USBH_SERIAL_RX2_NOCACHE_OFFSET : USBH_SERIAL_RX_NOCACHE_OFFSET], serial->bulkin->wMaxPacketSize,
@@ -561,9 +471,9 @@ int usbh_serial_read(struct usbh_serial *serial, void *buffer, uint32_t buflen)
     }
 
     if (serial->open_flags & USBH_SERIAL_O_NONBLOCK) {
-        return usbh_serial_ringbuffer_read(&serial->rx_rb, buffer, buflen);
+        return usb_ringbuffer_read(&serial->rx_rb, buffer, buflen);
     } else {
-        if (usbh_serial_ringbuffer_get_used(&serial->rx_rb) == 0) {
+        if (usb_ringbuffer_get_used(&serial->rx_rb) == 0) {
             ret = usb_osal_sem_take(serial->rx_complete_sem, serial->rx_timeout_ms == 0 ? USB_OSAL_WAITING_FOREVER : serial->rx_timeout_ms);
             if (ret < 0) {
                 return ret;
@@ -572,7 +482,7 @@ int usbh_serial_read(struct usbh_serial *serial, void *buffer, uint32_t buflen)
                 return serial->rx_errorcode;
             }
         }
-        return usbh_serial_ringbuffer_read(&serial->rx_rb, buffer, buflen);
+        return usb_ringbuffer_read(&serial->rx_rb, buffer, buflen);
     }
 }
 

+ 1 - 8
components/drivers/usb/cherryusb/class/serial/usbh_serial.h

@@ -67,13 +67,6 @@
 extern "C" {
 #endif
 
-typedef struct {
-    uint32_t in;   /*!< Define the write pointer.               */
-    uint32_t out;  /*!< Define the read pointer.                */
-    uint32_t mask; /*!< Define the write and read pointer mask. */
-    void *pool;    /*!< Define the memory pointer.              */
-} usbh_serial_ringbuf_t;
-
 /*
  * Counters of the input lines (CTS, DSR, RI, CD) interrupts
  */
@@ -143,7 +136,7 @@ struct usbh_serial {
 
     const struct usbh_serial_driver *driver;
 
-    usbh_serial_ringbuf_t rx_rb;
+    usb_ringbuffer_t rx_rb;
     uint8_t rx_rb_pool[CONFIG_USBHOST_SERIAL_RX_SIZE];
     usb_osal_sem_t rx_complete_sem;
     uint8_t rx_buf_index;

+ 172 - 0
components/drivers/usb/cherryusb/class/vendor/display/usbd_display.c

@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2026, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "usbd_core.h"
+#include "usbd_display.h"
+
+struct usbd_display_priv {
+    struct usb_mempool pool;
+    struct usbd_endpoint out_ep;
+    struct usbd_endpoint in_ep;
+    struct usbd_display_frame *current_frame;
+} g_usbd_display;
+
+int usbd_display_frame_create(struct usbd_display_frame *frame, uint32_t count)
+{
+    return usb_mempool_create(&g_usbd_display.pool, frame, sizeof(struct usbd_display_frame), count);
+}
+
+struct usbd_display_frame *usbd_display_frame_alloc(void)
+{
+    return (struct usbd_display_frame *)usb_mempool_alloc(&g_usbd_display.pool);
+}
+
+int usbd_display_frame_free(struct usbd_display_frame *frame)
+{
+    return usb_mempool_free(&g_usbd_display.pool, (uintptr_t *)frame);
+}
+
+int usbd_display_frame_send(struct usbd_display_frame *frame)
+{
+    return usb_mempool_send(&g_usbd_display.pool, (uintptr_t *)frame);
+}
+
+int usbd_display_frame_recv(struct usbd_display_frame **frame, uint32_t timeout)
+{
+    return usb_mempool_recv(&g_usbd_display.pool, (uintptr_t **)frame, timeout);
+}
+
+uint8_t usb_dispay_dummy[512];
+volatile uint32_t usb_display_buf_offset;
+volatile bool usb_display_ignore_frame;
+
+static void display_notify_handler(uint8_t busid, uint8_t event, void *arg)
+{
+    switch (event) {
+        case USBD_EVENT_RESET:
+            break;
+        case USBD_EVENT_CONFIGURED:
+            usb_display_buf_offset = 0;
+            usb_display_ignore_frame = true;
+            g_usbd_display.current_frame = NULL;
+            usb_mempool_reset(&g_usbd_display.pool);
+            usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
+            break;
+        default:
+            break;
+    }
+}
+
+void usbd_display_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    if (usb_display_ignore_frame) {
+        // alloc frame for next at the end of current frame
+        if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
+            if (g_usbd_display.current_frame == NULL) {
+                g_usbd_display.current_frame = usbd_display_frame_alloc();
+                if (g_usbd_display.current_frame) {
+                    usb_display_ignore_frame = false;
+                    usb_display_buf_offset = 0;
+
+                    goto get_frame;
+                } else {
+                    goto drop_frame;
+                }
+            } else {
+                usb_display_ignore_frame = false;
+                usb_display_buf_offset = 0;
+
+                goto get_frame;
+            }
+        } else {
+            goto drop_frame;
+        }
+    } else {
+        struct usbd_disp_frame_header *header = (struct usbd_disp_frame_header *)&g_usbd_display.current_frame->frame_buf[0];
+        struct usbd_display_frame *frame;
+
+        if (header->payload_total > g_usbd_display.current_frame->frame_bufsize) {
+            USB_LOG_ERR("frame overflow, drop it\r\n");
+            usb_display_ignore_frame = true;
+
+            goto drop_frame;
+        }
+
+        usb_display_buf_offset += nbytes;
+
+        if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
+            frame = g_usbd_display.current_frame;
+            g_usbd_display.current_frame = NULL;
+
+            frame->frame_format = header->type;
+            frame->frame_size = header->payload_total;
+            usbd_display_frame_send(frame);
+
+            g_usbd_display.current_frame = usbd_display_frame_alloc();
+            if (g_usbd_display.current_frame) {
+                usb_display_ignore_frame = false;
+                usb_display_buf_offset = 0;
+
+                goto get_frame;
+            } else {
+                usb_display_ignore_frame = true;
+
+                goto drop_frame;
+            }
+        } else {
+            goto get_frame;
+        }
+    }
+    return;
+
+drop_frame:
+    // drop current frame
+    usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
+    return;
+get_frame:
+    usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, &g_usbd_display.current_frame->frame_buf[usb_display_buf_offset], 16384);
+    return;
+}
+
+void usbd_display_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+}
+
+struct usbd_interface *usbd_display_init_intf(struct usbd_interface *intf,
+                                              const uint8_t out_ep,
+                                              const uint8_t in_ep,
+                                              struct usbd_display_frame *frame,
+                                              uint32_t count)
+{
+    intf->class_interface_handler = NULL;
+    intf->class_endpoint_handler = NULL;
+    intf->vendor_handler = NULL;
+    intf->notify_handler = display_notify_handler;
+
+    g_usbd_display.out_ep.ep_addr = out_ep;
+    g_usbd_display.out_ep.ep_cb = usbd_display_bulk_out;
+    g_usbd_display.in_ep.ep_addr = in_ep;
+    g_usbd_display.in_ep.ep_cb = usbd_display_bulk_in;
+    usbd_add_endpoint(0, &g_usbd_display.out_ep);
+    usbd_add_endpoint(0, &g_usbd_display.in_ep);
+
+    for (uint32_t i = 0; i < count; i++) {
+        USB_ASSERT_MSG(frame[i].frame_bufsize % 16384, "frame_bufsize must be the multiple of 16384");
+    }
+
+    usbd_display_frame_create(frame, count);
+    return intf;
+}
+
+int usbd_display_dequeue(struct usbd_display_frame **frame, uint32_t timeout)
+{
+    return usbd_display_frame_recv(frame, timeout);
+}
+
+int usbd_display_enqueue(struct usbd_display_frame *frame)
+{
+    return usbd_display_frame_free(frame);
+}

+ 51 - 0
components/drivers/usb/cherryusb/class/vendor/display/usbd_display.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2026, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_DISPLAY_H
+#define USBD_DISPLAY_H
+
+#define USBD_DISPLAY_TYPE_RGB565 0
+#define USBD_DISPLAY_TYPE_RGB888 1
+#define USBD_DISPLAY_TYPE_YUV420 2
+#define USBD_DISPLAY_TYPE_JPG    3
+
+struct usbd_disp_frame_header {
+    uint16_t crc16; //payload crc16
+    uint8_t type;   //raw rgb,yuv,jpg,other
+    uint8_t cmd;
+    uint16_t x; //32bit
+    uint16_t y;
+    uint16_t width; //32bit
+    uint16_t height;
+    uint32_t frame_id      : 10;
+    uint32_t payload_total : 22; //payload max 4MB
+} __PACKED;
+
+struct usbd_display_frame {
+    uint8_t *frame_buf;
+    uint32_t frame_bufsize;
+    uint32_t frame_format;
+    uint32_t frame_size;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Init display interface driver */
+struct usbd_interface *usbd_display_init_intf(struct usbd_interface *intf,
+                                              const uint8_t out_ep,
+                                              const uint8_t in_ep,
+                                              struct usbd_display_frame *frame,
+                                              uint32_t count);
+
+int usbd_display_dequeue(struct usbd_display_frame **frame, uint32_t timeout);
+int usbd_display_enqueue(struct usbd_display_frame *frame);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_DISPLAY_H */

+ 0 - 23
components/drivers/usb/cherryusb/class/video/usbd_video.c

@@ -44,7 +44,6 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
                 case VIDEO_REQUEST_GET_INFO:
                     break;
                 default:
-                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                     return -1;
             }
 
@@ -58,7 +57,6 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
                 case VIDEO_REQUEST_GET_INFO:
                     break;
                 default:
-                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                     return -1;
             }
 
@@ -91,7 +89,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 1;
                                         break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
@@ -127,7 +124,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 4;
                                     } break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
@@ -163,7 +159,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 2;
                                     } break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
@@ -199,7 +194,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 2;
                                     } break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
@@ -235,7 +229,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 2;
                                     } break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
@@ -247,16 +240,13 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                         *len = 2;
                                     } break;
                                     default:
-                                        USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                         return -1;
                                 }
                                 break;
                             default:
-                                USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
                                 return -1;
                         }
                     } else {
-                        USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType);
                         return -2;
                     }
                     break;
@@ -298,7 +288,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -337,7 +326,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -373,7 +361,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -409,7 +396,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -440,7 +426,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -471,7 +456,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -502,7 +486,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -538,7 +521,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 2;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
@@ -550,13 +532,11 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
                                     *len = 1;
                                 } break;
                                 default:
-                                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                                     return -1;
                             }
                             break;
                         default:
                             g_usbd_video[busid].error_code = 0x06;
-                            USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
                             return -1;
                     }
                     break;
@@ -606,7 +586,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
                     break;
 
                 default:
-                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                     return -1;
             }
             break;
@@ -638,7 +617,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
                     break;
 
                 default:
-                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                     return -1;
             }
             break;
@@ -653,7 +631,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
                     *len = 1;
                     break;
                 default:
-                    USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
                     return -1;
             }
             break;

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

@@ -174,12 +174,13 @@ int usbh_video_open(struct usbh_video *video_class,
                     frameidx = j + 1;
                     dwDefaultFrameInterval = video_class->format[i].frame[j].dwDefaultFrameInterval;
                     found = true;
-                    break;
+                    goto dev_found;
                 }
             }
         }
     }
 
+dev_found:
     if (found == false) {
         return -USB_ERR_NODEV;
     }
@@ -437,6 +438,9 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                             format_index = p[DESC_bFormatIndex];
                             num_of_frames = p[DESC_bNumFrameDescriptors];
 
+                            USB_ASSERT(format_index != 0);
+                            USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
+
                             video_class->format[format_index - 1].num_of_frames = num_of_frames;
                             video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_UNCOMPRESSED;
                             break;
@@ -444,12 +448,20 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                             format_index = p[DESC_bFormatIndex];
                             num_of_frames = p[DESC_bNumFrameDescriptors];
 
+                            USB_ASSERT(format_index != 0);
+                            USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
+
                             video_class->format[format_index - 1].num_of_frames = num_of_frames;
                             video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_MJPEG;
                             break;
                         case VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
                             frame_index = p[DESC_bFrameIndex];
 
+                            USB_ASSERT(format_index != 0);
+                            USB_ASSERT(frame_index != 0);
+                            USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
+                            USB_ASSERT(frame_index <= CONFIG_USBHOST_VIDEO_MAX_FRAMES);
+
                             video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wWidth;
                             video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wHeight;
                             video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval;
@@ -457,6 +469,11 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
                         case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE:
                             frame_index = p[DESC_bFrameIndex];
 
+                            USB_ASSERT(format_index != 0);
+                            USB_ASSERT(frame_index != 0);
+                            USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
+                            USB_ASSERT(frame_index <= CONFIG_USBHOST_VIDEO_MAX_FRAMES);
+
                             video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wWidth;
                             video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wHeight;
                             video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->dwDefaultFrameInterval;

+ 10 - 2
components/drivers/usb/cherryusb/class/video/usbh_video.h

@@ -11,6 +11,14 @@
 #define USBH_VIDEO_FORMAT_UNCOMPRESSED 0
 #define USBH_VIDEO_FORMAT_MJPEG        1
 
+#ifndef CONFIG_USBHOST_VIDEO_MAX_FRAMES
+#define CONFIG_USBHOST_VIDEO_MAX_FRAMES 12
+#endif
+
+#ifndef CONFIG_USBHOST_VIDEO_MAX_FORMATS
+#define CONFIG_USBHOST_VIDEO_MAX_FORMATS 3
+#endif
+
 struct usbh_video_resolution {
     uint16_t wWidth;
     uint16_t wHeight;
@@ -18,7 +26,7 @@ struct usbh_video_resolution {
 };
 
 struct usbh_video_format {
-    struct usbh_video_resolution frame[12];
+    struct usbh_video_resolution frame[CONFIG_USBHOST_VIDEO_MAX_FRAMES];
     uint8_t format_type;
     uint8_t num_of_frames;
 };
@@ -55,7 +63,7 @@ struct usbh_video {
     uint16_t bcdVDC;
     uint8_t num_of_intf_altsettings;
     uint8_t num_of_formats;
-    struct usbh_video_format format[3];
+    struct usbh_video_format format[CONFIG_USBHOST_VIDEO_MAX_FORMATS];
 
     void *user_data;
 };

+ 0 - 5
components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c

@@ -365,14 +365,9 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
 
     switch (cmd->Oid) {
         case OID_GEN_RNDIS_CONFIG_PARAMETER:
-            param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
-            USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
-                        param->ParameterNameOffset, param->ParameterNameLength,
-                        param->ParameterValueOffset, param->ParameterValueLength);
             break;
         case OID_GEN_CURRENT_PACKET_FILTER:
             if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
-                USB_LOG_WRN("PACKET_FILTER!\r\n");
                 resp->Status = RNDIS_STATUS_INVALID_DATA;
             } else {
                 uint32_t *filter;

+ 148 - 0
components/drivers/usb/cherryusb/common/usb_mempool.h

@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_MEMPOOL_H
+#define USB_MEMPOOL_H
+
+#include "usb_osal.h"
+#include "usb_ringbuffer.h"
+
+#ifndef CONFIG_USB_MEMPOOL_MAX_BLOCK_COUNT
+#define CONFIG_USB_MEMPOOL_MAX_BLOCK_COUNT 16
+#endif
+
+struct usb_mempool {
+    usb_ringbuffer_t in;
+    usb_ringbuffer_t out;
+    usb_osal_sem_t out_sem;
+
+    void *block;
+    uint32_t block_size;
+    uint32_t block_count;
+    uint8_t in_buf[sizeof(uintptr_t) * CONFIG_USB_MEMPOOL_MAX_BLOCK_COUNT];
+    uint8_t out_buf[sizeof(uintptr_t) * CONFIG_USB_MEMPOOL_MAX_BLOCK_COUNT];
+};
+
+#define usb_mempool_osal_sem_create(max_count) usb_osal_sem_create_counting(max_count)
+#define usb_mempool_osal_sem_delete(sem) usb_osal_sem_delete(sem)
+#define usb_mempool_osal_sem_take(sem, timeout) usb_osal_sem_take(sem, timeout)
+#define usb_mempool_osal_sem_give(sem) usb_osal_sem_give(sem)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int usb_mempool_create(struct usb_mempool *pool, void *block, uint32_t block_size, uint32_t block_count)
+{
+    uintptr_t *item;
+    uint32_t addr;
+
+    if (block_count > CONFIG_USB_MEMPOOL_MAX_BLOCK_COUNT) {
+        return -1;
+    }
+
+    if (block_size % 4) {
+        return -1;
+    }
+
+    if (usb_ringbuffer_init(&pool->in, pool->in_buf, sizeof(uintptr_t) * block_count) == -1) {
+        return -1;
+    }
+
+    if (usb_ringbuffer_init(&pool->out, pool->out_buf, sizeof(uintptr_t) * block_count) == -1) {
+        return -1;
+    }
+
+    pool->out_sem = usb_mempool_osal_sem_create(block_count);
+    if (pool->out_sem == NULL) {
+        return -1;
+    }
+
+    pool->block = block;
+    pool->block_size = block_size;
+    pool->block_count = block_count;
+
+    for (uint32_t i = 0; i < pool->block_count; i++) {
+        item = (uintptr_t *)((uint8_t *)pool->block + i * pool->block_size);
+        addr = (uintptr_t)item;
+        usb_ringbuffer_write(&pool->in, &addr, sizeof(uintptr_t));
+    }
+
+    return 0;
+}
+
+static inline void usb_mempool_delete(struct usb_mempool *pool)
+{
+    usb_ringbuffer_reset(&pool->in);
+    usb_ringbuffer_reset(&pool->out);
+    usb_mempool_osal_sem_delete(pool->out_sem);
+}
+
+static inline uintptr_t *usb_mempool_alloc(struct usb_mempool *pool)
+{
+    uintptr_t *addr;
+    uint32_t len;
+
+    len = usb_ringbuffer_read(&pool->in, (uintptr_t *)&addr, sizeof(uintptr_t));
+    if (len == 0) {
+        return NULL;
+    } else {
+        return addr;
+    }
+}
+
+static inline int usb_mempool_free(struct usb_mempool *pool, uintptr_t *item)
+{
+    uintptr_t addr;
+
+    addr = (uintptr_t)item;
+    return usb_ringbuffer_write(&pool->in, &addr, sizeof(uintptr_t));
+}
+
+static inline int usb_mempool_send(struct usb_mempool *pool, uintptr_t *item)
+{
+    uintptr_t addr;
+
+    addr = (uintptr_t)item;
+    usb_ringbuffer_write(&pool->out, &addr, sizeof(uintptr_t));
+    return usb_mempool_osal_sem_give(pool->out_sem);
+}
+
+static inline int usb_mempool_recv(struct usb_mempool *pool, uintptr_t **item, uint32_t timeout)
+{
+    uint32_t len;
+    int ret;
+
+    ret = usb_mempool_osal_sem_take(pool->out_sem, timeout);
+    if (ret < 0) {
+        return -1;
+    }
+
+    len = usb_ringbuffer_read(&pool->out, (uintptr_t *)item, sizeof(uintptr_t));
+    if (len == 0) {
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+static inline void usb_mempool_reset(struct usb_mempool *pool)
+{
+    uintptr_t *item;
+
+    usb_ringbuffer_reset(&pool->in);
+    usb_ringbuffer_reset(&pool->out);
+
+    for (uint32_t i = 0; i < pool->block_count; i++) {
+        item = (uintptr_t *)((uint8_t *)pool->block + i * pool->block_size);
+        usb_mempool_free(pool, item);
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

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

@@ -45,6 +45,7 @@ void usb_osal_thread_delete(usb_osal_thread_t thread);
 void usb_osal_thread_schedule_other(void);
 
 usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
+usb_osal_sem_t usb_osal_sem_create_counting(uint32_t max_count);
 void usb_osal_sem_delete(usb_osal_sem_t sem);
 int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
 int usb_osal_sem_give(usb_osal_sem_t sem);

+ 494 - 0
components/drivers/usb/cherryusb/common/usb_ringbuffer.h

@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2022, Egahp
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_RINGBUFFER_H
+#define USB_RINGBUFFER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    uint32_t in;   /*!< Define the write pointer.               */
+    uint32_t out;  /*!< Define the read pointer.                */
+    uint32_t mask; /*!< Define the write and read pointer mask. */
+    void *pool;    /*!< Define the memory pointer.              */
+} usb_ringbuffer_t;
+
+/*****************************************************************************
+* @brief        init ringbuffer
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    pool        memory pool address
+* @param[in]    size        memory size in byte,
+*                           must be power of 2 !!!
+*
+* @retval int               0:Success -1:Error
+*****************************************************************************/
+static inline int usb_ringbuffer_init(usb_ringbuffer_t *rb, void *pool, uint32_t size)
+{
+    if (NULL == rb) {
+        return -1;
+    }
+
+    if (NULL == pool) {
+        return -1;
+    }
+
+    if ((size < 2) || (size & (size - 1))) {
+        return -1;
+    }
+
+    rb->in = 0;
+    rb->out = 0;
+    rb->mask = size - 1;
+    rb->pool = pool;
+
+    return 0;
+}
+
+/*****************************************************************************
+* @brief        reset ringbuffer, clean all data,
+*               should be add lock in multithread
+*
+* @param[in]    rb          ringbuffer instance
+*
+*****************************************************************************/
+static inline void usb_ringbuffer_reset(usb_ringbuffer_t *rb)
+{
+    rb->in = 0;
+    rb->out = 0;
+}
+
+/*****************************************************************************
+* @brief        reset ringbuffer, clean all data,
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+*
+*****************************************************************************/
+static inline void usb_ringbuffer_reset_read(usb_ringbuffer_t *rb)
+{
+    rb->out = rb->in;
+}
+
+/*****************************************************************************
+* @brief        get ringbuffer total size in byte
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval uint32_t          total size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_get_size(usb_ringbuffer_t *rb)
+{
+    return rb->mask + 1;
+}
+
+/*****************************************************************************
+* @brief        get ringbuffer used size in byte
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval uint32_t          used size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_get_used(usb_ringbuffer_t *rb)
+{
+    return rb->in - rb->out;
+}
+
+/*****************************************************************************
+* @brief        get ringbuffer free size in byte
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval uint32_t          free size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_get_free(usb_ringbuffer_t *rb)
+{
+    return (rb->mask + 1) - (rb->in - rb->out);
+}
+
+/*****************************************************************************
+* @brief        check if ringbuffer is full
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval true              full
+* @retval false             not full
+*****************************************************************************/
+static inline bool usb_ringbuffer_check_full(usb_ringbuffer_t *rb)
+{
+    return usb_ringbuffer_get_used(rb) > rb->mask;
+}
+
+/*****************************************************************************
+* @brief        check if ringbuffer is empty
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval true              empty
+* @retval false             not empty
+*****************************************************************************/
+static inline bool usb_ringbuffer_check_empty(usb_ringbuffer_t *rb)
+{
+    return rb->in == rb->out;
+}
+
+/*****************************************************************************
+* @brief        write one byte to ringbuffer,
+*               should be add lock in multithread,
+*               in single write thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    byte        data
+*
+* @retval true              Success
+* @retval false             ringbuffer is full
+*****************************************************************************/
+static inline bool usb_ringbuffer_write_byte(usb_ringbuffer_t *rb, uint8_t byte)
+{
+    if (usb_ringbuffer_check_full(rb)) {
+        return false;
+    }
+
+    ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
+    rb->in++;
+    return true;
+}
+
+/*****************************************************************************
+* @brief        overwrite one byte to ringbuffer, drop oldest data,
+*               should be add lock always
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    byte        data
+*
+* @retval true              Success
+* @retval false             always return true
+*****************************************************************************/
+static inline bool usb_ringbuffer_overwrite_byte(usb_ringbuffer_t *rb, uint8_t byte)
+{
+    if (usb_ringbuffer_check_full(rb)) {
+        rb->out++;
+    }
+
+    ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
+    rb->in++;
+    return true;
+}
+
+/*****************************************************************************
+* @brief        peek one byte from ringbuffer,
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    byte        pointer to save data
+*
+* @retval true              Success
+* @retval false             ringbuffer is empty
+*****************************************************************************/
+static inline bool usb_ringbuffer_peek_byte(usb_ringbuffer_t *rb, uint8_t *byte)
+{
+    if (usb_ringbuffer_check_empty(rb)) {
+        return false;
+    }
+
+    *byte = ((uint8_t *)(rb->pool))[rb->out & rb->mask];
+    return true;
+}
+
+/*****************************************************************************
+* @brief        read one byte from ringbuffer,
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    byte        pointer to save data
+*
+* @retval true              Success
+* @retval false             ringbuffer is empty
+*****************************************************************************/
+static inline bool usb_ringbuffer_read_byte(usb_ringbuffer_t *rb, uint8_t *byte)
+{
+    bool ret;
+    ret = usb_ringbuffer_peek_byte(rb, byte);
+    rb->out += ret;
+    return ret;
+}
+
+/*****************************************************************************
+* @brief        drop one byte from ringbuffer,
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+*
+* @retval true              Success
+* @retval false             ringbuffer is empty
+*****************************************************************************/
+static inline bool usb_ringbuffer_drop_byte(usb_ringbuffer_t *rb)
+{
+    if (usb_ringbuffer_check_empty(rb)) {
+        return false;
+    }
+
+    rb->out += 1;
+    return true;
+}
+
+/*****************************************************************************
+* @brief        write data to ringbuffer,
+*               should be add lock in multithread,
+*               in single write thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    data        data pointer
+* @param[in]    size        size in byte
+*
+* @retval uint32_t          actual write size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_write(usb_ringbuffer_t *rb, void *data, uint32_t size)
+{
+    uint32_t unused;
+    uint32_t offset;
+    uint32_t remain;
+
+    unused = (rb->mask + 1) - (rb->in - rb->out);
+
+    if (size > unused) {
+        size = unused;
+    }
+
+    offset = rb->in & rb->mask;
+
+    remain = rb->mask + 1 - offset;
+    remain = remain > size ? size : remain;
+
+    memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
+    memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
+
+    rb->in += size;
+
+    return size;
+}
+
+/*****************************************************************************
+* @brief        write data to ringbuffer,
+*               should be add lock always
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    data        data pointer
+* @param[in]    size        size in byte
+*
+* @retval uint32_t          actual write size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_overwrite(usb_ringbuffer_t *rb, void *data, uint32_t size)
+{
+    uint32_t unused;
+    uint32_t offset;
+    uint32_t remain;
+
+    unused = (rb->mask + 1) - (rb->in - rb->out);
+
+    if (size > unused) {
+        if (size > (rb->mask + 1)) {
+            size = rb->mask + 1;
+        }
+
+        rb->out += size - unused;
+    }
+
+    offset = rb->in & rb->mask;
+
+    remain = rb->mask + 1 - offset;
+    remain = remain > size ? size : remain;
+
+    memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
+    memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
+
+    rb->in += size;
+
+    return size;
+}
+
+/*****************************************************************************
+* @brief        peek data from ringbuffer
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    data        data pointer
+* @param[in]    size        size in byte
+*
+* @retval uint32_t          actual peek size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_peek(usb_ringbuffer_t *rb, void *data, uint32_t size)
+{
+    uint32_t used;
+    uint32_t offset;
+    uint32_t remain;
+
+    used = rb->in - rb->out;
+    if (size > used) {
+        size = used;
+    }
+
+    offset = rb->out & rb->mask;
+
+    remain = rb->mask + 1 - offset;
+    remain = remain > size ? size : remain;
+
+    memcpy(data, ((uint8_t *)(rb->pool)) + offset, remain);
+    memcpy((uint8_t *)data + remain, rb->pool, size - remain);
+
+    return size;
+}
+
+/*****************************************************************************
+* @brief        read data from ringbuffer
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    data        data pointer
+* @param[in]    size        size in byte
+*
+* @retval uint32_t          actual read size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_read(usb_ringbuffer_t *rb, void *data, uint32_t size)
+{
+    size = usb_ringbuffer_peek(rb, data, size);
+    rb->out += size;
+    return size;
+}
+
+/*****************************************************************************
+* @brief        drop data from ringbuffer
+*               should be add lock in multithread,
+*               in single read thread not need lock
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    size        size in byte
+*
+* @retval uint32_t          actual drop size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_drop(usb_ringbuffer_t *rb, uint32_t size)
+{
+    uint32_t used;
+
+    used = rb->in - rb->out;
+    if (size > used) {
+        size = used;
+    }
+
+    rb->out += size;
+    return size;
+}
+
+/*****************************************************************************
+* @brief        linear write setup, get write pointer and max linear size.
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    size        pointer to store max linear size in byte
+*
+* @retval void*             write memory pointer
+*****************************************************************************/
+static inline void *usb_ringbuffer_linear_write_setup(usb_ringbuffer_t *rb, uint32_t *size)
+{
+    uint32_t unused;
+    uint32_t offset;
+    uint32_t remain;
+
+    unused = (rb->mask + 1) - (rb->in - rb->out);
+
+    offset = rb->in & rb->mask;
+
+    remain = rb->mask + 1 - offset;
+    remain = remain > unused ? unused : remain;
+
+    if (remain) {
+        *size = remain;
+        return ((uint8_t *)(rb->pool)) + offset;
+    } else {
+        *size = unused - remain;
+        return rb->pool;
+    }
+}
+
+/*****************************************************************************
+* @brief        linear read setup, get read pointer and max linear size.
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    size        pointer to store max linear size in byte
+*
+* @retval void*
+*****************************************************************************/
+static inline void *usb_ringbuffer_linear_read_setup(usb_ringbuffer_t *rb, uint32_t *size)
+{
+    uint32_t used;
+    uint32_t offset;
+    uint32_t remain;
+
+    used = rb->in - rb->out;
+
+    offset = rb->out & rb->mask;
+
+    remain = rb->mask + 1 - offset;
+    remain = remain > used ? used : remain;
+
+    if (remain) {
+        *size = remain;
+        return ((uint8_t *)(rb->pool)) + offset;
+    } else {
+        *size = used - remain;
+        return rb->pool;
+    }
+}
+
+/*****************************************************************************
+* @brief        linear write done, add write pointer only
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    size        write size in byte
+*
+* @retval uint32_t          actual write size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_linear_write_done(usb_ringbuffer_t *rb, uint32_t size)
+{
+    uint32_t unused;
+
+    unused = (rb->mask + 1) - (rb->in - rb->out);
+    if (size > unused) {
+        size = unused;
+    }
+    rb->in += size;
+
+    return size;
+}
+
+/*****************************************************************************
+* @brief        linear read done, add read pointer only
+*
+* @param[in]    rb          ringbuffer instance
+* @param[in]    size        read size in byte
+*
+* @retval uint32_t          actual read size in byte
+*****************************************************************************/
+static inline uint32_t usb_ringbuffer_linear_read_done(usb_ringbuffer_t *rb, uint32_t size)
+{
+    return usb_ringbuffer_drop(rb, size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

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

@@ -15,7 +15,7 @@
 #undef CHERRYUSB_VERSION_STR
 #endif
 
-#define CHERRYUSB_VERSION     0x010600
-#define CHERRYUSB_VERSION_STR "v1.6.0"
+#define CHERRYUSB_VERSION     0x010601
+#define CHERRYUSB_VERSION_STR "v1.6.1"
 
 #endif

+ 3 - 4
components/drivers/usb/cherryusb/core/usbd_core.c

@@ -1364,9 +1364,9 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin
 #endif
 
     g_usbd_core[busid].event_handler = event_handler;
-    ret = usb_dc_init(busid);
     usbd_class_event_notify_handler(busid, USBD_EVENT_INIT, NULL);
     g_usbd_core[busid].event_handler(busid, USBD_EVENT_INIT);
+    ret = usb_dc_init(busid);
     return ret;
 }
 
@@ -1374,8 +1374,6 @@ int usbd_deinitialize(uint8_t busid)
 {
     USB_ASSERT_MSG(busid < CONFIG_USBDEV_MAX_BUS, "bus overflow\r\n");
 
-    g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
-    usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
     usb_dc_deinit(busid);
 #ifdef CONFIG_USBDEV_EP0_THREAD
     if (g_usbd_core[busid].usbd_ep0_thread) {
@@ -1385,6 +1383,7 @@ int usbd_deinitialize(uint8_t busid)
         usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq);
     }
 #endif
-
+    g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
+    usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
     return 0;
 }

+ 2 - 0
components/drivers/usb/cherryusb/core/usbd_core.h

@@ -24,6 +24,8 @@ extern "C" {
 #include "usb_dc.h"
 #include "usb_osal.h"
 #include "usb_memcpy.h"
+#include "usb_ringbuffer.h"
+#include "usb_mempool.h"
 #include "usb_dcache.h"
 #include "usb_version.h"
 

+ 8 - 7
components/drivers/usb/cherryusb/core/usbh_core.c

@@ -274,8 +274,8 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
                     break;
             }
             /* skip to next descriptor */
-            p += p[DESC_bLength];
             desc_len += p[DESC_bLength];
+            p += p[DESC_bLength];
         }
     }
     return 0;
@@ -603,9 +603,8 @@ void usbh_hubport_release(struct usbh_hubport *hport)
             hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, i, USBH_EVENT_INTERFACE_STOP);
         }
         hport->config.config_desc.bNumInterfaces = 0;
-        if (hport->mutex) {
-            usb_osal_mutex_delete(hport->mutex);
-        }
+        usb_osal_mutex_take(hport->mutex);
+        usb_osal_mutex_delete(hport->mutex);
         USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hport->bus->busid, hport->parent->index, hport->port);
         hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_DISCONNECTED);
     }
@@ -666,8 +665,6 @@ int usbh_deinitialize(uint8_t busid)
 
     bus = &g_usbhost_bus[busid];
 
-    bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_DEINIT);
-
     usbh_hub_deinitialize(bus);
 
     usb_slist_remove(&g_bus_head, &bus->list);
@@ -685,6 +682,10 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
         return -USB_ERR_INVAL;
     }
 
+    if (!hport->connected) {
+        return -USB_ERR_NODEV;
+    }
+
     urb = &hport->ep0_urb;
 
     usb_osal_mutex_take(hport->mutex);
@@ -1214,4 +1215,4 @@ __WEAK uint8_t usbh_get_hport_active_config_index(struct usbh_hubport *hport)
     ARG_UNUSED(hport);
 
     return 0; // Default to configuration index 0
-}
+}

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

@@ -21,6 +21,8 @@
 #include "usb_osal.h"
 #include "usbh_hub.h"
 #include "usb_memcpy.h"
+#include "usb_ringbuffer.h"
+#include "usb_mempool.h"
 #include "usb_dcache.h"
 #include "usb_version.h"
 
@@ -201,7 +203,7 @@ struct usbh_bus {
     struct usbh_devaddr_map devgen;
     usb_osal_thread_t hub_thread;
     usb_osal_mq_t hub_mq;
-    usb_osal_mutex_t mutex;
+    usb_osal_sem_t hub_sem;
     usbh_event_handler_t event_handler;
 };
 

+ 1 - 1
components/drivers/usb/cherryusb/core/usbotg_core.c

@@ -38,7 +38,7 @@ static void usbotg_host_initialize(uint8_t busid)
     USB_LOG_INFO("Switch to HOST mode\r\n");
 
     g_usbotg_core[busid].usbh_initialized = true;
-    usbh_initialize(busid, g_usbotg_core[busid].reg_base);
+    usbh_initialize(busid, g_usbotg_core[busid].reg_base, NULL);
 }
 
 static void usbotg_device_initialize(uint8_t busid)

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

@@ -157,7 +157,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c

@@ -122,7 +122,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c

@@ -195,7 +195,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c

@@ -126,7 +126,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c

@@ -201,7 +201,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c

@@ -145,7 +145,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

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

@@ -72,7 +72,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 36 - 44
components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c

@@ -94,7 +94,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
@@ -112,49 +112,41 @@ static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
     0x09, 0x02, // USAGE (Mouse)
     0xA1, 0x01, // COLLECTION (Application)
-    0x09, 0x01, //   USAGE (Pointer)
-
-    0xA1, 0x00, //   COLLECTION (Physical)
-    0x05, 0x09, //     USAGE_PAGE (Button)
-    0x19, 0x01, //     USAGE_MINIMUM (Button 1)
-    0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
-
-    0x15, 0x00, //     LOGICAL_MINIMUM (0)
-    0x25, 0x01, //     LOGICAL_MAXIMUM (1)
-    0x95, 0x03, //     REPORT_COUNT (3)
-    0x75, 0x01, //     REPORT_SIZE (1)
-
-    0x81, 0x02, //     INPUT (Data,Var,Abs)
-    0x95, 0x01, //     REPORT_COUNT (1)
-    0x75, 0x05, //     REPORT_SIZE (5)
-    0x81, 0x01, //     INPUT (Cnst,Var,Abs)
-
-    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
-    0x09, 0x30, //     USAGE (X)
-    0x09, 0x31, //     USAGE (Y)
-    0x09, 0x38,
-
-    0x15, 0x81, //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7F, //     LOGICAL_MAXIMUM (127)
-    0x75, 0x08, //     REPORT_SIZE (8)
-    0x95, 0x03, //     REPORT_COUNT (2)
-
-    0x81, 0x06, //     INPUT (Data,Var,Rel)
-    0xC0, 0x09,
-    0x3c, 0x05,
-    0xff, 0x09,
-
-    0x01, 0x15,
-    0x00, 0x25,
-    0x01, 0x75,
-    0x01, 0x95,
-
-    0x02, 0xb1,
-    0x22, 0x75,
-    0x06, 0x95,
-    0x01, 0xb1,
-
-    0x01, 0xc0 //   END_COLLECTION
+    0x09, 0x01, // USAGE (Pointer)
+    0xA1, 0x00, // COLLECTION (Physical)
+    0x05, 0x09, // USAGE_PAGE (Button)
+    0x19, 0x01, // USAGE_MINIMUM (Button 1)
+    0x29, 0x03, // USAGE_MAXIMUM (Button 3)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x95, 0x03, // REPORT_COUNT (3)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x81, 0x02, // INPUT (Data,Var,Abs)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0x75, 0x05, // REPORT_SIZE (5)
+    0x81, 0x01, // INPUT (Cnst,Var,Abs)
+    0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+    0x09, 0x30, // USAGE (X)
+    0x09, 0x31, // USAGE (Y)
+    0x09, 0x38, // Usage (Wheel)
+    0x15, 0x81, // LOGICAL_MINIMUM (-127)
+    0x25, 0x7F, // LOGICAL_MAXIMUM (127)
+    0x75, 0x08, // REPORT_SIZE (8)
+    0x95, 0x03, // REPORT_COUNT (2)
+    0x81, 0x06, // INPUT (Data,Var,Rel)
+    0xC0,       // END_COLLECTION
+    0x09, 0x3c, // USAGE (Motion Wakeup)
+    0x05, 0xff, // USAGE_PAGE (Vendor Defined 0xFF)
+    0x09, 0x01, // USAGE (Vendor Usage 1)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x95, 0x02, // REPORT_COUNT (2)
+    0xb1, 0x22, // FEATURE (Data,Var,Abs,NPrf)
+    0x75, 0x06, // REPORT_SIZE (6)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0xb1, 0x01, // FEATURE (Cnst,Ary,Abs)
+    0xc0        // END_COLLECTION
 };
 
 /*!< mouse report struct */

+ 1 - 1
components/drivers/usb/cherryusb/demo/cdc_acm_mavlink_template.c

@@ -76,7 +76,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

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

@@ -85,7 +85,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c

@@ -89,7 +89,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/cdc_acm_rttchardev_template.c

@@ -74,7 +74,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/cdc_acm_template.c

@@ -74,7 +74,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 2 - 2
components/drivers/usb/cherryusb/demo/cdc_ecm_template.c

@@ -82,7 +82,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 4) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
@@ -351,7 +351,7 @@ struct usbd_interface intf1;
 /* ecm only supports in linux, and you should input the following command
  *
  * sudo ifconfig enxaabbccddeeff up
- * sudo dhcpclient enxaabbccddeeff
+ * sudo dhclient enxaabbccddeeff
 */
 void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
 {

+ 1 - 1
components/drivers/usb/cherryusb/demo/cdc_rndis_template.c

@@ -78,7 +78,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 0 - 372
components/drivers/usb/cherryusb/demo/dfu_st_cubemx_main.c

@@ -1,372 +0,0 @@
-/* USER CODE BEGIN Header */
-/**
-  ******************************************************************************
-  * @file           : main.c
-  * @brief          : Main program body
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-#include "usbd_core.h"
-#include "usb_dfu.h"
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN PTD */
-
-/* USER CODE END PTD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-UART_HandleTypeDef huart1;
-
-PCD_HandleTypeDef hpcd_USB_FS;
-
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-void SystemClock_Config(void);
-static void MX_GPIO_Init(void);
-static void MX_USART1_UART_Init(void);
-static void MX_USB_PCD_Init(void);
-/* USER CODE BEGIN PFP */
-typedef void (*pFunction)(void);
-static void jump_app(void)
-{
-  pFunction JumpToApplication;
-  uint32_t JumpAddress;
-
-  if (((*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFFB000) == 0x20000000)
-  {
-    /* Jump to user application */
-    /*!< Jump to app reset_handler */
-    JumpAddress = *(__IO uint32_t *)(USBD_DFU_APP_DEFAULT_ADD + 4);
-    JumpToApplication = (pFunction)JumpAddress;
-
-    /* Initialize user application's Stack Pointer */
-    __set_MSP(*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD);
-    JumpToApplication();
-  }
-}
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-int fputc(int ch, FILE *f)
-{
-    while ((USART1->SR & USART_SR_TXE) == 0)
-        ;
-    USART1->DR = ch;
-    return ch;
-}
-
-void usb_dc_low_level_init(void)
-{
-    /* Peripheral clock enable */
-    __HAL_RCC_USB_CLK_ENABLE();
-    /* USB interrupt Init */
-    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
-    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
-
-}
-
-uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
-{
-  uint32_t i = 0;
-  uint8_t *psrc = src;
-
-  for (i = 0; i < len; i++)
-  {
-    dest[i] = *psrc++;
-  }
-  /* Return a valid address to avoid HardFault */
-  return (uint8_t *)(dest);
-}
-
-uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
-{
-  HAL_FLASH_Unlock();
-  uint32_t i = 0;
-
-  for (i = 0; i < len; i += 4)
-  {
-    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
-     * be done by byte */
-    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest + i),
-                          *(uint32_t *)(src + i)) == HAL_OK)
-    {
-      /* Check the written value */
-      if (*(uint32_t *)(src + i) != *(uint32_t *)(dest + i))
-      {
-        /* Flash content doesn't match SRAM content */
-        return (1);
-      }
-    }
-    else
-    {
-      /* Error occurred while writing data in Flash memory */
-      return (2);
-    }
-  }
-  return 0;
-}
-
-uint16_t dfu_erase_flash(uint32_t add)
-{
-  HAL_FLASH_Unlock();
-  uint32_t PageError;
-  /* Variable contains Flash operation status */
-  HAL_StatusTypeDef status;
-  FLASH_EraseInitTypeDef eraseinitstruct;
-
-  eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
-  eraseinitstruct.PageAddress = add;
-  eraseinitstruct.NbPages = 1U;
-  status = HAL_FLASHEx_Erase(&eraseinitstruct, &PageError);
-  return 0;
-}
-
-void dfu_leave(void)
-{
-  NVIC_SystemReset();
-}
-
-/* USER CODE END 0 */
-
-/**
-  * @brief  The application entry point.
-  * @retval int
-  */
-int main(void)
-{
-  /* USER CODE BEGIN 1 */
-  jump_app();
-  /* USER CODE END 1 */
-
-  /* MCU Configuration--------------------------------------------------------*/
-
-  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
-  HAL_Init();
-
-  /* USER CODE BEGIN Init */
-
-  /* USER CODE END Init */
-
-  /* Configure the system clock */
-  SystemClock_Config();
-
-  /* USER CODE BEGIN SysInit */
-
-  /* USER CODE END SysInit */
-
-  /* Initialize all configured peripherals */
-  MX_GPIO_Init();
-  MX_USART1_UART_Init();
-  //MX_USB_PCD_Init();
-  /* USER CODE BEGIN 2 */
-
-
-//    extern void cdc_acm_msc_init(void);
-//    cdc_acm_msc_init();
-    extern void dfu_flash_init(void);
-		dfu_flash_init();
-
-  /* USER CODE END 2 */
-
-  /* Infinite loop */
-  /* USER CODE BEGIN WHILE */
-    while (1) {
-    /* USER CODE END WHILE */
-
-    /* USER CODE BEGIN 3 */
-//        extern void cdc_acm_data_send_with_dtr_test(void);
-//        cdc_acm_data_send_with_dtr_test();
-//        HAL_Delay(100);
-    }
-  /* USER CODE END 3 */
-}
-
-/**
-  * @brief System Clock Configuration
-  * @retval None
-  */
-void SystemClock_Config(void)
-{
-  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
-  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
-
-  /** Initializes the RCC Oscillators according to the specified parameters
-  * in the RCC_OscInitTypeDef structure.
-  */
-  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
-  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
-  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
-  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
-  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
-  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
-  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
-  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  /** Initializes the CPU, AHB and APB buses clocks
-  */
-  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
-                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
-  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
-  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
-  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
-  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
-  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
-  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
-  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
-  {
-    Error_Handler();
-  }
-}
-
-/**
-  * @brief USART1 Initialization Function
-  * @param None
-  * @retval None
-  */
-static void MX_USART1_UART_Init(void)
-{
-
-  /* USER CODE BEGIN USART1_Init 0 */
-
-  /* USER CODE END USART1_Init 0 */
-
-  /* USER CODE BEGIN USART1_Init 1 */
-
-  /* USER CODE END USART1_Init 1 */
-  huart1.Instance = USART1;
-  huart1.Init.BaudRate = 115200;
-  huart1.Init.WordLength = UART_WORDLENGTH_8B;
-  huart1.Init.StopBits = UART_STOPBITS_1;
-  huart1.Init.Parity = UART_PARITY_NONE;
-  huart1.Init.Mode = UART_MODE_TX_RX;
-  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
-  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
-  if (HAL_UART_Init(&huart1) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  /* USER CODE BEGIN USART1_Init 2 */
-
-  /* USER CODE END USART1_Init 2 */
-
-}
-
-/**
-  * @brief USB Initialization Function
-  * @param None
-  * @retval None
-  */
-static void MX_USB_PCD_Init(void)
-{
-
-  /* USER CODE BEGIN USB_Init 0 */
-
-  /* USER CODE END USB_Init 0 */
-
-  /* USER CODE BEGIN USB_Init 1 */
-
-  /* USER CODE END USB_Init 1 */
-  hpcd_USB_FS.Instance = USB;
-  hpcd_USB_FS.Init.dev_endpoints = 8;
-  hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
-  hpcd_USB_FS.Init.low_power_enable = DISABLE;
-  hpcd_USB_FS.Init.lpm_enable = DISABLE;
-  hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
-  if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  /* USER CODE BEGIN USB_Init 2 */
-
-  /* USER CODE END USB_Init 2 */
-
-}
-
-/**
-  * @brief GPIO Initialization Function
-  * @param None
-  * @retval None
-  */
-static void MX_GPIO_Init(void)
-{
-
-  /* GPIO Ports Clock Enable */
-  __HAL_RCC_GPIOD_CLK_ENABLE();
-  __HAL_RCC_GPIOA_CLK_ENABLE();
-
-}
-
-/* USER CODE BEGIN 4 */
-
-/* USER CODE END 4 */
-
-/**
-  * @brief  This function is executed in case of error occurrence.
-  * @retval None
-  */
-void Error_Handler(void)
-{
-  /* USER CODE BEGIN Error_Handler_Debug */
-    /* User can add his own implementation to report the HAL error return state */
-    __disable_irq();
-    while (1) {
-    }
-  /* USER CODE END Error_Handler_Debug */
-}
-
-#ifdef  USE_FULL_ASSERT
-/**
-  * @brief  Reports the name of the source file and the source line number
-  *         where the assert_param error has occurred.
-  * @param  file: pointer to the source file name
-  * @param  line: assert_param error line source number
-  * @retval None
-  */
-void assert_failed(uint8_t *file, uint32_t line)
-{
-  /* USER CODE BEGIN 6 */
-    /* User can add his own implementation to report the file name and line number,
-     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
-  /* USER CODE END 6 */
-}
-#endif /* USE_FULL_ASSERT */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 52 - 9
components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c → components/drivers/usb/cherryusb/demo/dfu_template.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -7,13 +7,13 @@
 #include "usbd_dfu.h"
 
 #define USBD_VID           0x0483
-#define USBD_PID           0xDF11
+#define USBD_PID           0xdf11
 #define USBD_MAX_POWER     100
 #define USBD_LANGID_STRING 1033
 
-#define FLASH_DESC_STR "@Internal Flash   /0x08000000/16*001Ka,112*01Kg"
+#define USB_CONFIG_SIZE (9 + DFU_DESCRIPTOR_LEN)
 
-#define USB_CONFIG_SIZE (9 + 9 + 9)
+#define FLASH_DESC_STR      "@Internal Flash   /0x08000000/16*128Kg"
 
 static const uint8_t device_descriptor[] = {
     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
@@ -21,7 +21,7 @@ static const uint8_t device_descriptor[] = {
 
 static const uint8_t config_descriptor[] = {
     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
-    DFU_DESCRIPTOR_INIT()
+    DFU_DESCRIPTOR_INIT(4)
 };
 
 static const uint8_t device_quality_descriptor[] = {
@@ -45,6 +45,7 @@ static const char *string_descriptors[] = {
     "CherryUSB",                  /* Manufacturer */
     "CherryUSB DFU DEMO",         /* Product */
     "2022123456",                 /* Serial Number */
+    FLASH_DESC_STR
 };
 
 static const uint8_t *device_descriptor_callback(uint8_t speed)
@@ -64,13 +65,13 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
 }
 
-const struct usb_descriptor dfu_flash_descriptor = {
+const struct usb_descriptor dfu_descriptor = {
     .device_descriptor_callback = device_descriptor_callback,
     .config_descriptor_callback = config_descriptor_callback,
     .device_quality_descriptor_callback = device_quality_descriptor_callback,
@@ -104,10 +105,52 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
 
 struct usbd_interface intf0;
 
-void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
+void dfu_init(uint8_t busid, uintptr_t reg_base)
 {
-    usbd_desc_register(busid, &dfu_flash_descriptor);
+    usbd_desc_register(busid, &dfu_descriptor);
 
     usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }
+
+volatile uint32_t flash_start_address;
+
+void usbd_dfu_begin_load(void)
+{
+    flash_start_address = 0x08000000;
+}
+
+void usbd_dfu_end_load(void)
+{
+}
+
+void usbd_dfu_reset(void)
+{
+    //NVIC_SystemReset();
+}
+
+int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
+{
+    //usb_hexdump(data, length);
+
+    // patch for stm32 special command
+#if 1
+    if (value == 0) {
+        if (data[0] == DFU_SPECIAL_CMD_SET_ADDRESS_POINTER) {
+            memcpy((uint8_t *)&flash_start_address, data, 4);
+        } else if (data[0] == DFU_SPECIAL_CMD_ERASE) {
+            memcpy((uint8_t *)&flash_start_address, data, 4);
+        }
+    } else if (value > 1) {
+        uint32_t addr = (value - 2) * CONFIG_USBDEV_REQUEST_BUFFER_LEN + flash_start_address;
+    }
+#else
+    flash_start_address += length;
+#endif
+    return 0;
+}
+
+int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
+{
+    return 0;
+}

+ 3 - 0
components/drivers/usb/cherryusb/demo/display/README.md

@@ -0,0 +1,3 @@
+Thanks to https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display project.
+
+Install tools/display/xfz1986_usb_graphic_250224_rc_sign.exe in windows before use.

+ 145 - 0
components/drivers/usb/cherryusb/demo/display/usbdisplay_template.c

@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2026, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_display.h"
+
+#define DISPLAY_IN_EP  0x81
+#define DISPLAY_OUT_EP 0x02
+
+#define USBD_VID           0x303A
+#define USBD_PID           0x2987
+#define USBD_MAX_POWER     100
+#define USBD_LANGID_STRING 1033
+
+#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
+
+#ifdef CONFIG_USB_HS
+#define DISPLAY_EP_MPS 512
+#else
+#define DISPLAY_EP_MPS 64
+#endif
+
+static const uint8_t device_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0101, 0x01)
+};
+
+static const uint8_t config_descriptor[] = {
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x00),
+    USB_ENDPOINT_DESCRIPTOR_INIT(DISPLAY_IN_EP, 0x02, DISPLAY_EP_MPS, 0x00),
+    USB_ENDPOINT_DESCRIPTOR_INIT(DISPLAY_OUT_EP, 0x02, DISPLAY_EP_MPS, 0x00),
+};
+
+static const uint8_t device_quality_descriptor[] = {
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x00,
+    0x00,
+};
+
+static const char *string_descriptors[] = {
+    (const char[]){ 0x09, 0x04 },            /* Langid */
+    "CherryUSB",                             /* Manufacturer */
+    "cherryusb_R640x480_Ergb16_Fps30_Bl128", /* Product */
+    // "cherryusb_R640x480_Ejpg9_Fps30_Bl128", /* Product */
+    "2022123456",                            /* Serial Number */
+};
+
+static const uint8_t *device_descriptor_callback(uint8_t speed)
+{
+    return device_descriptor;
+}
+
+static const uint8_t *config_descriptor_callback(uint8_t speed)
+{
+    return config_descriptor;
+}
+
+static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
+{
+    return device_quality_descriptor;
+}
+
+static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
+{
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
+        return NULL;
+    }
+    return string_descriptors[index];
+}
+
+const struct usb_descriptor usbdisplay_descriptor = {
+    .device_descriptor_callback = device_descriptor_callback,
+    .config_descriptor_callback = config_descriptor_callback,
+    .device_quality_descriptor_callback = device_quality_descriptor_callback,
+    .string_descriptor_callback = string_descriptor_callback
+};
+
+static void usbd_event_handler(uint8_t busid, uint8_t event)
+{
+    switch (event) {
+        case USBD_EVENT_RESET:
+            break;
+        case USBD_EVENT_CONNECTED:
+            break;
+        case USBD_EVENT_DISCONNECTED:
+            break;
+        case USBD_EVENT_RESUME:
+            break;
+        case USBD_EVENT_SUSPEND:
+            break;
+        case USBD_EVENT_CONFIGURED:
+            break;
+        case USBD_EVENT_SET_REMOTE_WAKEUP:
+            break;
+        case USBD_EVENT_CLR_REMOTE_WAKEUP:
+            break;
+
+        default:
+            break;
+    }
+}
+
+struct usbd_interface intf0;
+
+struct usbd_display_frame frame_pool[2];
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_display_buffer[2][640 * 480 * 2];
+
+void usbdisplay_init(uint8_t busid, uintptr_t reg_base)
+{
+    frame_pool[0].frame_buf = usb_display_buffer[0];
+    frame_pool[0].frame_bufsize = 640 * 480 * 2;
+    frame_pool[1].frame_buf = usb_display_buffer[1];
+    frame_pool[1].frame_bufsize = 640 * 480 * 2;
+
+    usbd_desc_register(busid, &usbdisplay_descriptor);
+
+    usbd_add_interface(busid, usbd_display_init_intf(&intf0, DISPLAY_OUT_EP, DISPLAY_IN_EP, frame_pool, 2));
+    usbd_initialize(busid, reg_base, usbd_event_handler);
+}
+
+void usbdisplay_poll(void)
+{
+    struct usbd_display_frame *frame;
+    int ret;
+
+    ret = usbd_display_dequeue(&frame, 0xffffffff); // timeout is not useful for baremental
+    if (ret < 0) {
+        return;
+    }
+    USB_LOG_INFO("frame type: %u, frame size %u\r\n", frame->frame_format, frame->frame_size);
+    usbd_display_enqueue(frame);
+}

+ 1 - 1
components/drivers/usb/cherryusb/demo/gamepad_template.c

@@ -89,7 +89,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
 

+ 1 - 1
components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c

@@ -79,7 +79,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/hid_keyboard_template.c

@@ -67,7 +67,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 37 - 45
components/drivers/usb/cherryusb/demo/hid_mouse_template.c

@@ -70,7 +70,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
@@ -88,49 +88,41 @@ static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
     0x09, 0x02, // USAGE (Mouse)
     0xA1, 0x01, // COLLECTION (Application)
-    0x09, 0x01, //   USAGE (Pointer)
-
-    0xA1, 0x00, //   COLLECTION (Physical)
-    0x05, 0x09, //     USAGE_PAGE (Button)
-    0x19, 0x01, //     USAGE_MINIMUM (Button 1)
-    0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
-
-    0x15, 0x00, //     LOGICAL_MINIMUM (0)
-    0x25, 0x01, //     LOGICAL_MAXIMUM (1)
-    0x95, 0x03, //     REPORT_COUNT (3)
-    0x75, 0x01, //     REPORT_SIZE (1)
-
-    0x81, 0x02, //     INPUT (Data,Var,Abs)
-    0x95, 0x01, //     REPORT_COUNT (1)
-    0x75, 0x05, //     REPORT_SIZE (5)
-    0x81, 0x01, //     INPUT (Cnst,Var,Abs)
-
-    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
-    0x09, 0x30, //     USAGE (X)
-    0x09, 0x31, //     USAGE (Y)
-    0x09, 0x38,
-
-    0x15, 0x81, //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7F, //     LOGICAL_MAXIMUM (127)
-    0x75, 0x08, //     REPORT_SIZE (8)
-    0x95, 0x03, //     REPORT_COUNT (2)
-
-    0x81, 0x06, //     INPUT (Data,Var,Rel)
-    0xC0, 0x09,
-    0x3c, 0x05,
-    0xff, 0x09,
-
-    0x01, 0x15,
-    0x00, 0x25,
-    0x01, 0x75,
-    0x01, 0x95,
-
-    0x02, 0xb1,
-    0x22, 0x75,
-    0x06, 0x95,
-    0x01, 0xb1,
-
-    0x01, 0xc0 //   END_COLLECTION
+    0x09, 0x01, // USAGE (Pointer)
+    0xA1, 0x00, // COLLECTION (Physical)
+    0x05, 0x09, // USAGE_PAGE (Button)
+    0x19, 0x01, // USAGE_MINIMUM (Button 1)
+    0x29, 0x03, // USAGE_MAXIMUM (Button 3)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x95, 0x03, // REPORT_COUNT (3)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x81, 0x02, // INPUT (Data,Var,Abs)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0x75, 0x05, // REPORT_SIZE (5)
+    0x81, 0x01, // INPUT (Cnst,Var,Abs)
+    0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+    0x09, 0x30, // USAGE (X)
+    0x09, 0x31, // USAGE (Y)
+    0x09, 0x38, // Usage (Wheel)
+    0x15, 0x81, // LOGICAL_MINIMUM (-127)
+    0x25, 0x7F, // LOGICAL_MAXIMUM (127)
+    0x75, 0x08, // REPORT_SIZE (8)
+    0x95, 0x03, // REPORT_COUNT (2)
+    0x81, 0x06, // INPUT (Data,Var,Rel)
+    0xC0,       // END_COLLECTION
+    0x09, 0x3c, // USAGE (Motion Wakeup)
+    0x05, 0xff, // USAGE_PAGE (Vendor Defined 0xFF)
+    0x09, 0x01, // USAGE (Vendor Usage 1)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x95, 0x02, // REPORT_COUNT (2)
+    0xb1, 0x22, // FEATURE (Data,Var,Abs,NPrf)
+    0x75, 0x06, // REPORT_SIZE (6)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0xb1, 0x01, // FEATURE (Cnst,Ary,Abs)
+    0xc0        // END_COLLECTION
 };
 
 /*!< mouse report struct */
@@ -256,7 +248,7 @@ 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) {
+    if (usb_device_is_configured(busid) == false) {
         return;
     }
 

+ 36 - 44
components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c

@@ -70,7 +70,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
@@ -88,49 +88,41 @@ static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
     0x09, 0x02, // USAGE (Mouse)
     0xA1, 0x01, // COLLECTION (Application)
-    0x09, 0x01, //   USAGE (Pointer)
-
-    0xA1, 0x00, //   COLLECTION (Physical)
-    0x05, 0x09, //     USAGE_PAGE (Button)
-    0x19, 0x01, //     USAGE_MINIMUM (Button 1)
-    0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
-
-    0x15, 0x00, //     LOGICAL_MINIMUM (0)
-    0x25, 0x01, //     LOGICAL_MAXIMUM (1)
-    0x95, 0x03, //     REPORT_COUNT (3)
-    0x75, 0x01, //     REPORT_SIZE (1)
-
-    0x81, 0x02, //     INPUT (Data,Var,Abs)
-    0x95, 0x01, //     REPORT_COUNT (1)
-    0x75, 0x05, //     REPORT_SIZE (5)
-    0x81, 0x01, //     INPUT (Cnst,Var,Abs)
-
-    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
-    0x09, 0x30, //     USAGE (X)
-    0x09, 0x31, //     USAGE (Y)
-    0x09, 0x38,
-
-    0x15, 0x81, //     LOGICAL_MINIMUM (-127)
-    0x25, 0x7F, //     LOGICAL_MAXIMUM (127)
-    0x75, 0x08, //     REPORT_SIZE (8)
-    0x95, 0x03, //     REPORT_COUNT (2)
-
-    0x81, 0x06, //     INPUT (Data,Var,Rel)
-    0xC0, 0x09,
-    0x3c, 0x05,
-    0xff, 0x09,
-
-    0x01, 0x15,
-    0x00, 0x25,
-    0x01, 0x75,
-    0x01, 0x95,
-
-    0x02, 0xb1,
-    0x22, 0x75,
-    0x06, 0x95,
-    0x01, 0xb1,
-
-    0x01, 0xc0 //   END_COLLECTION
+    0x09, 0x01, // USAGE (Pointer)
+    0xA1, 0x00, // COLLECTION (Physical)
+    0x05, 0x09, // USAGE_PAGE (Button)
+    0x19, 0x01, // USAGE_MINIMUM (Button 1)
+    0x29, 0x03, // USAGE_MAXIMUM (Button 3)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x95, 0x03, // REPORT_COUNT (3)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x81, 0x02, // INPUT (Data,Var,Abs)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0x75, 0x05, // REPORT_SIZE (5)
+    0x81, 0x01, // INPUT (Cnst,Var,Abs)
+    0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+    0x09, 0x30, // USAGE (X)
+    0x09, 0x31, // USAGE (Y)
+    0x09, 0x38, // Usage (Wheel)
+    0x15, 0x81, // LOGICAL_MINIMUM (-127)
+    0x25, 0x7F, // LOGICAL_MAXIMUM (127)
+    0x75, 0x08, // REPORT_SIZE (8)
+    0x95, 0x03, // REPORT_COUNT (2)
+    0x81, 0x06, // INPUT (Data,Var,Rel)
+    0xC0,       // END_COLLECTION
+    0x09, 0x3c, // USAGE (Motion Wakeup)
+    0x05, 0xff, // USAGE_PAGE (Vendor Defined 0xFF)
+    0x09, 0x01, // USAGE (Vendor Usage 1)
+    0x15, 0x00, // LOGICAL_MINIMUM (0)
+    0x25, 0x01, // LOGICAL_MAXIMUM (1)
+    0x75, 0x01, // REPORT_SIZE (1)
+    0x95, 0x02, // REPORT_COUNT (2)
+    0xb1, 0x22, // FEATURE (Data,Var,Abs,NPrf)
+    0x75, 0x06, // REPORT_SIZE (6)
+    0x95, 0x01, // REPORT_COUNT (1)
+    0xb1, 0x01, // FEATURE (Cnst,Ary,Abs)
+    0xc0        // END_COLLECTION
 };
 
 /*!< mouse report struct */

+ 1 - 1
components/drivers/usb/cherryusb/demo/midi_template.c

@@ -87,7 +87,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 7 - 46
components/drivers/usb/cherryusb/demo/msc_ram_template.c

@@ -71,7 +71,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];
@@ -109,7 +109,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
     }
 }
 
-#if !defined(RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV) && !defined(PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV)
+#if !defined(RT_CHERRYUSB_DEVICE_MSC_BLKDEV) && !defined(PKG_CHERRYUSB_DEVICE_MSC_BLKDEV)
 #define BLOCK_SIZE  512
 #define BLOCK_COUNT 10
 
@@ -138,58 +138,19 @@ int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *
         memcpy(mass_block[sector].BlockSpace, buffer, length);
     return 0;
 }
-#else
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#ifndef CONFIG_USBDEV_MSC_THREAD
-#error "Please enable CONFIG_USBDEV_MSC_THREAD, move msc read & write from isr to thread"
-#endif
-
-#ifndef CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
-#define CONFIG_USBDEV_MSC_BLOCK_DEV_NAME "sd0"
-#endif
-
-static rt_device_t blk_dev = RT_NULL;
-struct rt_device_blk_geometry geometry = { 0 };
-
-void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
-{
-    rt_device_control(blk_dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
-
-    *block_num = geometry.sector_count;
-    *block_size = geometry.bytes_per_sector;
-}
-
-int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
-{
-    rt_device_read(blk_dev, sector, buffer, length / geometry.bytes_per_sector);
-    return 0;
-}
-
-int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
-{
-    rt_device_write(blk_dev, sector, buffer, length / geometry.bytes_per_sector);
-    return 0;
-}
 #endif
 
 static struct usbd_interface intf0;
 
 void msc_ram_init(uint8_t busid, uintptr_t reg_base)
 {
-#if defined(RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV) || defined(PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV)
-    rt_err_t res;
-
-    blk_dev = rt_device_find(CONFIG_USBDEV_MSC_BLOCK_DEV_NAME);
-    RT_ASSERT(blk_dev);
-
-    res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
-    RT_ASSERT(res == RT_EOK);
-#endif
     usbd_desc_register(busid, &msc_ram_descriptor);
-
+#if defined(RT_CHERRYUSB_DEVICE_MSC_BLKDEV) || defined(PKG_CHERRYUSB_DEVICE_MSC_BLKDEV)
+    extern void usbd_msc_blkdev_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep);
+    usbd_msc_blkdev_init(busid, MSC_IN_EP, MSC_OUT_EP);
+#else
     usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
+#endif
 
     usbd_initialize(busid, reg_base, usbd_event_handler);
 }

+ 1 - 1
components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c

@@ -172,7 +172,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/video_static_h264_template.c

@@ -105,7 +105,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c

@@ -105,7 +105,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c

@@ -108,7 +108,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/webusb_hid_template.c

@@ -114,7 +114,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

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

@@ -191,7 +191,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 5) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

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

@@ -106,7 +106,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 3) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

+ 1 - 1
components/drivers/usb/cherryusb/demo/winusb2.0_template.c

@@ -120,7 +120,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
 
 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
 {
-    if (index > 5) {
+    if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
         return NULL;
     }
     return string_descriptors[index];

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

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

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

@@ -62,6 +62,11 @@ usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
     return sem;
 }
 
+usb_osal_sem_t usb_osal_sem_create_counting(uint32_t max_count)
+{
+    return usb_osal_sem_create(0);
+}
+
 void usb_osal_sem_delete(usb_osal_sem_t sem)
 {
     rt_sem_delete((rt_sem_t)sem);

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

@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2022 ~ 2025, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "rtthread.h"
-#include "usb_config.h"
-
-#if defined(PKG_CHERRYUSB_HOST) || defined(RT_CHERRYUSB_HOST)
-
-#ifndef RT_USING_TIMER_SOFT
-#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
-#endif
-
-#if RT_TIMER_THREAD_STACK_SIZE < 1024
-#error "RT_TIMER_THREAD_STACK_SIZE must be >= 1024"
-#endif
-#endif
-
-#if defined(ARCH_ARM_CORTEX_M7) ||                                                                  \
-    defined(ARCH_ARM_CORTEX_A) ||                                                                   \
-    defined(ARCH_RISCV64) ||                                                                        \
-    defined(SOC_HPM6200) || defined(SOC_HPM6300) || defined(SOC_HPM6700) || defined(SOC_HPM6800) || \
-    defined(SOC_HPM6E00) || defined(SOC_HPM6P00) ||                                                 \
-    defined(BSP_USING_BL61X) || defined(BSP_USING_BL808)
-#ifndef RT_USING_CACHE
-#error RT_USING_CACHE must be enabled in this chip
-#endif
-#endif
-
-#ifdef RT_USING_CACHE
-#ifndef CONFIG_USB_DCACHE_ENABLE
-#error CONFIG_USB_DCACHE_ENABLE must be enabled if you do not config nocache ram
-#endif
-#endif

+ 0 - 53
components/drivers/usb/cherryusb/platform/rtthread/usb_msh.c

@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "rtthread.h"
-
-#if defined(PKG_CHERRYUSB_HOST) || defined(RT_CHERRYUSB_HOST)
-
-#include "usbh_core.h"
-
-int usbh_init(int argc, char **argv)
-{
-    uint8_t busid;
-    uint32_t reg_base;
-
-    if (argc < 3) {
-        USB_LOG_ERR("please input correct command: usbh_init <busid> <reg_base>\r\n");
-        return -1;
-    }
-
-    busid = atoi(argv[1]);
-    reg_base = strtoll(argv[2], NULL, 16);
-    usbh_initialize(busid, reg_base, NULL);
-
-    return 0;
-}
-
-int usbh_deinit(int argc, char **argv)
-{
-    uint8_t busid;
-
-    if (argc < 2) {
-        USB_LOG_ERR("please input correct command: usbh_deinit <busid>\r\n");
-        return -1;
-    }
-
-    busid = atoi(argv[1]);
-    usbh_deinitialize(busid);
-
-    return 0;
-}
-
-MSH_CMD_EXPORT(usbh_init, init usb host);
-MSH_CMD_EXPORT(usbh_deinit, deinit usb host);
-MSH_CMD_EXPORT(lsusb, ls usb devices);
-
-#ifdef CONFIG_USBHOST_SERIAL
-#include "usbh_serial.h"
-MSH_CMD_EXPORT(usbh_serial, usbh_serial test);
-#endif
-
-#endif

+ 0 - 156
components/drivers/usb/cherryusb/platform/rtthread/usbd_adb_shell.c

@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2025, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "usbd_core.h"
-#include "usbd_adb.h"
-
-#ifndef CONFIG_USBDEV_SHELL_RX_BUFSIZE
-#define CONFIG_USBDEV_SHELL_RX_BUFSIZE (2048)
-#endif
-
-struct usbd_adb_shell {
-    struct rt_device parent;
-    usb_osal_sem_t tx_done;
-    struct rt_ringbuffer rx_rb;
-    rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SHELL_RX_BUFSIZE];
-} g_usbd_adb_shell;
-
-void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
-{
-    rt_ringbuffer_put(&g_usbd_adb_shell.rx_rb, data, len);
-
-    if (g_usbd_adb_shell.parent.rx_indicate) {
-        g_usbd_adb_shell.parent.rx_indicate(&g_usbd_adb_shell.parent, len);
-    }
-}
-
-void usbd_adb_notify_write_done(void)
-{
-    if (g_usbd_adb_shell.tx_done) {
-        usb_osal_sem_give(g_usbd_adb_shell.tx_done);
-    }
-}
-
-static rt_err_t usbd_adb_shell_open(struct rt_device *dev, rt_uint16_t oflag)
-{
-    while (!usb_device_is_configured(0)) {
-        rt_thread_mdelay(10);
-    }
-    return RT_EOK;
-}
-
-static rt_err_t usbd_adb_shell_close(struct rt_device *dev)
-{
-    if (g_usbd_adb_shell.tx_done) {
-        usb_osal_sem_give(g_usbd_adb_shell.tx_done);
-    }
-
-    return RT_EOK;
-}
-
-static rt_ssize_t usbd_adb_shell_read(struct rt_device *dev,
-                                      rt_off_t pos,
-                                      void *buffer,
-                                      rt_size_t size)
-{
-    return rt_ringbuffer_get(&g_usbd_adb_shell.rx_rb, (rt_uint8_t *)buffer, size);
-}
-
-static rt_ssize_t usbd_adb_shell_write(struct rt_device *dev,
-                                       rt_off_t pos,
-                                       const void *buffer,
-                                       rt_size_t size)
-{
-    int ret = 0;
-
-    RT_ASSERT(dev != RT_NULL);
-
-    if (!usb_device_is_configured(0)) {
-        return size;
-    }
-
-    if (usbd_adb_can_write() && size) {
-        usb_osal_sem_reset(g_usbd_adb_shell.tx_done);
-        usbd_abd_write(ADB_SHELL_LOALID, buffer, size);
-        usb_osal_sem_take(g_usbd_adb_shell.tx_done, 0xffffffff);
-    }
-
-    return size;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops usbd_adb_shell_ops = {
-    NULL,
-    usbd_adb_shell_open,
-    usbd_adb_shell_close,
-    usbd_adb_shell_read,
-    usbd_adb_shell_write,
-    NULL
-};
-#endif
-
-void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep)
-{
-    rt_err_t ret;
-    struct rt_device *device;
-
-    device = &(g_usbd_adb_shell.parent);
-
-    device->type = RT_Device_Class_Char;
-    device->rx_indicate = RT_NULL;
-    device->tx_complete = RT_NULL;
-
-#ifdef RT_USING_DEVICE_OPS
-    device->ops = &usbd_adb_shell_ops;
-#else
-    device->init = NULL;
-    device->open = usbd_adb_shell_open;
-    device->close = usbd_adb_shell_close;
-    device->read = usbd_adb_shell_read;
-    device->write = usbd_adb_shell_write;
-    device->control = NULL;
-#endif
-    device->user_data = NULL;
-
-    /* register a character device */
-    ret = rt_device_register(device, "adb-sh", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
-
-#ifdef RT_USING_POSIX_DEVIO
-    /* set fops */
-    device->fops = NULL;
-#endif
-
-    g_usbd_adb_shell.tx_done = usb_osal_sem_create(0);
-    rt_ringbuffer_init(&g_usbd_adb_shell.rx_rb, g_usbd_adb_shell.rx_rb_buffer, sizeof(g_usbd_adb_shell.rx_rb_buffer));
-}
-
-static int adb_enter(int argc, char **argv)
-{
-    (void)argc;
-    (void)argv;
-
-    finsh_set_device("adb-sh");
-    rt_console_set_device("adb-sh");
-
-    return 0;
-}
-MSH_CMD_EXPORT(adb_enter, adb_enter);
-
-static int adb_exit(int argc, char **argv)
-{
-    (void)argc;
-    (void)argv;
-
-    usbd_adb_close(ADB_SHELL_LOALID);
-
-    finsh_set_device(RT_CONSOLE_DEVICE_NAME);
-    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
-
-    return 0;
-}
-MSH_CMD_EXPORT(adb_exit, adb_exit);

+ 0 - 275
components/drivers/usb/cherryusb/platform/rtthread/usbd_serial.c

@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2025, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "usbd_core.h"
-#include "usbd_cdc_acm.h"
-
-#define DEV_FORMAT_CDC_ACM "usb-acm%d"
-
-#ifndef CONFIG_USBDEV_MAX_CDC_ACM_CLASS
-#define CONFIG_USBDEV_MAX_CDC_ACM_CLASS (4)
-#endif
-
-#ifndef CONFIG_USBDEV_SERIAL_RX_BUFSIZE
-#define CONFIG_USBDEV_SERIAL_RX_BUFSIZE (2048)
-#endif
-
-struct usbd_serial {
-    struct rt_device parent;
-    uint8_t busid;
-    uint8_t in_ep;
-    uint8_t out_ep;
-    struct usbd_interface intf_ctrl;
-    struct usbd_interface intf_data;
-    usb_osal_sem_t tx_done;
-    uint8_t minor;
-    char name[32];
-    struct rt_ringbuffer rx_rb;
-    rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SERIAL_RX_BUFSIZE];
-};
-
-static uint32_t g_devinuse = 0;
-
-static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbd_serial_cdc_acm_rx_buf[CONFIG_USBDEV_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(512, CONFIG_USB_ALIGN_SIZE)];
-
-static struct usbd_serial g_usbd_serial_cdc_acm[CONFIG_USBDEV_MAX_CDC_ACM_CLASS];
-
-static struct usbd_serial *usbd_serial_alloc(void)
-{
-    uint8_t devno;
-    struct usbd_serial *serial;
-
-    for (devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
-        if ((g_devinuse & (1U << devno)) == 0) {
-            g_devinuse |= (1U << devno);
-
-            serial = &g_usbd_serial_cdc_acm[devno];
-            memset(serial, 0, sizeof(struct usbd_serial));
-            serial->minor = devno;
-            snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->minor);
-            return serial;
-        }
-    }
-    return NULL;
-}
-
-static void usbd_serial_free(struct usbd_serial *serial)
-{
-    uint8_t devno = serial->minor;
-
-    if (devno < 32) {
-        g_devinuse &= ~(1U << devno);
-    }
-    memset(serial, 0, sizeof(struct usbd_serial));
-}
-
-static rt_err_t usbd_serial_open(struct rt_device *dev, rt_uint16_t oflag)
-{
-    struct usbd_serial *serial;
-
-    RT_ASSERT(dev != RT_NULL);
-
-    serial = (struct usbd_serial *)dev;
-
-    while(!usb_device_is_configured(serial->busid)) {
-        rt_thread_mdelay(10);
-    }
-
-    usbd_ep_start_read(serial->busid, serial->out_ep,
-                       g_usbd_serial_cdc_acm_rx_buf[serial->minor],
-                       usbd_get_ep_mps(serial->busid, serial->out_ep));
-    return RT_EOK;
-}
-
-static rt_ssize_t usbd_serial_read(struct rt_device *dev,
-                                   rt_off_t pos,
-                                   void *buffer,
-                                   rt_size_t size)
-{
-    struct usbd_serial *serial;
-
-    RT_ASSERT(dev != RT_NULL);
-
-    serial = (struct usbd_serial *)dev;
-
-    if (!usb_device_is_configured(serial->busid)) {
-        return -RT_EPERM;
-    }
-
-    return rt_ringbuffer_get(&serial->rx_rb, (rt_uint8_t *)buffer, size);
-}
-
-static rt_ssize_t usbd_serial_write(struct rt_device *dev,
-                                    rt_off_t pos,
-                                    const void *buffer,
-                                    rt_size_t size)
-{
-    struct usbd_serial *serial;
-    int ret = 0;
-    rt_uint8_t *align_buf;
-
-    RT_ASSERT(dev != RT_NULL);
-
-    serial = (struct usbd_serial *)dev;
-
-    if (!usb_device_is_configured(serial->busid)) {
-        return -RT_EPERM;
-    }
-    align_buf = (rt_uint8_t *)buffer;
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        align_buf = rt_malloc_align(USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE), CONFIG_USB_ALIGN_SIZE);
-        if (!align_buf) {
-            USB_LOG_ERR("serial get align buf failed\n");
-            return 0;
-        }
-
-        usb_memcpy(align_buf, buffer, size);
-    }
-
-    usb_osal_sem_reset(serial->tx_done);
-    usbd_ep_start_write(serial->busid, serial->in_ep, align_buf, size);
-    ret = usb_osal_sem_take(serial->tx_done, 3000);
-    if (ret < 0) {
-        USB_LOG_ERR("serial write timeout\n");
-        ret = -RT_ETIMEOUT;
-    } else {
-        ret = size;
-    }
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        rt_free_align(align_buf);
-    }
-
-    return ret;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops usbd_serial_ops = {
-    NULL,
-    usbd_serial_open,
-    NULL,
-    usbd_serial_read,
-    usbd_serial_write,
-    NULL
-};
-#endif
-
-rt_err_t usbd_serial_register(struct usbd_serial *serial,
-                              void *data)
-{
-    rt_err_t ret;
-    struct rt_device *device;
-    RT_ASSERT(serial != RT_NULL);
-
-    device = &(serial->parent);
-
-    device->type = RT_Device_Class_Char;
-    device->rx_indicate = RT_NULL;
-    device->tx_complete = RT_NULL;
-
-#ifdef RT_USING_DEVICE_OPS
-    device->ops = &usbd_serial_ops;
-#else
-    device->init = NULL;
-    device->open = usbd_serial_open;
-    device->close = NULL;
-    device->read = usbd_serial_read;
-    device->write = usbd_serial_write;
-    device->control = NULL;
-#endif
-    device->user_data = data;
-
-    /* register a character device */
-    ret = rt_device_register(device, serial->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_REMOVABLE);
-
-#ifdef RT_USING_POSIX_DEVIO
-    /* set fops */
-    device->fops = NULL;
-#endif
-    rt_ringbuffer_init(&serial->rx_rb, serial->rx_rb_buffer, sizeof(serial->rx_rb_buffer));
-
-    return ret;
-}
-
-void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
-{
-    struct usbd_serial *serial;
-
-    for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
-        serial = &g_usbd_serial_cdc_acm[devno];
-        if (serial->out_ep == ep) {
-            rt_ringbuffer_put(&serial->rx_rb, g_usbd_serial_cdc_acm_rx_buf[serial->minor], nbytes);
-            usbd_ep_start_read(serial->busid, serial->out_ep,
-                g_usbd_serial_cdc_acm_rx_buf[serial->minor],
-                usbd_get_ep_mps(serial->busid, serial->out_ep));
-
-            if (serial->parent.rx_indicate) {
-                serial->parent.rx_indicate(&serial->parent, nbytes);
-            }
-            break;
-        }
-    }
-}
-
-void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
-{
-    struct usbd_serial *serial;
-
-    if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
-        /* send zlp */
-        usbd_ep_start_write(busid, ep, NULL, 0);
-    } else {
-        for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
-            serial = &g_usbd_serial_cdc_acm[devno];
-            if ((serial->in_ep == ep) && serial->tx_done) {
-                usb_osal_sem_give(serial->tx_done);
-                break;
-            }
-        }
-    }
-}
-
-void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep)
-{
-    struct usbd_serial *serial;
-
-    struct usbd_endpoint cdc_out_ep = {
-        .ep_addr = out_ep,
-        .ep_cb = usbd_cdc_acm_bulk_out
-    };
-
-    struct usbd_endpoint cdc_in_ep = {
-        .ep_addr = in_ep,
-        .ep_cb = usbd_cdc_acm_bulk_in
-    };
-
-    serial = usbd_serial_alloc();
-    if (serial == NULL) {
-        USB_LOG_ERR("No more serial device available\n");
-        return;
-    }
-
-    serial->busid = busid;
-    serial->in_ep = in_ep;
-    serial->out_ep = out_ep;
-    serial->tx_done = usb_osal_sem_create(0);
-
-    usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_ctrl));
-    usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_data));
-    usbd_add_endpoint(busid, &cdc_out_ep);
-    usbd_add_endpoint(busid, &cdc_in_ep);
-
-    if (usbd_serial_register(serial, NULL) != RT_EOK) {
-        USB_LOG_ERR("Failed to register serial device\n");
-        usbd_serial_free(serial);
-        return;
-    }
-
-    USB_LOG_INFO("USB CDC ACM Serial Device %s initialized\n", serial->name);
-}

+ 0 - 191
components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c

@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "usbh_core.h"
-#include "usbh_msc.h"
-
-#include "rtthread.h"
-#include <dfs_fs.h>
-
-#define DEV_FORMAT "/dev/sd%c"
-
-#ifndef RT_USING_DFS_ELMFAT
-#error "RT_USING_DFS_ELMFAT must be enabled to use USB mass storage device"
-#endif
-
-#ifndef CONFIG_USB_DFS_MOUNT_POINT
-#define CONFIG_USB_DFS_MOUNT_POINT "/"
-#endif
-
-static rt_err_t rt_udisk_init(rt_device_t dev)
-{
-    struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
-
-    if (usbh_msc_scsi_init(msc_class) < 0) {
-        return -RT_ERROR;
-    }
-
-    return RT_EOK;
-}
-
-static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
-                                rt_size_t size)
-{
-    struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
-    int ret;
-    rt_uint8_t *align_buf;
-
-    align_buf = (rt_uint8_t *)buffer;
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
-        if (!align_buf) {
-            rt_kprintf("msc get align buf failed\n");
-            return 0;
-        }
-    } else {
-    }
-
-    ret = usbh_msc_scsi_read10(msc_class, pos, (uint8_t *)align_buf, size);
-    if (ret < 0) {
-        rt_kprintf("usb mass_storage read failed\n");
-        return 0;
-    }
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        usb_memcpy(buffer, align_buf, size * msc_class->blocksize);
-        rt_free_align(align_buf);
-    }
-
-    return size;
-}
-
-static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
-                                 rt_size_t size)
-{
-    struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
-    int ret;
-    rt_uint8_t *align_buf;
-
-    align_buf = (rt_uint8_t *)buffer;
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
-        if (!align_buf) {
-            rt_kprintf("msc get align buf failed\n");
-            return 0;
-        }
-
-        usb_memcpy(align_buf, buffer, size * msc_class->blocksize);
-    }
-
-    ret = usbh_msc_scsi_write10(msc_class, pos, (uint8_t *)align_buf, size);
-    if (ret < 0) {
-        rt_kprintf("usb mass_storage write failed\n");
-        return 0;
-    }
-
-    if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
-        rt_free_align(align_buf);
-    }
-
-    return size;
-}
-
-static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
-{
-    /* check parameter */
-    RT_ASSERT(dev != RT_NULL);
-    struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
-
-    if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) {
-        struct rt_device_blk_geometry *geometry;
-
-        geometry = (struct rt_device_blk_geometry *)args;
-        if (geometry == RT_NULL)
-            return -RT_ERROR;
-
-        geometry->bytes_per_sector = msc_class->blocksize;
-        geometry->block_size = msc_class->blocksize;
-        geometry->sector_count = msc_class->blocknum;
-    }
-
-    return RT_EOK;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops udisk_device_ops = {
-    rt_udisk_init,
-    RT_NULL,
-    RT_NULL,
-    rt_udisk_read,
-    rt_udisk_write,
-    rt_udisk_control
-};
-#endif
-
-static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
-{
-    struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
-    char name[CONFIG_USBHOST_DEV_NAMELEN];
-    char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
-    int ret;
-
-    snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
-    snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
-
-    ret = dfs_mount(name, mount_point, "elm", 0, 0);
-    if (ret == 0) {
-        rt_kprintf("udisk: %s mount successfully\n", name);
-    } else {
-        rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
-    }
-
-    usb_osal_thread_delete(NULL);
-}
-
-void usbh_msc_run(struct usbh_msc *msc_class)
-{
-    struct rt_device *dev;
-    char name[CONFIG_USBHOST_DEV_NAMELEN];
-
-    dev = rt_malloc(sizeof(struct rt_device));
-    memset(dev, 0, sizeof(struct rt_device));
-
-    snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
-
-    dev->type = RT_Device_Class_Block;
-#ifdef RT_USING_DEVICE_OPS
-    dev->ops = &udisk_device_ops;
-#else
-    dev->init = rt_udisk_init;
-    dev->read = rt_udisk_read;
-    dev->write = rt_udisk_write;
-    dev->control = rt_udisk_control;
-#endif
-    dev->user_data = msc_class;
-
-    rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
-
-    usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
-}
-
-void usbh_msc_stop(struct usbh_msc *msc_class)
-{
-    struct rt_device *dev;
-
-    char name[CONFIG_USBHOST_DEV_NAMELEN];
-    char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
-
-    snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
-    snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
-
-    dfs_unmount(mount_point);
-    dev = rt_device_find(name);
-    if (dev) {
-        rt_device_unregister(dev);
-        rt_free(dev);
-    }
-}

+ 0 - 469
components/drivers/usb/cherryusb/platform/rtthread/usbh_lwip.c

@@ -1,469 +0,0 @@
-/*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "netif/etharp.h"
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-#include "lwip/tcpip.h"
-#if LWIP_DHCP
-#include "lwip/dhcp.h"
-#include "lwip/prot/dhcp.h"
-#endif
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <netif/ethernetif.h>
-
-#include "usbh_core.h"
-
-#include "lwip/opt.h"
-
-#ifndef RT_USING_LWIP212
-#error must enable RT_USING_LWIP212
-#endif
-
-#ifndef LWIP_NO_RX_THREAD
-#warning suggest you to enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
-#endif
-
-#ifndef LWIP_NO_TX_THREAD
-#warning suggest you to enable LWIP_NO_TX_THREAD, we do not use rtthread eth tx thread
-#endif
-
-#if LWIP_TCPIP_CORE_LOCKING_INPUT != 1
-#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1 for better performance, usb handles eth input with own thread
-#endif
-
-#if LWIP_TCPIP_CORE_LOCKING != 1
-#error must set LWIP_TCPIP_CORE_LOCKING to 1
-#endif
-
-#if PBUF_POOL_BUFSIZE < 1600
-#error PBUF_POOL_BUFSIZE must be larger than 1600
-#endif
-
-#if RT_LWIP_TCPTHREAD_STACKSIZE < 2048
-#error RT_LWIP_TCPTHREAD_STACKSIZE must be >= 2048
-#endif
-
-#if !defined(CONFIG_USBHOST_PLATFORM_CDC_ECM) &&   \
-    !defined(CONFIG_USBHOST_PLATFORM_CDC_RNDIS) && \
-    !defined(CONFIG_USBHOST_PLATFORM_CDC_NCM) &&   \
-    !defined(CONFIG_USBHOST_PLATFORM_ASIX) &&      \
-    !defined(CONFIG_USBHOST_PLATFORM_RTL8152)
-#error "Please enable at least one USB Ethernet platform in usb_config.h or Kconfig"
-#endif
-
-// #define CONFIG_USBHOST_PLATFORM_CDC_ECM
-// #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
-// #define CONFIG_USBHOST_PLATFORM_CDC_NCM
-// #define CONFIG_USBHOST_PLATFORM_ASIX
-// #define CONFIG_USBHOST_PLATFORM_RTL8152
-
-void usbh_lwip_eth_output_common(struct pbuf *p, uint8_t *buf)
-{
-    struct pbuf *q;
-    uint8_t *buffer;
-
-    buffer = buf;
-    for (q = p; q != NULL; q = q->next) {
-        usb_memcpy(buffer, q->payload, q->len);
-        buffer += q->len;
-    }
-}
-
-void usbh_lwip_eth_input_common(struct netif *netif, uint8_t *buf, uint32_t len)
-{
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_REF;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    err_t err;
-    struct pbuf *p;
-
-    p = pbuf_alloc(PBUF_RAW, len, type);
-    if (p != NULL) {
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-        p->payload = buf;
-#else
-        usb_memcpy(p->payload, buf, len);
-#endif
-        err = netif->input(p, netif);
-        if (err != ERR_OK) {
-            pbuf_free(p);
-        }
-    } else {
-        USB_LOG_ERR("No memory to alloc pbuf\r\n");
-    }
-}
-
-#ifdef CONFIG_USBHOST_PLATFORM_CDC_ECM
-#include "usbh_cdc_ecm.h"
-
-static struct eth_device g_cdc_ecm_dev;
-
-static rt_err_t rt_usbh_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
-{
-    struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)dev->user_data;
-
-    switch (cmd) {
-        case NIOCTL_GADDR:
-
-            /* get mac address */
-            if (args)
-                rt_memcpy(args, cdc_ecm_class->mac, 6);
-            else
-                return -RT_ERROR;
-
-            break;
-
-        default:
-            break;
-    }
-
-    return RT_EOK;
-}
-
-static rt_err_t rt_usbh_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
-{
-    int ret;
-    (void)dev;
-
-    usbh_lwip_eth_output_common(p, usbh_cdc_ecm_get_eth_txbuf());
-    ret = usbh_cdc_ecm_eth_output(p->tot_len);
-    if (ret < 0) {
-        return -RT_ERROR;
-    } else {
-        return RT_EOK;
-    }
-}
-
-void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
-{
-    usbh_lwip_eth_input_common(g_cdc_ecm_dev.netif, buf, buflen);
-}
-
-void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
-{
-    memset(&g_cdc_ecm_dev, 0, sizeof(struct eth_device));
-
-    g_cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
-    g_cdc_ecm_dev.eth_rx = NULL;
-    g_cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
-    g_cdc_ecm_dev.parent.user_data = cdc_ecm_class;
-
-    eth_device_init(&g_cdc_ecm_dev, "u0");
-    eth_device_linkchange(&g_cdc_ecm_dev, RT_TRUE);
-
-    usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
-}
-
-void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
-{
-    (void)cdc_ecm_class;
-
-    eth_device_deinit(&g_cdc_ecm_dev);
-}
-#endif
-
-#ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
-#include "usbh_rndis.h"
-
-static struct eth_device g_rndis_dev;
-
-static rt_timer_t keep_timer = RT_NULL;
-
-static void rndis_dev_keepalive_timeout(void *parameter)
-{
-    struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
-    usbh_rndis_keepalive(rndis_class);
-}
-
-static void timer_init(struct usbh_rndis *rndis_class)
-{
-    keep_timer = rt_timer_create("keep",
-                                 rndis_dev_keepalive_timeout,
-                                 rndis_class,
-                                 5000,
-                                 RT_TIMER_FLAG_PERIODIC |
-                                     RT_TIMER_FLAG_SOFT_TIMER);
-
-    rt_timer_start(keep_timer);
-}
-
-static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
-{
-    struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
-
-    switch (cmd) {
-        case NIOCTL_GADDR:
-
-            /* get mac address */
-            if (args)
-                rt_memcpy(args, rndis_class->mac, 6);
-            else
-                return -RT_ERROR;
-
-            break;
-
-        default:
-            break;
-    }
-
-    return RT_EOK;
-}
-
-static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
-{
-    int ret;
-    (void)dev;
-
-    usbh_lwip_eth_output_common(p, usbh_rndis_get_eth_txbuf());
-    ret = usbh_rndis_eth_output(p->tot_len);
-    if (ret < 0) {
-        return -RT_ERROR;
-    } else {
-        return RT_EOK;
-    }
-}
-
-void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
-{
-    usbh_lwip_eth_input_common(g_rndis_dev.netif, buf, buflen);
-}
-
-void usbh_rndis_run(struct usbh_rndis *rndis_class)
-{
-    memset(&g_rndis_dev, 0, sizeof(struct eth_device));
-
-    g_rndis_dev.parent.control = rt_usbh_rndis_control;
-    g_rndis_dev.eth_rx = NULL;
-    g_rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
-    g_rndis_dev.parent.user_data = rndis_class;
-
-    eth_device_init(&g_rndis_dev, "u2");
-    eth_device_linkchange(&g_rndis_dev, RT_TRUE);
-
-    usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
-    //timer_init(rndis_class);
-}
-
-void usbh_rndis_stop(struct usbh_rndis *rndis_class)
-{
-    (void)rndis_class;
-
-    eth_device_deinit(&g_rndis_dev);
-    // rt_timer_stop(keep_timer);
-    // rt_timer_delete(keep_timer);
-}
-#endif
-
-#ifdef CONFIG_USBHOST_PLATFORM_CDC_NCM
-#include "usbh_cdc_ncm.h"
-
-static struct eth_device g_cdc_ncm_dev;
-
-static rt_err_t rt_usbh_cdc_ncm_control(rt_device_t dev, int cmd, void *args)
-{
-    struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)dev->user_data;
-
-    switch (cmd) {
-        case NIOCTL_GADDR:
-
-            /* get mac address */
-            if (args)
-                rt_memcpy(args, cdc_ncm_class->mac, 6);
-            else
-                return -RT_ERROR;
-
-            break;
-
-        default:
-            break;
-    }
-
-    return RT_EOK;
-}
-
-static rt_err_t rt_usbh_cdc_ncm_eth_tx(rt_device_t dev, struct pbuf *p)
-{
-    int ret;
-    (void)dev;
-
-    usbh_lwip_eth_output_common(p, usbh_cdc_ncm_get_eth_txbuf());
-    ret = usbh_cdc_ncm_eth_output(p->tot_len);
-    if (ret < 0) {
-        return -RT_ERROR;
-    } else {
-        return RT_EOK;
-    }
-}
-
-void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen)
-{
-    usbh_lwip_eth_input_common(g_cdc_ncm_dev.netif, buf, buflen);
-}
-
-void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
-{
-    memset(&g_cdc_ncm_dev, 0, sizeof(struct eth_device));
-
-    g_cdc_ncm_dev.parent.control = rt_usbh_cdc_ncm_control;
-    g_cdc_ncm_dev.eth_rx = NULL;
-    g_cdc_ncm_dev.eth_tx = rt_usbh_cdc_ncm_eth_tx;
-    g_cdc_ncm_dev.parent.user_data = cdc_ncm_class;
-
-    eth_device_init(&g_cdc_ncm_dev, "u1");
-    eth_device_linkchange(&g_cdc_ncm_dev, RT_TRUE);
-
-    usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, NULL);
-}
-
-void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
-{
-    (void)cdc_ncm_class;
-
-    eth_device_deinit(&g_cdc_ncm_dev);
-}
-#endif
-
-#ifdef CONFIG_USBHOST_PLATFORM_ASIX
-#include "usbh_asix.h"
-
-static struct eth_device g_asix_dev;
-
-static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
-{
-    struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
-
-    switch (cmd) {
-        case NIOCTL_GADDR:
-
-            /* get mac address */
-            if (args)
-                rt_memcpy(args, asix_class->mac, 6);
-            else
-                return -RT_ERROR;
-
-            break;
-
-        default:
-            break;
-    }
-
-    return RT_EOK;
-}
-
-static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
-{
-    int ret;
-    (void)dev;
-
-    usbh_lwip_eth_output_common(p, usbh_asix_get_eth_txbuf());
-    ret = usbh_asix_eth_output(p->tot_len);
-    if (ret < 0) {
-        return -RT_ERROR;
-    } else {
-        return RT_EOK;
-    }
-}
-
-void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen)
-{
-    usbh_lwip_eth_input_common(g_asix_dev.netif, buf, buflen);
-}
-
-void usbh_asix_run(struct usbh_asix *asix_class)
-{
-    memset(&g_asix_dev, 0, sizeof(struct eth_device));
-
-    g_asix_dev.parent.control = rt_usbh_asix_control;
-    g_asix_dev.eth_rx = NULL;
-    g_asix_dev.eth_tx = rt_usbh_asix_eth_tx;
-    g_asix_dev.parent.user_data = asix_class;
-
-    eth_device_init(&g_asix_dev, "u3");
-    eth_device_linkchange(&g_asix_dev, RT_TRUE);
-
-    usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, NULL);
-}
-
-void usbh_asix_stop(struct usbh_asix *asix_class)
-{
-    (void)asix_class;
-
-    eth_device_deinit(&g_asix_dev);
-}
-#endif
-
-#ifdef CONFIG_USBHOST_PLATFORM_RTL8152
-#include "usbh_rtl8152.h"
-
-static struct eth_device g_rtl8152_dev;
-
-static rt_err_t rt_usbh_rtl8152_control(rt_device_t dev, int cmd, void *args)
-{
-    struct usbh_rtl8152 *rtl8152_class = (struct usbh_rtl8152 *)dev->user_data;
-
-    switch (cmd) {
-        case NIOCTL_GADDR:
-
-            /* get mac address */
-            if (args)
-                rt_memcpy(args, rtl8152_class->mac, 6);
-            else
-                return -RT_ERROR;
-
-            break;
-
-        default:
-            break;
-    }
-
-    return RT_EOK;
-}
-
-static rt_err_t rt_usbh_rtl8152_eth_tx(rt_device_t dev, struct pbuf *p)
-{
-    int ret;
-    (void)dev;
-
-    usbh_lwip_eth_output_common(p, usbh_rtl8152_get_eth_txbuf());
-    ret = usbh_rtl8152_eth_output(p->tot_len);
-    if (ret < 0) {
-        return -RT_ERROR;
-    } else {
-        return RT_EOK;
-    }
-}
-
-void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen)
-{
-    usbh_lwip_eth_input_common(g_rtl8152_dev.netif, buf, buflen);
-}
-
-void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
-{
-    memset(&g_rtl8152_dev, 0, sizeof(struct eth_device));
-
-    g_rtl8152_dev.parent.control = rt_usbh_rtl8152_control;
-    g_rtl8152_dev.eth_rx = NULL;
-    g_rtl8152_dev.eth_tx = rt_usbh_rtl8152_eth_tx;
-    g_rtl8152_dev.parent.user_data = rtl8152_class;
-
-    eth_device_init(&g_rtl8152_dev, "u4");
-    eth_device_linkchange(&g_rtl8152_dev, RT_TRUE);
-
-    usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, NULL);
-}
-
-void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
-{
-    (void)rtl8152_class;
-
-    eth_device_deinit(&g_rtl8152_dev);
-}
-#endif

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

@@ -722,7 +722,7 @@ void USBD_IRQHandler(uint8_t busid)
                         if (ep_addr & 0x80) {
                             usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
                         } else {
-                            usb_dcache_invalidate((uintptr_t)g_chipidea_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
+                            usb_dcache_invalidate((uintptr_t)g_chipidea_udc[busid].out_ep[ep_idx / 2].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
                             usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
                         }
                     }

+ 10 - 4
components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c

@@ -95,13 +95,14 @@ static inline int dwc2_core_init(uint8_t busid)
                 regval &= ~USB_OTG_GUSBCFG_PHYIF16;
                 regval &= ~USB_OTG_GUSBCFG_DDR_SEL;
 
-                if (g_dwc2_udc[busid].user_params.phy_utmi_width == 16) {
-                    regval |= USB_OTG_GUSBCFG_PHYIF16;
-                }
                 break;
             case DWC2_PHY_TYPE_PARAM_UTMI:
                 regval &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
                 regval &= ~USB_OTG_GUSBCFG_PHYIF16;
+
+                if (g_dwc2_udc[busid].user_params.phy_utmi_width == 16) {
+                    regval |= USB_OTG_GUSBCFG_PHYIF16;
+                }
                 break;
 
             default:
@@ -616,7 +617,7 @@ int usb_dc_init(uint8_t busid)
 
 int usb_dc_deinit(uint8_t busid)
 {
-    USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
+    USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
     USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
 
     /* Clear Pending interrupt */
@@ -630,6 +631,11 @@ int usb_dc_deinit(uint8_t busid)
     USB_OTG_DEV->DOEPMSK = 0U;
     USB_OTG_DEV->DAINTMSK = 0U;
 
+    /* Disable all interrupts. */
+    USB_OTG_GLB->GINTMSK = 0U;
+    /* Clear any pending interrupts */
+    USB_OTG_GLB->GINTSTS = 0xBFFFFFFFU;
+
     /* Flush the FIFO */
     dwc2_flush_txfifo(busid, 0x10U);
     dwc2_flush_rxfifo(busid);

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

@@ -84,7 +84,7 @@ void usb_dc_low_level_init(uint8_t busid)
     USBHS_SS->PHY_FUNC_CTL_1 |= (7 << USBHS_SS_PHY_FUNC_CTL_1_PLL_FSEL_Pos);
     USBHS_SS->PHY_FUNC_CTL_2 |= (USBHS_SS_PHY_FUNC_CTL_2_RES_TUNING_SEL_Msk | USBHS_SS_PHY_FUNC_CTL_2_EFUSE_SEL_Msk);
 
-    rt_thread_mdelay(200); /* Wait for PHY stable */
+    rt_thread_mdelay(200); // Wait for PHY stable
 
     cy_stc_sysint_t usb_int_cfg = {
         .intrSrc = usbhs_interrupt_usbhsctrl_IRQn,
@@ -123,7 +123,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus)
     USBHS_SS->PHY_FUNC_CTL_1 |= (7 << USBHS_SS_PHY_FUNC_CTL_1_PLL_FSEL_Pos);
     USBHS_SS->PHY_FUNC_CTL_2 |= (USBHS_SS_PHY_FUNC_CTL_2_RES_TUNING_SEL_Msk | USBHS_SS_PHY_FUNC_CTL_2_EFUSE_SEL_Msk);
 
-    rt_thread_mdelay(200); /* Wait for PHY stable */
+    rt_thread_mdelay(200); // Wait for PHY stable
 
     cy_stc_sysint_t usb_int_cfg = {
         .intrSrc = usbhs_interrupt_usbhsctrl_IRQn,

+ 10 - 3
components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c

@@ -293,12 +293,11 @@ static void dwc2_chan_init(struct usbh_bus *bus,
                            uint8_t ep_mult,
                            uint8_t speed)
 {
+    USB_OTG_HC((uint32_t)ch_num)->HCINTMSK = 0U;
+
     /* Clear old interrupt conditions for this host channel. */
     USB_OTG_HC((uint32_t)ch_num)->HCINT = 0xFFFFFFFFU;
 
-    /* Enable channel interrupts required for this transfer. */
-    USB_OTG_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_CHHM;
-
     /* Enable the top level host channel interrupt. */
     USB_OTG_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
 
@@ -310,6 +309,7 @@ static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint
 {
     __IO uint32_t tmpreg;
     uint8_t is_oddframe;
+    size_t flags;
 
     /* Initialize the HCTSIZn register */
     USB_OTG_HC(ch_num)->HCTSIZ = (size & USB_OTG_HCTSIZ_XFRSIZ) |
@@ -319,6 +319,11 @@ static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint
     /* xfer_buff MUST be 32-bits aligned */
     USB_OTG_HC(ch_num)->HCDMA = (uint32_t)buf;
 
+    flags = usb_osal_enter_critical_section();
+
+    /* Enable channel interrupts required for this transfer. */
+    USB_OTG_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_CHHM;
+
     is_oddframe = (((uint32_t)USB_OTG_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U;
     USB_OTG_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
     USB_OTG_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29;
@@ -328,6 +333,8 @@ static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint
     tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
     tmpreg |= USB_OTG_HCCHAR_CHENA;
     USB_OTG_HC(ch_num)->HCCHAR = tmpreg;
+
+    usb_osal_leave_critical_section(flags);
 }
 
 static inline void dwc2_chan_enable_csplit(struct usbh_bus *bus, uint8_t ch_num, bool enable)

+ 33 - 12
components/drivers/usb/cherryusb/port/hpmicro/usb_dc_hpm.c

@@ -7,6 +7,11 @@
 #include "usbd_core.h"
 #include "hpm_usb_device.h"
 #include "usb_glue_hpm.h"
+#include "hpm_sdk_version.h"
+
+#if SDK_VERSION_NUMBER < 0x10C00
+#error "Please use SDK version 1.12.0 or later because of USB api modification"
+#endif
 
 #define USB_NUM_BIDIR_ENDPOINTS USB_SOC_DCD_MAX_ENDPOINT_COUNT
 
@@ -46,6 +51,7 @@ struct hpm_udc {
 static USB_NOCACHE_RAM_SECTION ATTR_ALIGN(USB_SOC_DCD_DATA_RAM_ADDRESS_ALIGNMENT)
     uint8_t _dcd_data[CONFIG_USBDEV_MAX_BUS][HPM_ALIGN_UP(sizeof(dcd_data_t), USB_SOC_DCD_DATA_RAM_ADDRESS_ALIGNMENT)];
 static USB_NOCACHE_RAM_SECTION usb_device_handle_t usb_device_handle[CONFIG_USBDEV_MAX_BUS];
+static uint8_t _setup_data[8];
 
 /* Index to bit position in register */
 static inline uint8_t ep_idx2bit(uint8_t ep_idx)
@@ -234,12 +240,13 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
 {
     uint8_t ep_idx = USB_EP_GET_IDX(ep);
     usb_device_handle_t *handle = g_hpm_udc[busid].handle;
+    bool ret;
 
     if (!data && data_len) {
-        return -1;
+        return -USB_ERR_NOMEM;
     }
     if (!g_hpm_udc[busid].in_ep[ep_idx].ep_enable) {
-        return -2;
+        return -USB_ERR_NOTCONN;
     }
 
 #ifdef CONFIG_USB_DCACHE_ENABLE
@@ -251,21 +258,22 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
     g_hpm_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
 
     usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
-    usb_device_edpt_xfer(handle, ep, (uint8_t *)data, data_len);
+    ret = usb_device_edpt_xfer(handle, ep, (uint8_t *)data, data_len);
 
-    return 0;
+    return ret ? 0 : -USB_ERR_INVAL;
 }
 
 int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
 {
     uint8_t ep_idx = USB_EP_GET_IDX(ep);
     usb_device_handle_t *handle = g_hpm_udc[busid].handle;
+    bool ret;
 
     if (!data && data_len) {
-        return -1;
+        return -USB_ERR_NOMEM;
     }
     if (!g_hpm_udc[busid].out_ep[ep_idx].ep_enable) {
-        return -2;
+        return -USB_ERR_NOTCONN;
     }
 
 #ifdef CONFIG_USB_DCACHE_ENABLE
@@ -277,9 +285,9 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
     g_hpm_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
 
     usb_dcache_invalidate((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
-    usb_device_edpt_xfer(handle, ep, data, data_len);
+    ret = usb_device_edpt_xfer(handle, ep, data, data_len);
 
-    return 0;
+    return ret ? 0 : -USB_ERR_INVAL;
 }
 
 void USBD_IRQHandler(uint8_t busid)
@@ -310,6 +318,7 @@ void USBD_IRQHandler(uint8_t busid)
         memset(g_hpm_udc[busid].out_ep, 0, sizeof(struct hpm_ep_state) * USB_NUM_BIDIR_ENDPOINTS);
         usbd_event_reset_handler(busid);
         usb_device_bus_reset(handle, g_hpm_udc[busid].in_ep[0].ep_mps);
+        return;
     }
 
     if (int_status & intr_suspend) {
@@ -359,6 +368,11 @@ void USBD_IRQHandler(uint8_t busid)
                             break;
                         } else {
                             transfer_len += p_qtd->expected_bytes - p_qtd->total_bytes;
+                            if ((ep_idx & 0x01) != 0) {
+                                g_hpm_udc[busid].in_ep[ep_idx / 2].actual_xfer_len = transfer_len;
+                            } else {
+                                g_hpm_udc[busid].out_ep[ep_idx / 2].actual_xfer_len = transfer_len;
+                            }
                             p_qtd->in_use = false;
                         }
 
@@ -374,7 +388,7 @@ void USBD_IRQHandler(uint8_t busid)
                         if (ep_addr & 0x80) {
                             usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
                         } else {
-                            usb_dcache_invalidate((uintptr_t)g_hpm_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
+                            usb_dcache_invalidate((uintptr_t)g_hpm_udc[busid].out_ep[ep_idx / 2].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
                             usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
                         }
                     }
@@ -383,10 +397,17 @@ void USBD_IRQHandler(uint8_t busid)
         }
 
         if (edpt_setup_status) {
-            /*------------- Set up Received -------------*/
-            usb_device_clear_setup_status(handle, edpt_setup_status);
+            /*------------- Setup Received -------------*/
             dcd_qhd_t *qhd0 = usb_device_qhd_get(handle, 0);
-            usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&qhd0->setup_request);
+
+            usb_device_clear_setup_status(handle, edpt_setup_status);
+            do {
+                usb_dcd_set_sutw(handle->regs, true);
+                memcpy(_setup_data, (uint8_t *)(&qhd0->setup_request), 8);
+            } while (!usb_dcd_get_sutw(handle->regs));
+            usb_dcd_set_sutw(handle->regs, false);
+
+            usbd_event_ep0_setup_complete_handler(busid, _setup_data);
         }
     }
 }

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

@@ -9,6 +9,7 @@
 ### TI
 
 - MSP432E4x
+- TM4Cx
 
 ### Bekencorp
 

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

@@ -924,13 +924,6 @@ void handle_ep0(struct usbh_bus *bus)
         musb_urb_waitup(urb);
         return;
     }
-    if (ep0_status & USB_CSRL0_STALL) {
-        HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_CSRL0_STALL;
-        pipe->ep0_state = USB_EP0_STATE_SETUP;
-        urb->errorcode = -USB_ERR_STALL;
-        musb_urb_waitup(urb);
-        return;
-    }
 
     switch (pipe->ep0_state) {
         case USB_EP0_STATE_SETUP:
@@ -1097,8 +1090,8 @@ void USBH_IRQHandler(uint8_t busid)
                 HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_NAKTO;
                 urb->errorcode = -USB_ERR_NAK;
                 musb_urb_waitup(urb);
-            } else if (ep_csrl_status & USB_TXCSRL1_STALL) {
-                HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_STALL;
+            } else if (ep_csrl_status & USB_TXCSRL1_STALLED) {
+                HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_STALLED;
                 urb->errorcode = -USB_ERR_STALL;
                 musb_urb_waitup(urb);
             } else {
@@ -1146,8 +1139,8 @@ void USBH_IRQHandler(uint8_t busid)
                 HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_NAKTO;
                 urb->errorcode = -USB_ERR_NAK;
                 musb_urb_waitup(urb);
-            } else if (ep_csrl_status & USB_RXCSRL1_STALL) {
-                HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_STALL;
+            } else if (ep_csrl_status & USB_RXCSRL1_STALLED) {
+                HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_STALLED;
                 urb->errorcode = -USB_ERR_STALL;
                 musb_urb_waitup(urb);
             } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {