update(cherryusb): update to v1.4.0

This commit is contained in:
sakumisu
2024-08-26 20:35:08 +08:00
committed by Meco Man
parent cbf6b641c2
commit 669a6822e7
132 changed files with 9776 additions and 1492 deletions
+11 -5
View File
@@ -48,6 +48,10 @@ if RT_USING_CHERRYUSB
bool "musb_bk"
config RT_CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX
bool "chipidea_mcx"
config RT_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
bool "chipidea_custom"
config RT_CHERRYUSB_DEVICE_BL
bool "bouffalo"
config RT_CHERRYUSB_DEVICE_CH32
@@ -162,10 +166,12 @@ if RT_USING_CHERRYUSB
bool "ehci_hpm"
config RT_CHERRYUSB_HOST_EHCI_AIC
bool "ehci_aic"
config RT_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980
bool "ehci_nuvoton_nuc980"
config RT_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0
bool "ehci_nuvoton_ma35d0"
config RT_CHERRYUSB_HOST_EHCI_MCX
bool "ehci_mcx"
config RT_CHERRYUSB_HOST_EHCI_NUC980
bool "ehci_nuc980"
config RT_CHERRYUSB_HOST_EHCI_MA35D0
bool "ehci_ma35d0"
config RT_CHERRYUSB_HOST_EHCI_CUSTOM
bool "ehci_custom"
config RT_CHERRYUSB_HOST_DWC2_ST
@@ -294,7 +300,7 @@ if RT_USING_CHERRYUSB
config CONFIG_USBHOST_PLATFORM_RTL8152
bool
config CHERRYUSB_HOST_TEMPLATE
config RT_CHERRYUSB_HOST_TEMPLATE
bool
prompt "Use usb host template"
default n
+24 -11
View File
@@ -34,7 +34,7 @@ Taking into account USB performance issues and trying to achieve the theoretical
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
- Subcontracting function is handled in interrupt
## Directoy Structure
## Directory Structure
| Directory | Description |
|:-------------:|:---------------------------:|
@@ -65,15 +65,17 @@ CherryUSB Device Stack has the following functions
- Support Device Firmware Upgrade CLASS (DFU)
- Support USB MIDI CLASS (MIDI)
- Support Remote NDIS (RNDIS)
- Support WINUSB1.0、WINUSB2.0(with BOS)
- Support WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- Support Vendor class
- Support UF2
- Support Android Debug Bridge (Only support shell)
- Support multi device with the same USB IP
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_core.c | 3516 | 512(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
@@ -87,6 +89,7 @@ The CherryUSB Host Stack has a standard enumeration implementation for devices m
CherryUSB Host Stack has the following functions
- Support low speed, full speed, high speed and super speed devices
- Automatic loading of supported Class drivers
- Support blocking transfers and asynchronous transfers
- Support Composite Device
@@ -98,7 +101,7 @@ CherryUSB Host Stack has the following functions
- Support USB Audio CLASS (UAC1.0)
- Support Remote NDIS (RNDIS)
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
- Support Vendor class
- Support Vendor class (serial, net, wifi)
- Support USB modeswitch
- Support multi host with the same USB IP
@@ -108,7 +111,7 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
@@ -152,6 +155,7 @@ Only standard and commercial USB IP are listed.
| DWC2(synopsys) | DWC2 | DWC2 | √ |
| MUSB(mentor) | MUSB | MUSB | √ |
| FOTG210(faraday)| FOTG210 | EHCI | √ |
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
| CDNS3(cadence) | CDNS3 | XHCI | × |
| DWC3(synopsys) | DWC3 | XHCI | × |
@@ -175,17 +179,26 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Package Support
CherryUSB package is available as follows:
- [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.
+24 -11
View File
@@ -65,15 +65,17 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 Device Firmware Upgrade CLASS (DFU)
- 支持 USB MIDI CLASS (MIDI)
- 支持 Remote NDIS (RNDIS)
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- 支持 Vendor 类 class
- 支持 UF2
- 支持 Android Debug Bridge (Only support shell)
- 支持相同 USB IP 的多从机
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_core.c | 3516 | 512(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
@@ -87,6 +89,7 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了
CherryUSB Host 协议栈当前实现以下功能:
- 支持 low speed, full speed, high speed 和 super speed 设备
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
@@ -98,7 +101,7 @@ CherryUSB Host 协议栈当前实现以下功能:
- Support USB Audio CLASS (UAC1.0)
- 支持 Remote NDIS (RNDIS)
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
- 支持 Vendor 类 class
- 支持 Vendor 类 class (serial, net, wifi)
- 支持 USB modeswitch
- 支持相同 USB IP 的多主机
@@ -108,7 +111,7 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
@@ -152,6 +155,7 @@ x 受以下宏影响:
| DWC2(synopsys) | DWC2 | DWC2 | √ |
| MUSB(mentor) | MUSB | MUSB | √ |
| FOTG210(faraday)| FOTG210 | EHCI | √ |
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
| CDNS3(cadence) | CDNS3 | XHCI | × |
| DWC3(synopsys) | DWC3 | XHCI | × |
@@ -176,20 +180,29 @@ CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## 软件包支持
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。
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html
## 联系
+40 -2
View File
@@ -15,6 +15,8 @@ path += [cwd + '/class/vendor/net']
path += [cwd + '/class/vendor/serial']
src = []
LIBS = []
LIBPATH = []
CPPDEFINES = []
# USB DEVICE
@@ -56,6 +58,9 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
src += Glob('port/musb/usb_dc_musb.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
src += Glob('port/chipidea/usb_dc_chipidea.c')
src += Glob('port/chipidea/usb_glue_mcx.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_BL']):
src += Glob('port/bouffalolab/usb_dc_bl.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_HPM']):
@@ -68,6 +73,15 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
src += Glob('port/ch32/usb_dc_usbhs.c')
else:
src += Glob('port/ch32/usb_dc_usbfs.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_PUSB2']):
path += [cwd + '/port/xhci/rt-thread']
src += Glob('port/pusb2/rt-thread/usb_dc_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_dc_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_dc_a32_softfp_neon.a']
if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_ACM']):
src += Glob('class/cdc/usbd_cdc.c')
@@ -140,10 +154,14 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_aic.c')
src += Glob('port/ohci/usb_hc_ohci.c')
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980']):
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_MCX']):
path += [cwd + '/port/chipidea']
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_mcx.c')
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUC980']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_nuc980.c')
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_MA35D0']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_ma35d0.c')
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_CUSTOM']):
@@ -169,6 +187,26 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['RT_CHERRYUSB_HOST_MUSB_CUSTOM']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['RT_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/rt-thread']
src += Glob('port/pusb2/rt-thread/usb_hc_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_hc_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_hc_a32_softfp_neon.a']
if GetDepend(['RT_CHERRYUSB_HOST_XHCI']):
path += [cwd + '/port/xhci/phytium/rt-thread']
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium_plat.c')
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/xhci/phytium']
LIBS = ['libxhci_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/xhci/phytium']
LIBS = ['libxhci_a32_softfp_neon.a']
if GetDepend(['RT_CHERRYUSB_HOST_CDC_ACM']):
src += Glob('class/cdc/usbh_cdc_acm.c')
+2 -2
View File
@@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 3
PATCHLEVEL = 1
VERSION_MINOR = 4
PATCHLEVEL = 0
VERSION_TWEAK = 0
EXTRAVERSION = 0
@@ -36,14 +36,16 @@ ${CMAKE_CURRENT_LIST_DIR}/class/audio
${CMAKE_CURRENT_LIST_DIR}/class/video
${CMAKE_CURRENT_LIST_DIR}/class/wireless
${CMAKE_CURRENT_LIST_DIR}/class/midi
${CMAKE_CURRENT_LIST_DIR}/class/adb
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
)
if(CONFIG_CHERRYUSB_DEVICE)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC_ACM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_acm.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_HID)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
@@ -69,6 +71,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
if(CONFIG_CHERRYUSB_DEVICE_DFU)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_ADB)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/adb/usbd_adb.c)
endif()
if(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
@@ -97,6 +102,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_bk")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "chipidea_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_dc_chipidea.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_glue_mcx.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
@@ -121,6 +129,9 @@ if(CONFIG_CHERRYUSB_HOST)
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
endif()
@@ -142,18 +153,10 @@ if(CONFIG_CHERRYUSB_HOST)
endif()
if(CONFIG_CHERRYUSB_HOST_VIDEO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/chry_pool.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/usbh_uvc_queue.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool)
endif()
if(CONFIG_CHERRYUSB_HOST_AUDIO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
@@ -209,6 +212,9 @@ if(CONFIG_CHERRYUSB_HOST)
if(CONFIG_CHERRYUSB_HOST_PL2303)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BL616)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
endif()
if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
@@ -226,6 +232,12 @@ if(CONFIG_CHERRYUSB_HOST)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_mcx.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_nuvoton")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
@@ -260,5 +272,21 @@ if(DEFINED CONFIG_CHERRYUSB_OSAL)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_yoc.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "idf")
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/osal/idf)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/idf/usb_osal_idf.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "threadx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_threadx.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_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/usbh_uvc_queue.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
endif()
@@ -6,16 +6,10 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x010301
#define CHERRYUSB_VERSION_STR "v1.3.1"
/* ================ USB common Configuration ================ */
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
#define usb_malloc(size) malloc(size)
#define usb_free(ptr) free(ptr)
#ifndef CONFIG_USB_DBG_LEVEL
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
#endif
@@ -72,6 +66,10 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
// #define CONFIG_USBDEV_MSC_POLLING
/* move msc read & write from isr to thread */
// #define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
@@ -0,0 +1,310 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_adb.h"
#define ADB_OUT_EP_IDX 0
#define ADB_IN_EP_IDX 1
#define ADB_STATE_READ_MSG 0
#define ADB_STATE_READ_DATA 1
#define ADB_STATE_WRITE_MSG 2
#define ADB_STATE_WRITE_DATA 3
#define ADB_STATE_AWRITE_MSG 4
#define ADB_STATE_AWRITE_DATA 5
#define MAX_PAYLOAD_V1 (4 * 1024)
#define MAX_PAYLOAD_V2 (256 * 1024)
#define MAX_PAYLOAD MAX_PAYLOAD_V1
#define A_VERSION 0x01000000
#define A_SYNC 0x434e5953
#define A_CNXN 0x4e584e43
#define A_OPEN 0x4e45504f
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
#define A_AUTH 0x48545541
struct adb_msg {
uint32_t command; /* command identifier constant (A_CNXN, ...) */
uint32_t arg0; /* first argument */
uint32_t arg1; /* second argument */
uint32_t data_length; /* length of payload (0 is allowed) */
uint32_t data_crc32; /* crc32 of data payload */
uint32_t magic; /* command ^ 0xffffffff */
};
struct adb_packet {
struct adb_msg msg;
uint8_t payload[MAX_PAYLOAD];
};
struct usbd_adb {
uint8_t state;
uint8_t common_state;
uint8_t write_state;
bool writable;
uint32_t localid;
uint32_t shell_remoteid;
uint32_t file_remoteid;
} adb_client;
static struct usbd_endpoint adb_ep_data[2];
USB_NOCACHE_RAM_SECTION struct adb_packet tx_packet;
USB_NOCACHE_RAM_SECTION struct adb_packet rx_packet;
static inline uint32_t adb_packet_checksum(struct adb_packet *packet)
{
uint32_t sum = 0;
uint32_t i;
for (i = 0; i < packet->msg.data_length; ++i) {
sum += (uint32_t)(packet->payload[i]);
}
return sum;
}
static uint32_t usbd_adb_get_remoteid(uint32_t localid)
{
if (localid == ADB_SHELL_LOALID) {
return adb_client.shell_remoteid;
} else {
return adb_client.file_remoteid;
}
}
static void adb_send_msg(struct adb_packet *packet)
{
adb_client.common_state = ADB_STATE_WRITE_MSG;
packet->msg.data_crc32 = adb_packet_checksum(packet);
packet->msg.magic = packet->msg.command ^ 0xffffffff;
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
}
static void adb_send_okay(struct adb_packet *packet, uint32_t localid)
{
packet->msg.command = A_OKAY;
packet->msg.arg0 = localid;
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
packet->msg.data_length = 0;
adb_send_msg(&tx_packet);
}
static void adb_send_close(struct adb_packet *packet, uint32_t localid, uint32_t remoteid)
{
packet->msg.command = A_CLSE;
packet->msg.arg0 = localid;
packet->msg.arg1 = remoteid;
packet->msg.data_length = 0;
adb_send_msg(&tx_packet);
}
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", nbytes);
return;
}
USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
rx_packet.msg.command,
rx_packet.msg.arg0,
rx_packet.msg.arg1,
rx_packet.msg.data_length);
if (rx_packet.msg.data_length) {
/* setup next out ep read transfer */
adb_client.common_state = ADB_STATE_READ_DATA;
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, rx_packet.payload, rx_packet.msg.data_length);
} else {
if (rx_packet.msg.command == A_CLSE) {
adb_client.writable = false;
usbd_adb_notify_write_done();
USB_LOG_INFO("Close remoteid:%x\r\n", rx_packet.msg.arg0);
}
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
}
} else if (adb_client.common_state == ADB_STATE_READ_DATA) {
switch (rx_packet.msg.command) {
case A_SYNC:
break;
case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
char *support_feature = "device::"
"ro.product.name=cherryadb;"
"ro.product.model=cherrysh;"
"ro.product.device=cherryadb;"
"features=cmd,shell_v1";
tx_packet.msg.command = A_CNXN;
tx_packet.msg.arg0 = A_VERSION;
tx_packet.msg.arg1 = MAX_PAYLOAD;
tx_packet.msg.data_length = strlen(support_feature);
memcpy(tx_packet.payload, support_feature, strlen(support_feature));
adb_send_msg(&tx_packet);
adb_client.writable = false;
break;
case A_OPEN: /* OPEN(local-id, 0, "destination") */
rx_packet.payload[rx_packet.msg.data_length] = '\0';
if (strncmp((const char *)rx_packet.payload, "shell:", 6) == 0) {
adb_client.localid = ADB_SHELL_LOALID;
adb_client.shell_remoteid = rx_packet.msg.arg0;
adb_send_okay(&tx_packet, ADB_SHELL_LOALID);
USB_LOG_INFO("Open shell service, remoteid:%x\r\n", rx_packet.msg.arg0);
} else if (strncmp((const char *)rx_packet.payload, "sync:", 5) == 0) {
adb_client.localid = ADB_FILE_LOALID;
adb_client.file_remoteid = rx_packet.msg.arg0;
adb_send_okay(&tx_packet, ADB_FILE_LOALID);
USB_LOG_INFO("Open file service, remoteid:%x\r\n", rx_packet.msg.arg0);
}
break;
case A_OKAY:
break;
case A_CLSE:
break;
case A_WRTE: /* WRITE(local-id, remote-id, "data") */
if ((rx_packet.msg.arg0 == adb_client.shell_remoteid) && (rx_packet.msg.arg1 == ADB_SHELL_LOALID)) {
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
} else if ((rx_packet.msg.arg0 == adb_client.file_remoteid) && (rx_packet.msg.arg1 == ADB_FILE_LOALID)) {
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
} else {
adb_send_close(&tx_packet, 0, rx_packet.msg.arg0);
}
break;
case A_AUTH:
break;
default:
break;
}
}
}
void usbd_adb_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
(void)nbytes;
if (adb_client.common_state == ADB_STATE_WRITE_MSG) {
if (tx_packet.msg.data_length) {
adb_client.common_state = ADB_STATE_WRITE_DATA;
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
} else {
if (rx_packet.msg.command == A_WRTE) {
adb_client.writable = true;
if (adb_client.localid == ADB_SHELL_LOALID) {
usbd_adb_notify_shell_read(rx_packet.payload, rx_packet.msg.data_length);
} else {
}
}
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
}
} else if (adb_client.common_state == ADB_STATE_WRITE_DATA) {
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
} else if (adb_client.write_state == ADB_STATE_AWRITE_MSG) {
if (tx_packet.msg.data_length) {
adb_client.write_state = ADB_STATE_AWRITE_DATA;
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
} else {
}
} else if (adb_client.write_state == ADB_STATE_AWRITE_DATA) {
usbd_adb_notify_write_done();
}
}
void adb_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)arg;
switch (event) {
case USBD_EVENT_INIT:
break;
case USBD_EVENT_DEINIT:
break;
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONFIGURED:
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
break;
default:
break;
}
}
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep)
{
(void)busid;
intf->class_interface_handler = NULL;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = adb_notify_handler;
adb_ep_data[ADB_OUT_EP_IDX].ep_addr = out_ep;
adb_ep_data[ADB_OUT_EP_IDX].ep_cb = usbd_adb_bulk_out;
adb_ep_data[ADB_IN_EP_IDX].ep_addr = in_ep;
adb_ep_data[ADB_IN_EP_IDX].ep_cb = usbd_adb_bulk_in;
usbd_add_endpoint(busid, &adb_ep_data[ADB_OUT_EP_IDX]);
usbd_add_endpoint(busid, &adb_ep_data[ADB_IN_EP_IDX]);
return intf;
}
bool usbd_adb_can_write(void)
{
return adb_client.writable;
}
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len)
{
struct adb_packet *packet;
packet = &tx_packet;
packet->msg.command = A_WRTE;
packet->msg.arg0 = localid;
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
packet->msg.data_length = len;
memcpy(packet->payload, data, len);
packet->msg.data_crc32 = adb_packet_checksum(packet);
packet->msg.magic = packet->msg.command ^ 0xffffffff;
adb_client.write_state = ADB_STATE_AWRITE_MSG;
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
return 0;
}
void usbd_adb_close(uint32_t localid)
{
adb_send_close(&tx_packet, 0, usbd_adb_get_remoteid(localid));
}
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_ADB_H
#define USBD_ADB_H
#include <stdint.h>
#define ADB_SHELL_LOALID 0x01
#define ADB_FILE_LOALID 0x02
// clang-format off
#define ADB_DESCRIPTOR_INIT(bFirstInterface, in_ep, out_ep, wMaxPacketSize) \
USB_INTERFACE_DESCRIPTOR_INIT(bFirstInterface, 0x00, 0x02, 0xff, 0x42, 0x01, 0x02), \
USB_ENDPOINT_DESCRIPTOR_INIT(in_ep, 0x02, wMaxPacketSize, 0x00), \
USB_ENDPOINT_DESCRIPTOR_INIT(out_ep, 0x02, wMaxPacketSize, 0x00)
// clang-format on
#ifdef __cplusplus
extern "C" {
#endif
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep);
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len);
void usbd_adb_notify_file_read(uint8_t *data, uint32_t len);
void usbd_adb_notify_write_done(void);
bool usbd_adb_can_write(void);
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len);
void usbd_adb_close(uint32_t localid);
#ifdef __cplusplus
}
#endif
#endif /* USBD_ADB_H */
@@ -62,7 +62,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
setup->bRequest);
uint8_t entity_id;
uint8_t ep;
uint8_t ep = 0;
uint8_t subtype = 0x01;
uint8_t control_selector;
uint8_t ch;
@@ -314,31 +314,56 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
{
(void)busid;
(void)ep;
(void)ch;
(void)volume;
}
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
{
(void)busid;
(void)ep;
(void)ch;
(void)mute;
}
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
(void)busid;
(void)ep;
(void)sampling_freq;
}
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
(void)ep;
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
(void)busid;
(void)ep;
(void)sampling_freq_table;
}
@@ -456,20 +456,26 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
{
(void)audio_class;
}
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
{
(void)audio_class;
}
const struct usbh_class_driver audio_ctrl_class_driver = {
@@ -1,29 +1,13 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_H
#define USBD_CDC_H
#include "usb_cdc.h"
// legacy for old version
#include "usbd_cdc_acm.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_H */
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
const char *stop_name[] = { "1", "1.5", "2" };
const char *parity_name[] = { "N", "O", "E", "M", "S" };
@@ -85,6 +85,8 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
{
(void)busid;
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
@@ -95,10 +97,16 @@ struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interfa
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
(void)line_coding;
}
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
line_coding->dwDTERate = 2000000;
line_coding->bDataBits = 8;
line_coding->bParityType = 0;
@@ -107,12 +115,20 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
(void)busid;
(void)intf;
(void)dtr;
}
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
{
(void)busid;
(void)intf;
(void)rts;
}
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
{
(void)busid;
(void)intf;
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_ACM_H
#define USBD_CDC_ACM_H
#include "usb_cdc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_ACM_H */
@@ -79,6 +79,10 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
"bRequest 0x%02x\r\n",
setup->bRequest);
(void)busid;
(void)data;
(void)len;
g_cmd_intf = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
@@ -105,6 +109,9 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)busid;
(void)arg;
switch (event) {
case USBD_EVENT_RESET:
g_current_net_status = 0;
@@ -123,19 +130,23 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < usbd_get_ep_mps(busid, ep)) {
if (nbytes < usbd_get_ep_mps(0, ep)) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
} else {
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, ep));
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep));
}
}
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
(void)busid;
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
@@ -145,6 +156,10 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
(void)ep;
(void)nbytes;
if (g_current_net_status == 1) {
g_current_net_status = 2;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
@@ -242,4 +257,6 @@ void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
(void)buf;
(void)len;
}
@@ -12,7 +12,7 @@
#define DEV_FORMAT "/dev/ttyACM%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
@@ -57,9 +57,9 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
memcpy(g_cdc_acm_buf[cdc_acm_class->minor], line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -78,11 +78,11 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
memcpy(line_coding, g_cdc_acm_buf[cdc_acm_class->minor], sizeof(struct cdc_line_coding));
return ret;
}
@@ -231,20 +231,26 @@ int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
const struct usbh_class_driver cdc_acm_class_driver = {
@@ -236,6 +236,7 @@ void usbh_cdc_ecm_rx_thread(void *argument)
uint32_t g_cdc_ecm_rx_length;
int ret;
(void)argument;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:
@@ -306,10 +307,12 @@ int usbh_cdc_ecm_eth_output(uint32_t buflen)
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
const struct usbh_class_driver cdc_ecm_class_driver = {
@@ -259,6 +259,7 @@ void usbh_cdc_ncm_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
// clang-format off
find_class:
@@ -330,7 +331,7 @@ find_class:
#else
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
@@ -386,10 +387,12 @@ int usbh_cdc_ncm_eth_output(uint32_t buflen)
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
const struct usbh_class_driver cdc_ncm_class_driver = {
@@ -558,26 +558,24 @@ struct usb_hid_kbd_report
};
/* Keyboard output report (1 byte) (HID B.1),
* see USBHID_KBDOUT_* definitions
* see HID_KBD_OUTPUT_* definitions
*/
/* Mouse input report (HID B.2) */
struct usb_hid_mouse_report
{
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
uint8_t xdisp; /* X displacement */
uint8_t ydisp; /* y displacement */
int8_t xdisp; /* X displacement */
int8_t ydisp; /* y displacement */
/* Device specific additional bytes may follow */
#ifdef CONFIG_INPUT_MOUSE_WHEEL
uint8_t wdisp; /* Wheel displacement */
#endif
};
/* Joystick input report (1 bytes) (HID D.1) */
struct usb_hid_js_report
{
uint8_t xpos; /* X position */
uint8_t ypos; /* X position */
int8_t xpos; /* X position */
int8_t ypos; /* X position */
uint8_t buttons; /* See USBHID_JSIN_* definitions */
uint8_t throttle; /* Throttle */
};
@@ -50,6 +50,8 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
{
(void)busid;
intf->class_interface_handler = hid_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
@@ -60,30 +62,65 @@ struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *
return intf;
}
/*
* Appendix G: HID Request Support Requirements
*
* The following table enumerates the requests that need to be supported by various types of HID class devices.
* Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
* ------------------------------------------------------------------------------------------
* Boot Mouse Required Optional Optional Optional Required Required
* Non-Boot Mouse Required Optional Optional Optional Optional Optional
* Boot Keyboard Required Optional Required Required Required Required
* Non-Boot Keybrd Required Optional Required Required Optional Optional
* Other Device Required Optional Optional Optional Optional Optional
*/
__WEAK void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
{
(void)busid;
(void)intf;
(void)report_id;
(void)report_type;
(*data[0]) = 0;
*len = 1;
}
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
{
(void)busid;
(void)intf;
(void)report_id;
return 0;
}
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
{
(void)busid;
(void)intf;
return 0;
}
__WEAK void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
{
(void)busid;
(void)intf;
(void)report_id;
(void)report_type;
(void)report;
(void)report_len;
}
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
{
(void)busid;
(void)intf;
(void)report_id;
(void)duration;
}
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
{
(void)busid;
(void)intf;
(void)protocol;
}
@@ -12,7 +12,15 @@
#define DEV_FORMAT "/dev/input%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[CONFIG_USBHOST_MAX_HID_CLASS][USB_ALIGN_UP(256, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
@@ -56,13 +64,13 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
setup->wIndex = hid_class->intf;
setup->wLength = 128;
setup->wLength = hid_class->report_size;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf, ret - 8);
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
@@ -100,11 +108,11 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
setup->wIndex = hid_class->intf;
setup->wLength = 1;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf, 1);
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
@@ -147,6 +155,7 @@ int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
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 usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
@@ -159,13 +168,21 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
setup->wIndex = 0;
setup->wLength = buflen;
return usbh_control_transfer(hid_class->hport, setup, buffer);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t cur_iface = 0xff;
uint8_t *p;
bool found = false;
struct usbh_hid *hid_class = usbh_hid_class_alloc();
if (hid_class == NULL) {
@@ -178,6 +195,47 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
hport->config.intf[intf].priv = hid_class;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
if (cur_iface == intf) {
hid_class->protocol = p[7];
struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9);
if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) {
USB_LOG_ERR("HID descriptor not found\r\n");
return -USB_ERR_INVAL;
}
if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) {
USB_LOG_ERR("HID report descriptor not found\r\n");
return -USB_ERR_INVAL;
}
hid_class->report_size = desc->subdesc[0].wDescriptorLength;
if (hid_class->report_size > sizeof(g_hid_buf[hid_class->minor])) {
USB_LOG_ERR("HID report descriptor too large\r\n");
return -USB_ERR_INVAL;
}
found = true;
goto found;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
if (found == false) {
USB_LOG_ERR("HID interface not found\r\n");
return -USB_ERR_INVAL;
}
found:
// /* 0x0 = boot protocol, 0x1 = report protocol */
// ret = usbh_hid_set_protocol(hid_class, 0x1);
// if (ret < 0) {
@@ -239,10 +297,12 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
{
(void)hid_class;
}
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
{
(void)hid_class;
}
const struct usbh_class_driver hid_class_driver = {
@@ -16,6 +16,9 @@ struct usbh_hid {
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t report_desc[256];
uint16_t report_size;
uint8_t protocol;
uint8_t intf; /* interface number */
uint8_t minor;
@@ -10,6 +10,12 @@
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
#define HUB_MAX_DEPTH 5
#define HUB_SUBCLASS 0x00
#define HUB_PROTOCOL_STT 0x01
#define HUB_PROTOCOL_MTT 0x02
/* Hub class requests */
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
@@ -32,18 +38,26 @@
#define HUB_PORT_FEATURE_SUSPEND (0x02)
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
#define HUB_PORT_FEATURE_RESET (0x04)
#define HUB_PORT_FEATURE_L1 (0x05)
#define HUB_PORT_FEATURE_POWER (0x08)
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
#define HUB_PORT_FEATURE_POWER_SS (0x09) /* USB 3.0 only */
/* This is a bit tricky because HUB_PORT_FEATURE_POWER_SS and
HUB_PORT_FEATURE_LOWSPEED share the same bit. */
#define HUB_PORT_FEATURE_LOWSPEED (0x09) /* USB 2.0 only */
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) /* USB 2.0 only */
#define HUB_PORT_FEATURE_TEST (0x0b) /* USB 2.0 only */
#define HUB_PORT_FEATURE_INDICATOR (0x0c) /* USB 2.0 only */
/* Port status change (wPortChange) */
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
#define HUB_PORT_FEATURE_C_RESET (0x14)
#define HUB_PORT_FEATURE_TEST (0x15)
#define HUB_PORT_FEATURE_INDICATOR (0x16)
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
/* Hub status */
#define HUB_STATUS_LOCALPOWER (1 << 0)
@@ -56,23 +70,42 @@
/* Hub port status */
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
#define HUB_PORT_STATUS_ENABLE (1 << 1)
#define HUB_PORT_STATUS_SUSPEND (1 << 2)
#define HUB_PORT_STATUS_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_RESET (1 << 4)
#define HUB_PORT_STATUS_L1 (1 << 5)
#define HUB_PORT_STATUS_L1 (1 << 5) /* USB 2.0 only */
/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
#define HUB_PORT_STATUS_LS_U2 (0x02 << 5)
#define HUB_PORT_STATUS_LS_U3 (0x03 << 5)
#define HUB_PORT_STATUS_LS_SS_DISABLED (0x04 << 5)
#define HUB_PORT_STATUS_LS_RX_DETECT (0x05 << 5)
#define HUB_PORT_STATUS_LS_SS_INACTIVE (0x06 << 5)
#define HUB_PORT_STATUS_LS_POLLING (0x07 << 5)
#define HUB_PORT_STATUS_LS_RECOVERY (0x08 << 5)
#define HUB_PORT_STATUS_LS_HOT_RESET (0x09 << 5)
#define HUB_PORT_STATUS_LS_COMP_MOD (0x0a << 5)
#define HUB_PORT_STATUS_LS_LOOPBACK (0x0b << 5)
#define HUB_PORT_STATUS_POWER (1 << 8)
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
#define HUB_PORT_STATUS_TEST (1 << 11)
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
#define HUB_PORT_STATUS_POWER_SS (1 << 9) /* USB 3.0 only */
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) /* USB 2.0 only */
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) /* USB 2.0 only */
#define HUB_PORT_STATUS_TEST (1 << 11) /* USB 2.0 only */
#define HUB_PORT_STATUS_INDICATOR (1 << 12) /* USB 2.0 only */
/* Hub port status change */
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_C_RESET (1 << 4)
#define HUB_PORT_STATUS_C_L1 (1 << 5)
#define HUB_PORT_STATUS_C_L1 (1 << 5) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_BH_RESET (1 << 5) /* USB 3.0 only */
#define HUB_PORT_STATUS_C_PORTLINK (1 << 6) /* USB 3.0 only */
#define HUB_PORT_STATUS_C_CONFIGERR (1 << 7) /* USB 3.0 only */
/* Hub characteristics */
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
@@ -106,6 +139,21 @@ struct usb_hub_descriptor {
#define USB_SIZEOF_HUB_DESC 9
/* Super speed Hub descriptor */
struct usb_hub_ss_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
uint16_t wHubCharacteristics;
uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent;
uint8_t bHubHdrDecLat;
uint16_t wHubDelay;
uint8_t DeviceRemovable;
} __PACKED;
#define USB_SIZEOF_HUB_SS_DESC 11
/* Hub status */
struct hub_status {
uint16_t wPortStatus;
@@ -55,9 +55,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
#endif
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -67,15 +65,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
and we havn't handle the difference here */
if ((hub->parent->speed == USB_SPEED_SUPER) ||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
} else {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
}
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_HUB_DESC;
@@ -87,8 +77,8 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
return ret;
}
#if 0
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
@@ -96,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
setup = hub->parent->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = HUB_REQUEST_GET_STATUS;
setup->wValue = 0;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
setup->wIndex = 0;
setup->wLength = 2;
setup->wLength = USB_SIZEOF_HUB_SS_DESC;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf[hub->bus->busid], 2);
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
return ret;
}
#endif
#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -180,6 +170,8 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
{
(void)length;
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -1;
@@ -199,6 +191,29 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
}
return 0;
}
static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
{
(void)length;
if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -1;
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
return -2;
} else {
USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
}
return 0;
}
#endif
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
@@ -311,22 +326,65 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->bus = hport->bus;
hub->speed = hport->speed;
hport->self = hub;
hport->config.intf[intf].priv = hub;
if (hport->depth > HUB_MAX_DEPTH) {
USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
return -USB_ERR_INVAL;
}
/*
* Super-Speed hubs need to know their depth to be able to
* parse the bits of the route-string that correspond to
* their downstream port number.
*
*/
if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
ret = usbh_hub_set_depth(hub, hport->depth - 1);
if (ret < 0) {
USB_LOG_ERR("Unable to set hub depth \r\n");
return ret;
}
}
/* Get hub descriptor. */
if (hport->speed == USB_SPEED_SUPER) {
ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
if (ret < 0) {
return ret;
}
parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
hub->nports = hub->hub_ss_desc.bNbrPorts;
hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
hub->tt_think = 0U;
} else {
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
if (ret < 0) {
return ret;
}
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
hub->nports = hub->hub_desc.bNbrPorts;
hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
hub->child[port].port = port + 1;
hub->child[port].parent = hub;
hub->child[port].bus = hport->bus;
}
if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
hub->ismtt = 1;
} else {
hub->ismtt = 0;
}
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(hub->intin, ep_desc);
@@ -334,28 +392,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
return -1;
}
if (hport->speed == USB_SPEED_SUPER) {
uint16_t depth = 0;
struct usbh_hubport *parent = hport->parent->parent;
while (parent) {
depth++;
parent = parent->parent->parent;
}
ret = usbh_hub_set_depth(hub, depth);
if (ret < 0) {
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
if (ret < 0) {
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
usb_osal_msleep(hub->powerdelay);
for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
if (ret < 0) {
@@ -395,7 +441,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
usb_osal_timer_delete(hub->int_timer);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
child = &hub->child[port];
usbh_hubport_release(child);
child->parent = NULL;
@@ -415,7 +461,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
{
struct usbh_hubport *child;
struct hub_port_status port_status;
uint8_t portchange_index;
uint16_t portchange_index;
uint16_t portstatus;
uint16_t portchange;
uint16_t mask;
@@ -429,11 +475,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
flags = usb_osal_enter_critical_section();
portchange_index = hub->int_buffer[0];
hub->int_buffer[0] &= ~portchange_index;
memcpy(&portchange_index, hub->int_buffer, 2);
usb_osal_leave_critical_section(flags);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
if (!(portchange_index & (1 << (port + 1)))) {
@@ -539,6 +584,11 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
/*
* Figure out device speed. This is a bit tricky because
* HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
*/
if (portstatus & HUB_PORT_STATUS_POWER) {
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
speed = USB_SPEED_HIGH;
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
@@ -546,6 +596,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
} else {
speed = USB_SPEED_FULL;
}
} else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
speed = USB_SPEED_SUPER;
} else {
USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
continue;
}
child = &hub->child[port];
/** release child sources first */
@@ -553,6 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
memset(child, 0, sizeof(struct usbh_hubport));
child->parent = hub;
child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
child->connected = true;
child->port = port + 1;
child->speed = speed;
@@ -624,7 +681,7 @@ int usbh_hub_initialize(struct usbh_bus *bus)
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
@@ -652,7 +709,7 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
flags = usb_osal_enter_critical_section();
hub = &bus->hcd.roothub;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
usbh_hubport_release(hport);
@@ -10,10 +10,6 @@
struct usbh_hub;
#define USBH_HUB_MAX_PORTS 4
/* Maximum size of an interrupt IN transfer */
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
#ifdef __cplusplus
extern "C" {
#endif
@@ -9,6 +9,8 @@
#include "usb_scsi.h"
#if defined(CONFIG_USBDEV_MSC_THREAD)
#include "usb_osal.h"
#elif defined(CONFIG_USBDEV_MSC_POLLING)
#include "chry_ringbuffer.h"
#endif
#define MSD_OUT_EP_IDX 0
@@ -50,6 +52,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
usb_osal_mq_t usbd_msc_mq;
usb_osal_thread_t usbd_msc_thread;
uint32_t nbytes;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_t msc_rb;
uint8_t msc_rb_pool[2];
uint32_t nbytes;
#endif
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
@@ -94,9 +100,11 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)arg;
switch (event) {
case USBD_EVENT_INIT:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
@@ -105,10 +113,12 @@ void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_init(&g_usbd_msc[busid].msc_rb, g_usbd_msc[busid].msc_rb_pool, sizeof(g_usbd_msc[busid].msc_rb_pool));
#endif
break;
case USBD_EVENT_DEINIT:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
if (g_usbd_msc[busid].usbd_msc_mq) {
usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
}
@@ -500,6 +510,9 @@ static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -522,8 +535,10 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
@@ -532,6 +547,9 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -554,8 +572,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
@@ -565,6 +585,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -594,6 +618,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -803,6 +831,8 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
switch (g_usbd_msc[busid].stage) {
case MSC_READ_CBW:
if (SCSI_CBWDecode(busid, nbytes) == false) {
@@ -815,9 +845,12 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_WRITE10:
case SCSI_CMD_WRITE12:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].nbytes = nbytes;
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
g_usbd_msc[busid].nbytes = nbytes;
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_OUT);
#else
if (SCSI_processWrite(busid, nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -835,13 +868,18 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
(void)nbytes;
switch (g_usbd_msc[busid].stage) {
case MSC_DATA_IN:
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
#else
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -870,7 +908,7 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
}
}
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
static void usbdev_msc_thread(void *argument)
{
uintptr_t event;
@@ -882,7 +920,26 @@ static void usbdev_msc_thread(void *argument)
if (ret < 0) {
continue;
}
USB_LOG_DBG("%d\r\n", event);
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else if (event == MSC_DATA_IN) {
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else {
}
}
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
void usbd_msc_polling(uint8_t busid)
{
uint8_t event;
if (chry_ringbuffer_read_byte(&g_usbd_msc[busid].msc_rb, &event)) {
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -932,7 +989,7 @@ void usbd_msc_set_readonly(uint8_t busid, bool readonly)
g_usbd_msc[busid].readonly = readonly;
}
bool usbd_msc_set_popup(uint8_t busid)
bool usbd_msc_get_popup(uint8_t busid)
{
return g_usbd_msc[busid].popup;
}
@@ -23,7 +23,9 @@ int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *b
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
bool usbd_msc_set_popup(uint8_t busid);
bool usbd_msc_get_popup(uint8_t busid);
void usbd_msc_polling(uint8_t busid);
#ifdef __cplusplus
}
@@ -15,7 +15,7 @@
#define MSC_INQUIRY_TIMEOUT 500
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[64];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
static uint32_t g_devinuse = 0;
@@ -87,6 +87,8 @@ static void usbh_msc_cbw_dump(struct CBW *cbw)
static void usbh_msc_csw_dump(struct CSW *csw)
{
(void)csw;
USB_LOG_DBG("CSW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
@@ -182,14 +184,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL, MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
@@ -197,7 +199,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -207,7 +209,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
@@ -215,7 +217,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -225,7 +227,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_INQUIRY;
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
@@ -233,7 +235,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -242,7 +244,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
@@ -250,11 +252,11 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memcpy(g_msc_buf, message, 31);
memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL, MSC_INQUIRY_TIMEOUT);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
@@ -274,12 +276,12 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
hport->config.intf[intf].priv = msc_class;
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][0] + 1);
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
@@ -376,7 +378,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -387,7 +389,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
@@ -395,7 +397,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -407,7 +409,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
@@ -421,10 +423,12 @@ void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
{
(void)msc_class;
}
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
{
(void)msc_class;
}
const struct usbh_class_driver msc_class_driver = {
@@ -680,6 +680,7 @@ void usbh_asix_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create asix rx thread\r\n");
// clang-format off
find_class:
@@ -742,7 +743,7 @@ find_class:
#else
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
@@ -791,10 +792,12 @@ int usbh_asix_eth_output(uint32_t buflen)
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
{
(void)asix_class;
}
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
{
(void)asix_class;
}
static const uint16_t asix_id_table[][2] = {
@@ -2140,6 +2140,7 @@ void usbh_rtl8152_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
// clang-format off
find_class:
@@ -2210,7 +2211,7 @@ find_class:
#else
if ((g_rtl8152_rx_length + (16 * 1024)) > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE\r\n");
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
@@ -2248,10 +2249,12 @@ int usbh_rtl8152_eth_output(uint32_t buflen)
__WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
{
(void)rtl8152_class;
}
__WEAK void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
{
(void)rtl8152_class;
}
static const uint16_t rtl_id_table[][2] = {
@@ -349,10 +349,12 @@ int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
{
(void)ch34x_class;
}
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
{
(void)ch34x_class;
}
static const uint16_t ch34x_id_table[][2] = {
@@ -10,7 +10,7 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
static uint32_t g_devinuse = 0;
@@ -298,10 +298,12 @@ int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buf
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
{
(void)cp210x_class;
}
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
{
(void)cp210x_class;
}
static const uint16_t cp210x_id_table[][2] = {
@@ -10,7 +10,7 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
#define CONFIG_USBHOST_MAX_FTDI_CLASS 1
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
static uint32_t g_devinuse = 0;
@@ -57,7 +57,7 @@ static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_
}
int divisor = FTDI_USB_CLK / baudrate;
int frac_bits = 0;
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
for (uint8_t i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
if ((divisor & 0xF) == frac[i]) {
frac_bits = i;
break;
@@ -370,10 +370,12 @@ int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, u
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
{
(void)ftdi_class;
}
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
{
(void)ftdi_class;
}
static const uint16_t ftdi_id_table[][2] = {
@@ -15,7 +15,7 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[64];
#define CONFIG_USBHOST_MAX_PL2303_CLASS 4
#define CONFIG_USBHOST_MAX_PL2303_CLASS 1
#define UT_WRITE_VENDOR_DEVICE (USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
#define UT_READ_VENDOR_DEVICE (USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
@@ -413,10 +413,12 @@ int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buf
__WEAK void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
{
(void)pl2303_class;
}
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
{
(void)pl2303_class;
}
static const uint16_t pl2303_id_table[][2] = {
@@ -0,0 +1,6 @@
# BL616 USB WIFI
Usbwifi firmware please contact bouffalolab. You can purchase a module in the following ways:
- https://iot.mi.com/moduleBrowser.html
- https://docs.ai-thinker.com/ai_m61
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,220 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_BL616_H
#define USBH_BL616_H
#define USBWIFI_DATA_TYPE_CMD 0xA55A
#define USBWIFI_DATA_TYPE_PKT 0x6996
#define USB_DATA_FLAG_AP_PKT (1u << 0)
typedef enum {
BFLB_CMD_REBOOT = 0,
BFLB_CMD_RESET,
BFLB_CMD_HELLO,
BFLB_CMD_PING,
BFLB_CMD_GET_MAC_ADDR,
// Scan
BFLB_CMD_SCAN,
BFLB_CMD_SCAN_RESULTS,
// STA
BFLB_CMD_STA_CONNECT,
BFLB_CMD_STA_DISCONNECT,
BFLB_CMD_STA_CONNECTED_IND,
BFLB_CMD_STA_DISCONNECTED_IND,
BFLB_CMD_STA_IP_UPDATE_IND,
BFLB_CMD_STA_SET_AUTO_RECONNECT,
BFLB_CMD_STA_GET_LINK_STATUS,
// AP
BFLB_CMD_AP_START,
BFLB_CMD_AP_STOP,
BFLB_CMD_AP_STARTED_IND,
BFLB_CMD_AP_STOPPED_IND,
BFLB_CMD_AP_GET_STA_LIST,
// Monitor
BFLB_CMD_MONITOR_START,
BFLB_CMD_MONITOR_STOP,
BFLB_CMD_MONITOR_SET_CHANNEL,
BFLB_CMD_MONITOR_GET_CHANNEL,
BFLB_CMD_SET_LPM_MODE,
// OTA
BFLB_CMD_GET_DEV_VERSION,
BFLB_CMD_OTA,
BFLB_CMD_EXT,
BFLB_CMD_USER_EXT,
BFLB_CMD_UNLOAD_DRV,
BFLB_CMD_MAX,
} bflb_cmd_t;
typedef enum {
STATUS_OK,
STATUS_NOMEM = 128,
STATUS_INVALID_INPUT,
STATUS_INVALID_MODE,
STATUS_ERR_UNSPECIFIED,
STATUS_NOT_IMPLEMENTED,
} cmd_status_t;
typedef enum {
RNM_WIFI_AUTH_UNKNOWN = 0,
RNM_WIFI_AUTH_OPEN,
RNM_WIFI_AUTH_WEP,
RNM_WIFI_AUTH_WPA_PSK,
RNM_WIFI_AUTH_WPA2_PSK,
RNM_WIFI_AUTH_WPA_WPA2_PSK,
RNM_WIFI_AUTH_WPA_ENTERPRISE,
RNM_WIFI_AUTH_WPA3_SAE,
RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE,
RNM_WIFI_AUTH_MAX,
} rnm_wifi_auth_mode_t;
typedef enum {
RNM_WIFI_CIPHER_UNKNOWN = 0,
RNM_WIFI_CIPHER_NONE,
RNM_WIFI_CIPHER_WEP,
RNM_WIFI_CIPHER_AES,
RNM_WIFI_CIPHER_TKIP,
RNM_WIFI_CIPHER_TKIP_AES,
RNM_WIFI_CIPHER_MAX,
} rnm_wifi_cipher_t;
/* common header */
typedef struct {
uint16_t cmd;
// flag ACK is used by server to indicate a response to client
#define RNM_MSG_FLAG_ACK (1 << 0)
// flag TRANSPARENT is never transfered to peer but used locally
#define RNM_MSG_FLAG_TRANSPARENT (1 << 1)
// flag ASYNC is used by server to notify client events such as STA_CONNECTED
#define RNM_MSG_FLAG_ASYNC (1 << 2)
uint16_t flags;
uint16_t status;
uint16_t msg_id;
uint16_t session_id;
uint16_t msg_id_replying;
} rnm_base_msg_t;
typedef struct {
rnm_base_msg_t hdr;
} rnm_ack_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint8_t sta_mac[6];
uint8_t ap_mac[6];
} rnm_mac_addr_ind_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint16_t ssid_len;
uint8_t ssid[32];
uint8_t password[64];
} rnm_sta_connect_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint8_t ip4_addr[4];
uint8_t ip4_mask[4];
uint8_t ip4_gw[4];
uint8_t ip4_dns1[4];
uint8_t ip4_dns2[4];
uint8_t gw_mac[6];
} rnm_sta_ip_update_ind_msg_t;
struct bf1b_wifi_scan_record {
uint8_t bssid[6];
// TODO use compressed SSID encoding to save room
uint8_t ssid[32 + 1];
uint16_t channel;
int8_t rssi;
uint8_t auth_mode;
uint8_t cipher;
} __PACKED;
typedef struct {
rnm_base_msg_t hdr;
uint16_t num;
struct bf1b_wifi_scan_record records[];
} rnm_scan_ind_msg_t;
typedef enum {
BL_MODE_NONE,
BL_MODE_STA, // card is STA
BL_MODE_AP, // card is AP
BL_MODE_STA_AP, // card is STA&AP
BL_MODE_SNIFFER, // card is sniffer
BL_MODE_MAX,
} bl_wifi_mode_t;
typedef struct {
uint16_t type;
uint16_t length;
uint16_t flags;
uint16_t payload_offset;
uint32_t rsvd[8];
uint8_t payload[];
} __attribute__((aligned(4))) usb_data_t;
struct usbh_bl616 {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
uint8_t intf;
uint8_t sta_mac[6];
uint8_t ap_mac[6];
uint8_t mode;
bool connect_status;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_bl616_wifi_sta_connect(const char *ssid,
const int ssid_len,
const char *password,
const int pwd_len);
int usbh_bl616_wifi_sta_disconnect(void);
int usbh_bl616_wifi_scan(void);
void usbh_bl616_sta_connect_callback(void);
void usbh_bl616_sta_disconnect_callback(void);
void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t ip4_gw[4]);
uint8_t *usbh_bl616_get_eth_txbuf(void);
int usbh_bl616_eth_output(uint32_t buflen);
void usbh_bl616_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_bl616_rx_thread(void *argument);
void usbh_bl616_run(struct usbh_bl616 *bl616_class);
void usbh_bl616_stop(struct usbh_bl616 *bl616_class);
int wifi_sta_connect(int argc, char **argv);
int wifi_scan(int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif /* USBH_BL616_H */
@@ -0,0 +1,228 @@
/*
* Copyright (c) 2024 Till Harbaum
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_xbox.h"
#define DEV_FORMAT "/dev/xbox%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_xbox_buf[128];
static struct usbh_xbox g_xbox_class[CONFIG_USBHOST_MAX_XBOX_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_xbox *usbh_xbox_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_xbox_class[devno], 0, sizeof(struct usbh_xbox));
g_xbox_class[devno].minor = devno;
return &g_xbox_class[devno];
}
}
return NULL;
}
static void usbh_xbox_class_free(struct usbh_xbox *xbox_class)
{
int devno = xbox_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(xbox_class, 0, sizeof(struct usbh_xbox));
}
int usbh_xbox_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
struct usbh_xbox *xbox_class = usbh_xbox_class_alloc();
if (xbox_class == NULL) {
USB_LOG_ERR("Fail to alloc xbox_class\r\n");
return -USB_ERR_NOMEM;
}
xbox_class->hport = hport;
xbox_class->intf = intf;
hport->config.intf[intf].priv = xbox_class;
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(xbox_class->intin, ep_desc);
} else {
USBH_EP_INIT(xbox_class->intout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, xbox_class->minor);
USB_LOG_INFO("Register XBOX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xbox_run(xbox_class);
return 0;
}
int usbh_xbox_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_xbox *xbox_class = (struct usbh_xbox *)hport->config.intf[intf].priv;
if (xbox_class) {
if (xbox_class->intin) {
usbh_kill_urb(&xbox_class->intin_urb);
}
if (xbox_class->intout) {
usbh_kill_urb(&xbox_class->intout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister XBOX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xbox_stop(xbox_class);
}
usbh_xbox_class_free(xbox_class);
}
return ret;
}
__WEAK void usbh_xbox_run(struct usbh_xbox *xbox_class)
{
}
__WEAK void usbh_xbox_stop(struct usbh_xbox *xbox_class)
{
}
const struct usbh_class_driver xbox_class_driver = {
.driver_name = "xbox",
.connect = usbh_xbox_connect,
.disconnect = usbh_xbox_disconnect
};
static const uint16_t xbox_id_table[][2] = {
{ 0x0079, 0x18d4 }, // GPD Win 2 X-Box Controller
{ 0x03eb, 0xff01 }, // Wooting One (Legacy)
{ 0x03eb, 0xff02 }, // Wooting Two (Legacy)
{ 0x044f, 0xb326 }, // Thrustmaster Gamepad GP XID
{ 0x045e, 0x028e }, // Microsoft X-Box 360 pad
{ 0x045e, 0x028f }, // Microsoft X-Box 360 pad v2
{ 0x046d, 0xc21d }, // Logitech Gamepad F310
{ 0x046d, 0xc21e }, // Logitech Gamepad F510
{ 0x046d, 0xc21f }, // Logitech Gamepad F710
{ 0x046d, 0xc242 }, // Logitech Chillstream Controller
{ 0x046d, 0xcaa3 }, // Logitech DriveFx Racing Wheel
{ 0x056e, 0x2004 }, // Elecom JC-U3613M
{ 0x06a3, 0xf51a }, // Saitek P3600
{ 0x0738, 0x4716 }, // Mad Catz Wired Xbox 360 Controller
{ 0x0738, 0x4718 }, // Mad Catz Street Fighter IV FightStick SE
{ 0x0738, 0x4726 }, // Mad Catz Xbox 360 Controller
{ 0x0738, 0x4736 }, // Mad Catz MicroCon Gamepad
{ 0x0738, 0x4740 }, // Mad Catz Beat Pad
{ 0x0738, 0x9871 }, // Mad Catz Portable Drum
{ 0x0738, 0xb726 }, // Mad Catz Xbox controller - MW2
{ 0x0738, 0xbeef }, // Mad Catz JOYTECH NEO SE Advanced GamePad
{ 0x0738, 0xcb02 }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
{ 0x0738, 0xcb03 }, // Saitek P3200 Rumble Pad - PC/Xbox 360
{ 0x0738, 0xcb29 }, // Saitek Aviator Stick AV8R02
{ 0x0738, 0xf738 }, // Super SFIV FightStick TE S
{ 0x07ff, 0xffff }, // Mad Catz GamePad
{ 0x0e6f, 0x0113 }, // Afterglow AX.1 Gamepad for Xbox 360
{ 0x0e6f, 0x011f }, // Rock Candy Gamepad Wired Controller
{ 0x0e6f, 0x0131 }, // PDP EA Sports Controller
{ 0x0e6f, 0x0133 }, // Xbox 360 Wired Controller
{ 0x0e6f, 0x0201 }, // Pelican PL-3601 'TSZ' Wired Xbox 360 Controller
{ 0x0e6f, 0x0213 }, // Afterglow Gamepad for Xbox 360
{ 0x0e6f, 0x021f }, // Rock Candy Gamepad for Xbox 360
{ 0x0e6f, 0x0301 }, // Logic3 Controller
{ 0x0e6f, 0x0401 }, // Logic3 Controller
{ 0x0e6f, 0x0413 }, // Afterglow AX.1 Gamepad for Xbox 360
{ 0x0e6f, 0x0501 }, // PDP Xbox 360 Controller
{ 0x0e6f, 0xf900 }, // PDP Afterglow AX.1
{ 0x0f0d, 0x000a }, // Hori Co. DOA4 FightStick
{ 0x0f0d, 0x000c }, // Hori PadEX Turbo
{ 0x1038, 0x1430 }, // SteelSeries Stratus Duo
{ 0x1038, 0x1431 }, // SteelSeries Stratus Duo
{ 0x11c9, 0x55f0 }, // Nacon GC-100XF
{ 0x1209, 0x2882 }, // Ardwiino Controller
{ 0x12ab, 0x0301 }, // PDP AFTERGLOW AX.1
{ 0x1430, 0x4748 }, // RedOctane Guitar Hero X-plorer
{ 0x1430, 0xf801 }, // RedOctane Controller
{ 0x146b, 0x0601 }, // BigBen Interactive XBOX 360 Controller
{ 0x1532, 0x0037 }, // Razer Sabertooth
{ 0x15e4, 0x3f00 }, // Power A Mini Pro Elite
{ 0x15e4, 0x3f0a }, // Xbox Airflo wired controller
{ 0x15e4, 0x3f10 }, // Batarang Xbox 360 controller
{ 0x162e, 0xbeef }, // Joytech Neo-Se Take2
{ 0x1689, 0xfd00 }, // Razer Onza Tournament Edition
{ 0x1689, 0xfd01 }, // Razer Onza Classic Edition
{ 0x1689, 0xfe00 }, // Razer Sabertooth
{ 0x1949, 0x041a }, // Amazon Game Controller
{ 0x1bad, 0x0002 }, // Harmonix Rock Band Guitar
{ 0x1bad, 0xf016 }, // Mad Catz Xbox 360 Controller
{ 0x1bad, 0xf021 }, // Mad Cats Ghost Recon FS GamePad
{ 0x1bad, 0xf023 }, // MLG Pro Circuit Controller (Xbox)
{ 0x1bad, 0xf025 }, // Mad Catz Call Of Duty
{ 0x1bad, 0xf027 }, // Mad Catz FPS Pro
{ 0x1bad, 0xf028 }, // Street Fighter IV FightPad
{ 0x1bad, 0xf030 }, // Mad Catz Xbox 360 MC2 MicroCon Racing Wheel
{ 0x1bad, 0xf036 }, // Mad Catz MicroCon GamePad Pro
{ 0x1bad, 0xf038 }, // Street Fighter IV FightStick TE
{ 0x1bad, 0xf501 }, // HoriPad EX2 Turbo
{ 0x1bad, 0xf506 }, // Hori Real Arcade Pro.EX Premium VLX
{ 0x1bad, 0xf900 }, // Harmonix Xbox 360 Controller
{ 0x1bad, 0xf901 }, // Gamestop Xbox 360 Controller
{ 0x1bad, 0xf903 }, // Tron Xbox 360 controller
{ 0x1bad, 0xf904 }, // PDP Versus Fighting Pad
{ 0x1bad, 0xfa01 }, // MadCatz GamePad
{ 0x1bad, 0xfd00 }, // Razer Onza TE
{ 0x1bad, 0xfd01 }, // Razer Onza
{ 0x20d6, 0x2001 }, // BDA Xbox Series X Wired Controller
{ 0x20d6, 0x281f }, // PowerA Wired Controller For Xbox 360
{ 0x24c6, 0x5300 }, // PowerA MINI PROEX Controller
{ 0x24c6, 0x5303 }, // Xbox Airflo wired controller
{ 0x24c6, 0x530a }, // Xbox 360 Pro EX Controller
{ 0x24c6, 0x531a }, // PowerA Pro Ex
{ 0x24c6, 0x5397 }, // FUS1ON Tournament Controller
{ 0x24c6, 0x5500 }, // Hori XBOX 360 EX 2 with Turbo
{ 0x24c6, 0x5501 }, // Hori Real Arcade Pro VX-SA
{ 0x24c6, 0x5506 }, // Hori SOULCALIBUR V Stick
{ 0x24c6, 0x550d }, // Hori GEM Xbox controller
{ 0x24c6, 0x5b00 }, // ThrustMaster Ferrari 458 Racing Wheel
{ 0x24c6, 0x5b02 }, // Thrustmaster, Inc. GPX Controller
{ 0x24c6, 0x5b03 }, // Thrustmaster Ferrari 458 Racing Wheel
{ 0x24c6, 0x5d04 }, // Razer Sabertooth
{ 0x24c6, 0xfafe }, // Rock Candy Gamepad for Xbox 360
{ 0x2563, 0x058d }, // OneXPlayer Gamepad
{ 0x2dc8, 0x3106 }, // 8BitDo Ultimate Wireless / Pro 2 Wired Controller
{ 0x2dc8, 0x3109 }, // 8BitDo Ultimate Wireless Bluetooth
{ 0x31e3, 0x1100 }, // Wooting One
{ 0x31e3, 0x1200 }, // Wooting Two
{ 0x31e3, 0x1210 }, // Wooting Lekker
{ 0x31e3, 0x1220 }, // Wooting Two HE
{ 0x31e3, 0x1230 }, // Wooting Two HE (ARM)
{ 0x31e3, 0x1300 }, // Wooting 60HE (AVR)
{ 0x31e3, 0x1310 }, // Wooting 60HE (ARM)
{ 0x3285, 0x0607 }, // Nacon GC-100
{ 0x413d, 0x2104 }, // Black Shark Green Ghost Gamepad
{ 0x0000, 0x0000 } // end of list
};
CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_VEND_SPECIFIC,
.subclass = 0x5d,
.protocol = 0x01,
.id_table = xbox_id_table,
.class_driver = &xbox_class_driver
};
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024, Till Harbaum
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_XBOX_H
#define USBH_XBOX_H
struct usbh_xbox {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t intf; /* interface number */
uint8_t minor;
};
#ifdef __cplusplus
extern "C" {
#endif
void usbh_xbox_run(struct usbh_xbox *xbox_class);
void usbh_xbox_stop(struct usbh_xbox *xbox_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_XBOX_H */
@@ -24,6 +24,8 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
(void)busid;
switch (control_selector) {
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
switch (setup->bRequest) {
@@ -495,20 +495,26 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_video_run(struct usbh_video *video_class)
{
(void)video_class;
}
__WEAK void usbh_video_stop(struct usbh_video *video_class)
{
(void)video_class;
}
const struct usbh_class_driver video_ctrl_class_driver = {
@@ -102,6 +102,8 @@ static void rndis_notify_rsp(void)
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
(void)busid;
switch (setup->bRequest) {
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
rndis_encapsulated_cmd_handler(*data, setup->wLength);
@@ -152,6 +154,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
rndis_initialize_cmplt_t *resp;
(void)len;
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
@@ -177,6 +181,9 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
{
rndis_halt_msg_t *resp;
(void)data;
(void)len;
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
resp->MessageLength = 0;
@@ -192,6 +199,8 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
uint8_t *infomation_buffer;
uint32_t infomation_len = 0;
(void)len;
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
resp->RequestId = cmd->RequestId;
@@ -338,6 +347,8 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
rndis_set_cmplt_t *resp;
rndis_config_parameter_t *param;
(void)len;
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
@@ -394,6 +405,9 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
rndis_reset_cmplt_t *resp;
(void)data;
(void)len;
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
@@ -412,6 +426,8 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
rndis_keepalive_cmplt_t *resp;
(void)len;
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
@@ -425,6 +441,9 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)busid;
(void)arg;
switch (event) {
case USBD_EVENT_RESET:
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
@@ -445,6 +464,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
rndis_data_packet_t *hdr;
(void)busid;
(void)ep;
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
@@ -461,7 +483,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
(void)busid;
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
@@ -471,6 +495,10 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
(void)ep;
(void)nbytes;
//USB_LOG_DBG("len:%d\r\n", nbytes);
}
@@ -365,14 +365,18 @@ delete :
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
{
(void)data;
(void)len;
}
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
(void)bluetooth_class;
}
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
(void)bluetooth_class;
}
static const struct usbh_class_driver bluetooth_class_driver = {
@@ -26,6 +26,7 @@ static struct usbh_rndis g_rndis_class;
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
// int ret;
// struct usbh_urb *urb = &rndis_class->intin_urb;
@@ -460,6 +461,8 @@ void usbh_rndis_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create rndis rx thread\r\n");
// clang-format off
find_class:
@@ -531,7 +534,7 @@ find_class:
#else
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
@@ -581,10 +584,12 @@ int usbh_rndis_eth_output(uint32_t buflen)
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
}
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
}
static const struct usbh_class_driver rndis_class_driver = {
@@ -33,6 +33,13 @@ int usb_dc_deinit(uint8_t busid);
*/
int usbd_set_address(uint8_t busid, const uint8_t addr);
/**
* @brief Set remote wakeup feature
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_set_remote_wakeup(uint8_t busid);
/**
* @brief Get USB device speed
*
@@ -614,7 +614,7 @@ struct usb_webusb_url_descriptor {
char URL[];
} __PACKED;
struct usb_webusb_url_ex_descriptor {
struct usb_webusb_descriptor {
uint8_t vendor_code;
const uint8_t *string;
uint32_t string_len;
@@ -82,4 +82,31 @@ void usb_assert(const char *filename, int linenum);
usb_assert(__FILE__, __LINE__); \
} while (0)
#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
{
unsigned char *buf = (unsigned char *)ptr;
uint32_t i, j;
for (i = 0; i < buflen; i += 16) {
CONFIG_USB_PRINTF("%08X:", i);
for (j = 0; j < 16; j++)
if (i + j < buflen) {
if ((j % 8) == 0) {
CONFIG_USB_PRINTF(" ");
}
CONFIG_USB_PRINTF("%02X ", buf[i + j]);
} else
CONFIG_USB_PRINTF(" ");
CONFIG_USB_PRINTF(" ");
for (j = 0; j < 16; j++)
if (i + j < buflen)
CONFIG_USB_PRINTF("%c", ___is_print(buf[i + j]) ? buf[i + j] : '.');
CONFIG_USB_PRINTF("\n");
}
}
#endif /* USB_LOG_H */
@@ -58,4 +58,7 @@ void usb_osal_leave_critical_section(size_t flag);
void usb_osal_msleep(uint32_t delay);
void *usb_osal_malloc(size_t size);
void usb_osal_free(void *ptr);
#endif /* USB_OSAL_H */
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_VERSION_H
#define USB_VERSION_H
#ifdef CHERRYUSB_VERSION
#warning "Please do not define CHERRYUSB_VERSION in usb_config.h"
#undef CHERRYUSB_VERSION
#endif
#ifdef CHERRYUSB_VERSION_STR
#warning "Please do not define CHERRYUSB_VERSION_STR in usb_config.h"
#undef CHERRYUSB_VERSION_STR
#endif
#define CHERRYUSB_VERSION 0x010400
#define CHERRYUSB_VERSION_STR "v1.4.0"
#endif
@@ -45,12 +45,18 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
struct usb_msosv1_descriptor *msosv1_desc;
struct usb_msosv2_descriptor *msosv2_desc;
struct usb_bos_descriptor *bos_desc;
struct usb_webusb_descriptor *webusb_url_desc;
#endif
/* Buffer used for storing standard, class and vendor request data */
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
/** Currently selected configuration */
uint8_t configuration;
uint8_t device_address;
bool self_powered;
bool remote_wakeup_support;
bool remote_wakeup_enabled;
bool is_suspend;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
uint8_t speed;
#endif
@@ -174,6 +180,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
break;
}
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
g_usbd_core[busid].self_powered = (desc[7] & USB_CONFIG_POWERED_MASK) ? true : false;
g_usbd_core[busid].remote_wakeup_support = (desc[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
break;
case USB_DESCRIPTOR_TYPE_STRING:
if (index == USB_OSDESC_STRING_DESC_INDEX) {
@@ -336,6 +345,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
*/
*len = (p[CONF_DESC_wTotalLength]) |
(p[CONF_DESC_wTotalLength + 1] << 8);
g_usbd_core[busid].self_powered = (p[7] & USB_CONFIG_POWERED_MASK) ? true : false;
g_usbd_core[busid].remote_wakeup_support = (p[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
} else {
/* normally length is at offset 0 */
*len = p[DESC_bLength];
@@ -522,6 +534,12 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
/* bit 0: self-powered */
/* bit 1: remote wakeup */
(*data)[0] = 0x00;
if (g_usbd_core[busid].self_powered) {
(*data)[0] |= USB_GETSTATUS_SELF_POWERED;
}
if (g_usbd_core[busid].remote_wakeup_enabled) {
(*data)[0] |= USB_GETSTATUS_REMOTE_WAKEUP;
}
(*data)[1] = 0x00;
*len = 2;
break;
@@ -530,8 +548,10 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
case USB_REQUEST_SET_FEATURE:
if (value == USB_FEATURE_REMOTE_WAKEUP) {
if (setup->bRequest == USB_REQUEST_SET_FEATURE) {
g_usbd_core[busid].remote_wakeup_enabled = true;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SET_REMOTE_WAKEUP);
} else {
g_usbd_core[busid].remote_wakeup_enabled = false;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CLR_REMOTE_WAKEUP);
}
} else if (value == USB_FEATURE_TEST_MODE) {
@@ -543,6 +563,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
break;
case USB_REQUEST_SET_ADDRESS:
g_usbd_core[busid].device_address = value;
usbd_set_address(busid, value);
*len = 0;
break;
@@ -556,17 +577,20 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
break;
case USB_REQUEST_GET_CONFIGURATION:
*data = (uint8_t *)&g_usbd_core[busid].configuration;
(*data)[0] = g_usbd_core[busid].configuration;
*len = 1;
break;
case USB_REQUEST_SET_CONFIGURATION:
value &= 0xFF;
if (!usbd_set_configuration(busid, value, 0)) {
if (value == 0) {
g_usbd_core[busid].configuration = 0;
} else if (!usbd_set_configuration(busid, value, 0)) {
ret = false;
} else {
g_usbd_core[busid].configuration = value;
g_usbd_core[busid].is_suspend = false;
usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CONFIGURED);
}
@@ -600,6 +624,16 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
uint8_t type = HI_BYTE(setup->wValue);
uint8_t intf_num = LO_BYTE(setup->wIndex);
bool ret = true;
const uint8_t *p;
uint32_t desc_len = 0;
uint32_t current_desc_len = 0;
uint8_t cur_iface = 0xFF;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed);
#else
p = (uint8_t *)g_usbd_core[busid].descriptors;
#endif
/* Only when device is configured, then interface requests can be valid. */
if (!is_device_configured(busid)) {
@@ -614,7 +648,39 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
break;
case USB_REQUEST_GET_DESCRIPTOR:
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
if (type == 0x21) { /* HID_DESCRIPTOR_TYPE_HID */
while (p[DESC_bLength] != 0U) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
current_desc_len = 0;
desc_len = (p[CONF_DESC_wTotalLength]) |
(p[CONF_DESC_wTotalLength + 1] << 8);
break;
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
break;
case 0x21:
if (cur_iface == intf_num) {
*data = (uint8_t *)p;
//memcpy(*data, p, p[DESC_bLength]);
*len = p[DESC_bLength];
return true;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
current_desc_len += p[DESC_bLength];
if (current_desc_len >= desc_len && desc_len) {
break;
}
}
} else if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
@@ -663,6 +729,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
{
uint8_t ep = (uint8_t)setup->wIndex;
bool ret = true;
uint8_t stalled;
/* Only when device is configured, then endpoint requests can be valid. */
if (!is_device_configured(busid)) {
@@ -671,7 +738,12 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
switch (setup->bRequest) {
case USB_REQUEST_GET_STATUS:
usbd_ep_is_stalled(busid, ep, &stalled);
if (stalled) {
(*data)[0] = 0x01;
} else {
(*data)[0] = 0x00;
}
(*data)[1] = 0x00;
*len = 2;
break;
@@ -841,10 +913,12 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
return -1;
}
}
} else if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
}
if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
if (setup->bRequest == g_usbd_core[busid].descriptors->webusb_url_descriptor->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
case WEBUSB_REQUEST_GET_URL:
desclen = g_usbd_core[busid].descriptors->webusb_url_descriptor->string_len;
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
//memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen);
@@ -897,6 +971,22 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
}
}
}
if (g_usbd_core[busid].webusb_url_desc) {
if (setup->bRequest == g_usbd_core[busid].webusb_url_desc->vendor_code) {
switch (setup->wIndex) {
case WEBUSB_REQUEST_GET_URL:
desclen = g_usbd_core[busid].webusb_url_desc->string_len;
*data = (uint8_t *)g_usbd_core[busid].webusb_url_desc->string;
//memcpy(*data, g_usbd_core[busid].webusb_url_desc->string, desclen);
*len = desclen;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
return -1;
}
}
}
#endif
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
@@ -985,17 +1075,22 @@ void usbd_event_disconnect_handler(uint8_t busid)
void usbd_event_resume_handler(uint8_t busid)
{
g_usbd_core[busid].is_suspend = false;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESUME);
}
void usbd_event_suspend_handler(uint8_t busid)
{
if (g_usbd_core[busid].device_address > 0) {
g_usbd_core[busid].is_suspend = true;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
}
}
void usbd_event_reset_handler(uint8_t busid)
{
usbd_set_address(busid, 0);
g_usbd_core[busid].device_address = 0;
g_usbd_core[busid].configuration = 0;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
@@ -1091,6 +1186,8 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
(void)ep;
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
@@ -1130,6 +1227,8 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
(void)ep;
if (nbytes > 0) {
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
@@ -1213,6 +1312,11 @@ void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc)
{
g_usbd_core[busid].bos_desc = desc;
}
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc)
{
g_usbd_core[busid].webusb_url_desc = desc;
}
#endif
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
@@ -1256,7 +1360,30 @@ bool usb_device_is_configured(uint8_t busid)
return g_usbd_core[busid].configuration;
}
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
bool usb_device_is_suspend(uint8_t busid)
{
return g_usbd_core[busid].is_suspend;
}
int usbd_send_remote_wakeup(uint8_t busid)
{
if (g_usbd_core[busid].remote_wakeup_support && g_usbd_core[busid].remote_wakeup_enabled && g_usbd_core[busid].is_suspend) {
return usbd_set_remote_wakeup(busid);
} else {
if (!g_usbd_core[busid].remote_wakeup_support) {
USB_LOG_ERR("device does not support remote wakeup\r\n");
}
if (!g_usbd_core[busid].remote_wakeup_enabled) {
USB_LOG_ERR("device remote wakeup is not enabled\r\n");
}
if (!g_usbd_core[busid].is_suspend) {
USB_LOG_ERR("device is not in suspend state\r\n");
}
return -1;
}
}
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
{
int ret;
struct usbd_bus *bus;
@@ -1279,9 +1406,9 @@ int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint
int usbd_deinitialize(uint8_t busid)
{
g_usbd_core[busid].intf_offset = 0;
usb_dc_deinit(busid);
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
usb_dc_deinit(busid);
g_usbd_core[busid].intf_offset = 0;
return 0;
}

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