Update cherryusb to v1.6.1#11362

This commit is contained in:
sakumisu
2026-05-08 20:17:52 +08:00
committed by GitHub
parent 4e46e97c18
commit 3d2dc22c58
98 changed files with 2126 additions and 3078 deletions
@@ -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
View File
@@ -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
@@ -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
@@ -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
View File
@@ -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
@@ -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);
@@ -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
View File
@@ -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
View File
@@ -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 dont 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 showhttps://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
## Resources
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/).
### Getting Started
## Video Tutorial
- 📖 [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)
CherryUSB Cheese (>= V1.4.3): https://www.bilibili.com/cheese/play/ss707687201 .
### Tools
## Descriptor Generator Tool
- 🌐 [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)
Cherry Descriptor: https://desc.cherry-embedded.org/en
### Community Or Commercial Support
## Demo Repo
- 💬 [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)
| 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 |
### Package Support
## Package 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 package is available as follows:
### Mirror URL
- [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)
## Commercial Support
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
## Contact
CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
- [AtomGit](https://atomgit.com/cherry-embedded/CherryUSB)
## Company Support
+49 -61
View File
@@ -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 | × |
## 文档教程
## Resources
CherryUSB 快速入门、USB 基本概念、API 手册、Class 基本概念和例程,参考 [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)。
### 快速开始
## 视频教程
- 📖 [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 课程(>= V1.4.3):https://www.bilibili.com/cheese/play/ss707687201 。
### 工具
## 描述符生成工具
- 🌐 [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)
Cherry Descriptor: https://desc.cherry-embedded.org/zh
### 社区 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)
| 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 |
### 软件包
## 软件包支持
- 🌐 [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 软件包可以通过以下方式获取:
### 镜像仓库
- [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)
## 商业支持
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html 。
## 联系
CherryUSB QQ群:642693751
CherryUSB 微信群:与我联系后邀请加入
- [AtomGit](https://atomgit.com/cherry-embedded/CherryUSB)
## 支持企业
+18 -6
View File
@@ -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
View File
@@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 6
PATCHLEVEL = 0
PATCHLEVEL = 1
VERSION_TWEAK = 0
EXTRAVERSION = 0
@@ -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()
@@ -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
@@ -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,
@@ -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))
@@ -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;
@@ -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;
}
}
@@ -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 */ \
@@ -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;
}
@@ -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;
}
@@ -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 */
File diff suppressed because it is too large Load Diff
@@ -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
@@ -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;
@@ -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;
}
File diff suppressed because it is too large Load Diff
@@ -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 usage_min;
uint32_t usage_max;
uint32_t flags;
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;
};
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_item {
uint8_t report_type; /* input, output, feature */
uint16_t report_flags;
uint32_t report_bit_offset;
struct usbh_hid_report_item_attribute attribute;
};
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);
@@ -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;
}
@@ -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,
@@ -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 {
@@ -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
};
};
@@ -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);
}
}
@@ -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;
@@ -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);
}
@@ -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 */
@@ -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;
@@ -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;
@@ -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;
};
@@ -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;
@@ -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
@@ -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);
@@ -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
@@ -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
@@ -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;
}
@@ -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"
@@ -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
}
}
@@ -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;
};
@@ -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)
@@ -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];

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