1 Commits

Author SHA1 Message Date
CCHhui
d0fac3260a fix(core/usbh_core): Fix raw_config_desc heap out of bounds 2024-09-16 23:11:45 +08:00
181 changed files with 1217 additions and 5597 deletions

View File

@@ -1,85 +0,0 @@
name: "🐞 上报bug / Bug report"
description: "提交bug以让改进软件功能 / Create a report to help us improve"
labels: ["peding"]
body:
- type: markdown
attributes:
value: |
感谢上报新的问题请填写以下信息以帮助我们更好地理解问题。请注意如果您不按模板填写issue那您的issue可能会被关闭或者删除
我们的工作语言是中文或者英文请使用这两种语言之一填写issue。
Thank you for reporting a new issue! Please fill in the following information to help us better understand the problem. Please note that if you do not fill in the issue according to the template, your issue may be closed or deleted!
Our working languages are Chinese or English, please use one of these two languages to fill in the issue.
- type: textarea
id: bug-description
attributes:
label: 描述一下这个bug / Describe the bug
description: 请使用简介并详细的语句来描述这个bug。 / A clear and concise description of what the bug is.
placeholder: 我准备……我想要……但是实际上它……了 / I am doing ... What I expect is ... What actually happening is ...
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: 复现步骤 / To Reproduce
description: 按照下面的步骤可以复现bug / Steps to reproduce the behavior
placeholder: 首先……然后……接着…… / Go to '...', Click on '....', Scroll down to '....'
validations:
required: true
- type: textarea
id: target
attributes:
label: 设备信息 / Target Device
description: 您使用的板子/芯片型号、使用的引脚、以及USB IP类型 / Your target board/chip model, the pins you used, and the type of USB IP you used
placeholder: |-
板子型号HPM5301EVKLite
引脚PA24 PA25
USB IP/
validations:
required: true
- type: textarea
id: log
attributes:
label: 日志 / Log
description: 请提供输出 log
placeholder: |-
[D/USB] EP0 send 18 bytes, 0 remained
[D/USB] EP0 recv out status
[D/USB] EP0 send 0 bytes, 0 remained
[D/USB] EP0 send 18 bytes, 0 remained
[D/USB] EP0 recv out status
validations:
required: true
- type: markdown
attributes:
value: |
以下的部分仅在移植的时候需要填写,如果不是移植问题,请忽略这部分。
The following section is only required when porting, if it is not a porting issue, please ignore this section.
- type: textarea
id: configure
attributes:
label: 配置 / Configuration
description: 请确认 USB 中断,时钟,引脚,寄存器地址是否正确,并截图 / Please confirm that the USB interrupt, clock, pin, and register address are correct, and provide a screenshot
- type: textarea
id: USBIrq
attributes:
label: USB中断 / USB Interrupt
description: 请确认是否能进入USB中断
- type: textarea
id: cache
attributes:
label: 缓存 / Cache
description: 芯片是否带有 cache功能是否做了 no cache 处理,并截图 / Whether the chip has a cache function, whether no cache processing is done, and provide a screenshot
- type: checkboxes
id: bussiness
attributes:
label: 商业 / Business
description: 是否流片并销售 / Whether it is mass-produced and sold
options:
- label: 是 / Yes

View File

@@ -1,17 +0,0 @@
name: Cppcheck action
on:
push:
pull_request:
jobs:
build:
name: cppcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: cppcheck
shell: bash
run: |
sudo apt install cppcheck
cppcheck --enable=warning,portability,performance --language=c --platform=unix32 --std=c99 --force . -i third_party/ -i class/template -i port/template/

View File

@@ -1,28 +0,0 @@
name: Deploy docs
on:
push:
branches:
- master
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: ammaraskar/sphinx-action@8.0.2
with:
docs-folder: "docs/"
- uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: docs/build/html

View File

@@ -2,10 +2,9 @@ cmake_minimum_required(VERSION 3.15)
if(BL_SDK_BASE)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC_ACM 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
set(CONFIG_CHERRYUSB_DEVICE_DCD "bl")
@@ -77,14 +76,10 @@ set(ldfragments "osal/idf/linker.lf")
if(CONFIG_CHERRYUSB_HOST_CDC_ECM OR CONFIG_CHERRYUSB_HOST_CDC_RNDIS OR CONFIG_CHERRYUSB_HOST_CDC_NCM
OR CONFIG_CHERRYUSB_HOST_ASIX OR CONFIG_CHERRYUSB_HOST_RTL8152 OR CONFIG_CHERRYUSB_HOST_BL616)
list(APPEND cherryusb_srcs platform/none/usbh_lwip.c)
idf_component_get_property(lwip lwip COMPONENT_LIB)
target_compile_definitions(${lwip} PRIVATE "-DPBUF_POOL_BUFSIZE=1600")
endif()
idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH)
idf_component_register(SRCS ${cherryusb_srcs}
INCLUDE_DIRS ${cherryusb_incs} ${freertos_include}
INCLUDE_DIRS ${cherryusb_incs}
PRIV_REQUIRES usb
LDFRAGMENTS ${ldfragments}
)

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

21
Kconfig
View File

@@ -38,8 +38,6 @@ if CHERRYUSB
bool "dwc2_gd"
config CHERRYUSB_DEVICE_DWC2_HC
bool "dwc2_hc"
config CHERRYUSB_DEVICE_DWC2_KENDRYTE
bool "dwc2_kendryte"
config CHERRYUSB_DEVICE_DWC2_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_DEVICE_MUSB_ES
@@ -50,12 +48,6 @@ if CHERRYUSB
bool "musb_bk"
config CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_DEVICE_KINETIS_MCX
bool "kinetis_mcx"
config CHERRYUSB_DEVICE_KINETIS_MM32
bool "kinetis_mm32"
config CHERRYUSB_DEVICE_KINETIS_CUSTOM
bool "kinetis_custom"
config CHERRYUSB_DEVICE_CHIPIDEA_MCX
bool "chipidea_mcx"
config CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
@@ -193,8 +185,6 @@ if CHERRYUSB
bool "dwc2_esp"
config CHERRYUSB_HOST_DWC2_HC
bool "dwc2_hc"
config CHERRYUSB_HOST_DWC2_KENDRYTE
bool "dwc2_kendryte"
config CHERRYUSB_HOST_DWC2_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_HOST_MUSB_ES
@@ -211,12 +201,6 @@ if CHERRYUSB
bool "xhci_phytium"
config CHERRYUSB_HOST_XHCI_CUSTOM
bool "xhci"
config CHERRYUSB_HOST_KINETIS_MCX
bool "kinetis_mcx"
config CHERRYUSB_HOST_KINETIS_MM32
bool "kinetis_mm32"
config CHERRYUSB_HOST_KINETIS_CUSTOM
bool "kinetis_custom"
endchoice
config CHERRYUSB_HOST_CDC_ACM
@@ -299,11 +283,6 @@ if CHERRYUSB
prompt "Enable usb pl2303 driver"
default n
config CHERRYUSB_HOST_AOA
bool
prompt "Enable usb aoa driver"
default n
config USBHOST_PLATFORM_CDC_ECM
bool

View File

@@ -1,16 +1,6 @@
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
<p align="center">
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
</p>
# CherryUSB
<p align="center">
<a href="./README_zh.md">中文</a>
|
<a href="./README.md">English</a>
</p>
[中文版](./README_zh.md)
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
@@ -32,7 +22,7 @@ In order to make it easier for users to learn USB basics, enumeration, driver lo
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
- Equivalent to using uart tx dma/uart rx dma
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does it)
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does the packetization process)
### Easy to bring out USB performance
@@ -42,7 +32,7 @@ Taking into account USB performance issues and trying to achieve the theoretical
- Memory zero copy
- If IP has DMA then uses DMA mode (DMA with hardware packetization)
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
- Packetization is handled in interrupt
- Subcontracting function is handled in interrupt
## Directory Structure
@@ -85,13 +75,13 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | ~4400 | 512(default) + 320 | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~2600 | 0 | 84 | 0 |
|usbd_rndis.c | ~2100 | 2 * 1580(default)+156+8 | 76 | 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 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host Stack Overview
@@ -113,7 +103,6 @@ CherryUSB Host Stack has the following functions
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
- Support Vendor class (serial, net, wifi)
- Support USB modeswitch
- Support Android Open Accessory
- Support multi host with the same USB IP
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
@@ -122,17 +111,16 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~9000 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~6000 | 32 + 4 * (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~900 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2700 | 64 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 256 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3800 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~4200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3300 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_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 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros
@@ -160,7 +148,7 @@ Only standard and commercial USB IP are listed.
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | |
| OHCI(intel) | none | OHCI | × |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| UHCI(intel) | none | UHCI | × |
@@ -196,8 +184,7 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|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/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|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 |
@@ -224,4 +211,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
Thanks to the following companies for their support (in no particular order).
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" />

View File

@@ -1,16 +1,6 @@
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
<p align="center">
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
</p>
# CherryUSB
<p align="center">
<a href="./README_zh.md">中文</a>
|
<a href="./README.md">English</a>
</p>
[English](./README.md)
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
@@ -32,7 +22,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma因此设计的数据收发类接口具备以下优点
- 等价于使用 uart tx dma/uart rx dma
- 收发长度没有限制,用户不需要关心 USB 分包过程(分包过程在 porting 中处理
- 收发长度没有限制,用户不需要关心 USB 分包过程porting 驱动做分包过程
### 易于发挥 USB 性能
@@ -42,7 +32,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
- Memory zero copy
- IP 如果带 DMA 则使用 DMA 模式DMA 带硬件分包功能)
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
- 分包过程在中断中执行
- 分包功能在中断中处理
## 目录结构
@@ -85,13 +75,13 @@ CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | ~4400 | 512(default) + 320 | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~2600 | 0 | 84 | 0 |
|usbd_rndis.c | ~2100 | 2 * 1580(default)+156+8 | 76 | 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 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host 协议栈简介
@@ -113,7 +103,6 @@ CherryUSB Host 协议栈当前实现以下功能:
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
- 支持 Vendor 类 class (serial, net, wifi)
- 支持 USB modeswitch
- 支持 Android Open Accessory
- 支持相同 USB IP 的多主机
同时CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
@@ -122,17 +111,16 @@ CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~9000 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~6000 | 32 + 4 * (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~900 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2700 | 64 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 256 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3800 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~4200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3300 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_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 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:
@@ -160,7 +148,7 @@ x 受以下宏影响:
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | |
| OHCI(intel) | none | OHCI | × |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| UHCI(intel) | none | UHCI | × |
@@ -197,8 +185,7 @@ CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和
|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/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|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 |
@@ -226,4 +213,4 @@ CherryUSB 微信群:与我联系后邀请加入
感谢以下企业支持(顺序不分先后)。
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" />

View File

@@ -45,9 +45,6 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_HC']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_hc.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_KENDRYTE']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_kendryte.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_ES']):
@@ -61,11 +58,6 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
src += Glob('port/musb/usb_dc_musb.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_MCX']):
src += Glob('port/kinetis/usb_dc_kinetis.c')
src += Glob('port/kinetis/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_CUSTOM']):
src += Glob('port/kinetis/usb_dc_kinetis.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
src += Glob('port/chipidea/usb_dc_chipidea.c')
src += Glob('port/chipidea/usb_glue_mcx.c')
@@ -180,9 +172,6 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ESP']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
src += Glob('port/dwc2/usb_glue_esp.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_KENDRYTE']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
src += Glob('port/dwc2/usb_glue_kendryte.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_CUSTOM']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_STANDARD']):
@@ -198,11 +187,6 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_MCX']):
src += Glob('port/kinetis/usb_hc_kinetis.c')
src += Glob('port/kinetis/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_CUSTOM']):
src += Glob('port/kinetis/usb_hc_kinetis.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/rt-thread']
src += Glob('port/pusb2/rt-thread/usb_hc_glue_phytium.c')

View File

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

View File

@@ -40,7 +40,6 @@ ${CMAKE_CURRENT_LIST_DIR}/class/adb
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
${CMAKE_CURRENT_LIST_DIR}/class/aoa
)
if(CONFIG_CHERRYUSB_DEVICE)
@@ -106,9 +105,6 @@ if(CONFIG_CHERRYUSB_DEVICE)
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 "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_dc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/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")
@@ -219,9 +215,6 @@ if(CONFIG_CHERRYUSB_HOST)
if(CONFIG_CHERRYUSB_HOST_BL616)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
endif()
if(CONFIG_CHERRYUSB_HOST_AOA)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c)
endif()
if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
@@ -267,9 +260,6 @@ if(CONFIG_CHERRYUSB_HOST)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb_bk")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
endif()
endif()
@@ -298,9 +288,4 @@ endif()
if(CONFIG_CHERRYMP)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c)
endif()
endif()

View File

@@ -208,9 +208,6 @@
#define CONFIG_USBDEV_EP_NUM 8
#endif
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */
// #define CONFIG_USB_HS
/* ---------------- FSDEV Configuration ---------------- */
//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
@@ -221,7 +218,7 @@
// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
/* IN Endpoints Max packet Size / 4 */
// #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4)
// #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
@@ -230,8 +227,6 @@
// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_DMA_ENABLE
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI

View File

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

View File

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

View File

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

View File

@@ -132,11 +132,11 @@
#define AUDIO_FORMAT_ALAW 0x0004
#define AUDIO_FORMAT_MULAW 0x0005
#define AUDIO_V2_FORMAT_PCM 0x00000001
#define AUDIO_V2_FORMAT_PCM8 0x00000002
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
#define AUDIO_V2_FORMAT_ALAW 0x00000008
#define AUDIO_V2_FORMAT_MULAW 0x00000010
#define AUDIO_V2_FORMAT_PCM 0x00000001
#define AUDIO_V2_FORMAT_PCM8 0x00000002
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
#define AUDIO_V2_FORMAT_ALAW 0x00000008
#define AUDIO_V2_FORMAT_MULAW 0x00000010
/* bmChannelConfig: a bitmap field that indicates which spatial locations
* are occupied by the channels present in the cluster. The bit allocations
@@ -648,18 +648,6 @@ struct audio_cs_if_ac_feature_unit_descriptor {
#define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n)
struct audio_cs_if_ac_selector_unit_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bUnitID;
uint8_t bNrInPins;
uint8_t baSourceID[1];
uint8_t iSelector;
} __PACKED;
#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n)
struct audio_cs_if_as_general_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -824,60 +812,6 @@ struct audio_cs_ep_ep_general_descriptor {
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
bAlternateSetting, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
0x01, /* bDelay */ \
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bNrChannels, /* bNrChannels */ \
bSubFrameSize, /* bSubFrameSize : Bytes per audio subframe */ \
bBitResolution, /* bBitResolution : bits per sample */ \
(PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
__VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
bInterval, /* bInterval : one packet per frame */ \
0x00, /* bRefresh */ \
0x00, /* bSynchAddress */ \
0x07, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00 /* iInterface */
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -1162,58 +1096,6 @@ struct audio_v2_control_range3_param_block {
0x00, /* wLockDelay */ \
0x00
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
bAlternateSetting, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x10, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output or Input Terminal*/ \
0x00, /* bmControls */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType : AUDIO_FORMAT_TYPE_I */ \
DBVAL(AUDIO_V2_FORMAT_PCM), /* bmFormats PCM */ \
bNrChannels, /* bNrChannels */ \
DBVAL(bmChannelConfig), /* bmChannelConfig */ \
0x00, /* iChannelNames */ \
0x06, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bSubslotSize, /* bSubslotSize */ \
bBitResolution, /* bBitResolution */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
bInterval, /* bInterval */ \
0x08, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
0x00, /* bmAttributes */ \
0x00, /* bmControls */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00
#define AUDIO_V2_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00 /* iInterface */
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -1268,13 +1150,12 @@ struct audio_v2_control_range3_param_block {
bFeedbackEndpointAddress, /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */ \
0x11, /* bmAttributes: TransferType=Isochronous SyncType=None EndpointType=Feedback */ \
WBVAL(4), /* XXXX wMaxPacketSize in Bytes */ \
bInterval /* bInterval */
bInterval /* bInterval */ \
// clang-format on
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT_LEN (0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
#define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
#define AUDIO_SAMPLE_FREQ_3B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

View File

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

View File

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

View File

@@ -21,6 +21,10 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
@@ -28,11 +32,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_audio *usbh_audio_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
g_audio_class[devno].minor = devno;
return &g_audio_class[devno];
@@ -43,15 +47,15 @@ static struct usbh_audio *usbh_audio_class_alloc(void)
static void usbh_audio_class_free(struct usbh_audio *audio_class)
{
uint8_t devno = audio_class->minor;
int devno = audio_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
}
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution)
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
{
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
@@ -70,24 +74,20 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
return 0;
}
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
intf = audio_class->as_msg_table[i].stream_intf;
for (uint8_t j = 1; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
if (audio_class->as_msg_table[i].as_format[j].bBitResolution == bitresolution) {
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
uint32_t freq = 0;
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
if (freq == samp_freq) {
altsetting = j;
goto freq_found;
}
for (uint8_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
if (audio_class->module[i].altsetting[j].sampfreq[k] == samp_freq) {
intf = audio_class->module[i].data_intf;
altsetting = j;
goto freq_found;
}
}
}
}
}
return -USB_ERR_NODEV;
freq_found:
@@ -105,18 +105,16 @@ freq_found:
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].ep_attr & AUDIO_EP_CONTROL_SAMPLING_FEQ) {
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
setup->wIndex = ep_desc->bEndpointAddress;
setup->wLength = 3;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
setup->wIndex = ep_desc->bEndpointAddress;
setup->wLength = 3;
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
@@ -129,7 +127,7 @@ freq_found:
USBH_EP_INIT(audio_class->isoout, ep_desc);
}
USB_LOG_INFO("Open audio stream :%s, altsetting: %u\r\n", name, altsetting);
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
audio_class->is_opened = true;
return ret;
}
@@ -147,9 +145,9 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
intf = audio_class->as_msg_table[i].stream_intf;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->module[i].data_intf;
}
}
@@ -157,17 +155,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = 0;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Close audio stream :%s\r\n", name);
USB_LOG_INFO("Close audio module :%s\r\n", name);
audio_class->is_opened = false;
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
@@ -181,128 +169,52 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
}
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = 0;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db)
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
{
struct usb_setup_packet *setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
uint8_t intf;
uint16_t volume_hex;
int volume_min_db;
int volume_max_db;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
if ((volume_db > 127) || (volume_db < -127)) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
intf = audio_class->as_msg_table[i].stream_intf;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (feature_id == 0xff) {
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_MIN;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_MAX;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_RES;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 2;
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
} else {
volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256;
}
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) {
volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256;
} else {
volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256;
}
USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db);
if (volume_db >= 0) {
volume_hex = volume_db * 256;
if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) {
return -USB_ERR_RANGE;
}
} else {
volume_hex = volume_db * 256 + 0x10000;
if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) {
return -USB_ERR_RANGE;
}
}
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
memcpy(g_audio_buf, &volume_hex, 2);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
@@ -310,37 +222,34 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
{
struct usb_setup_packet *setup;
int ret;
uint8_t feature_id = 0xff;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
intf = audio_class->as_msg_table[i].stream_intf;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (feature_id == 0xff) {
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 1;
memcpy(g_audio_buf, &mute, 1);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute;
return ret;
}
@@ -348,28 +257,26 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
{
USB_LOG_INFO("============= Audio module information ===================\r\n");
USB_LOG_RAW("bcdADC :%04x\r\n", audio_class->bcdADC);
USB_LOG_RAW("Num of audio stream :%u\r\n", audio_class->stream_intf_num);
USB_LOG_RAW("Num of modules :%u\r\n", audio_class->module_num);
USB_LOG_RAW("Num of altsettings:%u\r\n", audio_class->num_of_intf_altsettings);
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
USB_LOG_RAW("\tstream name :%s\r\n", audio_class->as_msg_table[i].stream_name);
USB_LOG_RAW("\tstream intf :%u\r\n", audio_class->as_msg_table[i].stream_intf);
USB_LOG_RAW("\tNum of altsetting :%u\r\n", audio_class->as_msg_table[i].num_of_altsetting);
for (uint8_t i = 0; i < audio_class->module_num; i++) {
USB_LOG_RAW(" module name :%s\r\n", audio_class->module[i].name);
USB_LOG_RAW(" module feature unit id :%d\r\n", audio_class->module[i].feature_unit_id);
for (uint8_t j = 0; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
if (j == 0) {
USB_LOG_RAW("\t\tIngore altsetting 0\r\n");
USB_LOG_RAW(" Ingore altsetting 0\r\n");
continue;
}
USB_LOG_RAW("\t\tAltsetting :%u\r\n", j);
USB_LOG_RAW("\t\t\tbNrChannels :%u\r\n", audio_class->as_msg_table[i].as_format[j].bNrChannels);
USB_LOG_RAW("\t\t\tbBitResolution :%u\r\n", audio_class->as_msg_table[i].as_format[j].bBitResolution);
USB_LOG_RAW("\t\t\tbSamFreqType :%u\r\n", audio_class->as_msg_table[i].as_format[j].bSamFreqType);
USB_LOG_RAW(" Altsetting %u\r\n", j);
USB_LOG_RAW(" module channels :%u\r\n", audio_class->module[i].altsetting[j].channels);
//USB_LOG_RAW(" module format_type :%u\r\n",audio_class->module[i].altsetting[j].format_type);
USB_LOG_RAW(" module bitresolution :%u\r\n", audio_class->module[i].altsetting[j].bitresolution);
USB_LOG_RAW(" module sampfreq num :%u\r\n", audio_class->module[i].altsetting[j].sampfreq_num);
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
uint32_t freq = 0;
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
USB_LOG_RAW("\t\t\t\tSampleFreq :%u\r\n", freq);
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
USB_LOG_RAW(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
}
}
}
@@ -380,14 +287,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
{
int ret;
uint8_t cur_iface = 0;
uint8_t cur_iface_count = 0;
uint8_t cur_alt_setting = 0;
uint8_t cur_iface = 0xff;
uint8_t cur_iface_count = 0xff;
uint8_t cur_alt_setting = 0xff;
uint8_t input_offset = 0;
uint8_t output_offset = 0;
uint8_t feature_unit_offset = 0;
uint8_t format_offset = 0;
uint8_t *p;
struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
struct usbh_audio *audio_class = usbh_audio_class_alloc();
if (audio_class == NULL) {
@@ -397,6 +304,8 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
audio_class->hport = hport;
audio_class->ctrl_intf = intf;
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
hport->config.intf[intf].priv = audio_class;
p = hport->raw_config_desc;
@@ -422,49 +331,72 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
case AUDIO_CONTROL_INPUT_TERMINAL: {
struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p;
memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor));
audio_class->module[input_offset].input_terminal_id = desc->bTerminalID;
audio_class->module[input_offset].input_terminal_type = desc->wTerminalType;
audio_class->module[input_offset].input_channel_config = desc->wChannelConfig;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[input_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_INTERM_MIC) {
audio_class->module[input_offset].name = "mic";
}
input_offset++;
} break;
break;
case AUDIO_CONTROL_OUTPUT_TERMINAL: {
struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p;
memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor));
audio_class->module[output_offset].output_terminal_id = desc->bTerminalID;
audio_class->module[output_offset].output_terminal_type = desc->wTerminalType;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[output_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_OUTTERM_SPEAKER) {
audio_class->module[output_offset].name = "speaker";
}
output_offset++;
} break;
case AUDIO_CONTROL_FEATURE_UNIT: {
struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p;
audio_class->module[feature_unit_offset].feature_unit_id = desc->bUnitID;
audio_class->module[feature_unit_offset].feature_unit_controlsize = desc->bControlSize;
memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
for (uint8_t j = 0; j < desc->bControlSize; j++) {
audio_class->module[feature_unit_offset].feature_unit_controls[j] = p[6 + j];
}
feature_unit_offset++;
} break;
default:
USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]);
return -USB_ERR_NOTSUPP;
}
} else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL: {
struct audio_cs_if_as_general_descriptor *desc = (struct audio_cs_if_as_general_descriptor *)p;
case AUDIO_CONTROL_PROCESSING_UNIT:
/* all altsetting have the same general */
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].stream_intf = cur_iface;
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_general, desc, sizeof(struct audio_cs_if_as_general_descriptor));
} break;
case AUDIO_STREAMING_FORMAT_TYPE: {
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].num_of_altsetting = (cur_alt_setting + 1);
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, desc->bLength);
} break;
break;
default:
break;
}
}
break;
case AUDIO_ENDPOINT_DESCRIPTOR_TYPE:
if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) {
struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p;
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].ep_attr = desc->bmAttributes;
} else if ((cur_iface < (audio_class->ctrl_intf + cur_iface_count)) && (cur_iface > audio_class->ctrl_intf)) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL:
break;
case AUDIO_STREAMING_FORMAT_TYPE: {
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
audio_class->module[format_offset].data_intf = cur_iface;
audio_class->module[format_offset].altsetting[cur_alt_setting].channels = desc->bNrChannels;
audio_class->module[format_offset].altsetting[cur_alt_setting].format_type = desc->bFormatType;
audio_class->module[format_offset].altsetting[cur_alt_setting].bitresolution = desc->bBitResolution;
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq_num = desc->bSamFreqType;
for (uint8_t j = 0; j < desc->bSamFreqType; j++) {
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq[j] = (uint32_t)(p[10 + j * 3] << 16) |
(uint32_t)(p[9 + j * 3] << 8) |
(uint32_t)(p[8 + j * 3] << 0);
}
if (cur_alt_setting == (hport->config.intf[intf + 1].altsetting_num - 1)) {
format_offset++;
}
} break;
default:
break;
}
}
break;
@@ -475,98 +407,16 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
p += p[DESC_bLength];
}
if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) {
USB_LOG_ERR("Audio control descriptor is invalid\r\n");
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
return -USB_ERR_INVAL;
}
if (cur_iface_count == 0xff) {
USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n");
return -USB_ERR_INVAL;
}
audio_class->module_num = input_offset;
audio_class->stream_intf_num = input_offset;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
/* Search 0x0101 in input or output desc */
for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) {
if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) {
/* INPUT --> FEATURE UNIT --> OUTPUT */
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID;
/* Search input terminal id in feature desc */
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) {
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
/* Search feature unit id in output desc */
for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) {
if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) {
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID;
switch (ac_msg_table[outputid].ac_output.wTerminalType) {
case AUDIO_OUTTERM_SPEAKER:
audio_class->as_msg_table[i].stream_name = "speaker";
break;
case AUDIO_OUTTERM_HEADPHONES:
audio_class->as_msg_table[i].stream_name = "headphoens";
break;
case AUDIO_OUTTERM_HEADDISPLAY:
audio_class->as_msg_table[i].stream_name = "headdisplay";
break;
default:
audio_class->as_msg_table[i].stream_name = "unknown";
break;
}
break;
}
}
break;
}
}
} else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) {
/* OUTPUT --> FEATURE UNIT --> INPUT */
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID;
/* Search output terminal id in feature desc */
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) {
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
/* Search feature unit id in input desc */
for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) {
if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) {
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID;
switch (ac_msg_table[inputid].ac_input.wTerminalType) {
case AUDIO_INTERM_MIC:
audio_class->as_msg_table[i].stream_name = "mic";
break;
default:
audio_class->as_msg_table[i].stream_name = "unknown";
break;
}
break;
}
}
break;
}
}
}
}
}
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (audio_class->as_msg_table[i].stream_name == NULL) {
USB_LOG_ERR("Audio stream search fail\r\n");
return -USB_ERR_NODEV;
}
}
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name);
for (size_t i = 0; i < audio_class->module_num; i++) {
ret = usbh_audio_close(audio_class, audio_class->module[i].name);
if (ret < 0) {
USB_LOG_ERR("Fail to close audio stream :%s\r\n", audio_class->as_msg_table[i].stream_name);
USB_LOG_ERR("Fail to close audio module :%s\r\n", audio_class->module[i].name);
return ret;
}
}
@@ -642,18 +492,18 @@ const struct usbh_class_driver audio_streaming_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL,
.bInterfaceProtocol = 0x00,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &audio_ctrl_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.bInterfaceProtocol = 0x00,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &audio_streaming_class_driver
};

View File

@@ -8,31 +8,34 @@
#include "usb_audio.h"
#ifndef CONFIG_USBHOST_AUDIO_MAX_STREAMS
#define CONFIG_USBHOST_AUDIO_MAX_STREAMS 3
#endif
struct usbh_audio_ac_msg {
struct audio_cs_if_ac_input_terminal_descriptor ac_input;
struct audio_cs_if_ac_feature_unit_descriptor ac_feature_unit;
struct audio_cs_if_ac_output_terminal_descriptor ac_output;
struct usbh_audio_format_type {
uint8_t channels;
uint8_t format_type;
uint8_t bitresolution;
uint8_t sampfreq_num;
uint32_t sampfreq[3];
};
struct usbh_audio_as_msg {
const char *stream_name;
uint8_t stream_intf;
/**
* bSourceID in feature_unit = input_terminal_id
* bSourceID in output_terminal = feature_unit_id
* terminal_link_id = input_terminal_id or output_terminal_id (if input_terminal_type or output_terminal_type is 0x0101)
*
*
*/
struct usbh_audio_module {
const char *name;
uint8_t data_intf;
uint8_t input_terminal_id;
uint8_t feature_terminal_id;
uint16_t input_terminal_type;
uint16_t input_channel_config;
uint8_t output_terminal_id;
uint8_t ep_attr;
uint8_t num_of_altsetting;
uint16_t volume_min;
uint16_t volume_max;
uint16_t volume_res;
uint16_t volume_cur;
bool mute;
struct audio_cs_if_as_general_descriptor as_general;
struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
uint16_t output_terminal_type;
uint8_t feature_unit_id;
uint8_t feature_unit_controlsize;
uint8_t feature_unit_controls[8];
uint8_t terminal_link_id;
struct usbh_audio_format_type altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
};
struct usbh_audio {
@@ -47,8 +50,9 @@ struct usbh_audio {
bool is_opened;
uint16_t bcdADC;
uint8_t bInCollection;
uint8_t stream_intf_num;
struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
uint8_t num_of_intf_altsettings;
struct usbh_audio_module module[2];
uint8_t module_num;
void *user_data;
};
@@ -57,9 +61,9 @@ struct usbh_audio {
extern "C" {
#endif
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution);
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq);
int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
void usbh_audio_run(struct usbh_audio *audio_class);

View File

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

View File

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

View File

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

View File

@@ -19,11 +19,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
g_cdc_acm_class[devno].minor = devno;
return &g_cdc_acm_class[devno];
@@ -34,10 +34,10 @@ static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
{
uint8_t devno = cdc_acm_class->minor;
int devno = cdc_acm_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
}
@@ -267,18 +267,18 @@ const struct usbh_class_driver cdc_data_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
.bInterfaceProtocol = 0x00,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &cdc_acm_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = USB_DEVICE_CLASS_CDC_DATA,
.subclass = 0x00,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &cdc_data_class_driver
};

View File

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

View File

@@ -48,7 +48,7 @@ static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, s
setup->wLength = 28;
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
if (ret < 8) {
if (ret < 0) {
return ret;
}
@@ -403,9 +403,9 @@ const struct usbh_class_driver cdc_ncm_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
.bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL,
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_NETWORK_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ncm_class_driver
};

View File

@@ -20,18 +20,18 @@
#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(64, CONFIG_USB_ALIGN_SIZE)];
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;
static struct usbh_hid *usbh_hid_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
g_hid_class[devno].minor = devno;
return &g_hid_class[devno];
@@ -42,17 +42,18 @@ static struct usbh_hid *usbh_hid_class_alloc(void)
static void usbh_hid_class_free(struct usbh_hid *hid_class)
{
uint8_t devno = hid_class->minor;
int devno = hid_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
}
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen)
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
@@ -63,9 +64,14 @@ int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer,
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
setup->wIndex = hid_class->intf;
setup->wLength = buflen;
setup->wLength = hid_class->report_size;
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_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration)
@@ -103,7 +109,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
setup->wLength = 1;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 8) {
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
@@ -163,7 +169,7 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
setup->wLength = buflen;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 8) {
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
@@ -209,6 +215,11 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
}
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;
}
@@ -236,8 +247,7 @@ found:
USB_LOG_WRN("Do not support set idle\r\n");
}
/* We read report desc but do nothing (because of too much memory usage for parsing report desc, parsed by users) */
ret = usbh_hid_get_report_descriptor(hid_class, g_hid_buf[hid_class->minor], MIN(sizeof(g_hid_buf[hid_class->minor]), hid_class->report_size));
ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc);
if (ret < 0) {
return ret;
}
@@ -303,9 +313,9 @@ const struct usbh_class_driver hid_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = USB_DEVICE_CLASS_HID,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = USB_DEVICE_CLASS_HID,
.subclass = 0x00,
.protocol = 0x00,
.id_table = NULL,
.class_driver = &hid_class_driver
};

View File

@@ -15,6 +15,7 @@ struct usbh_hid {
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t report_desc[256];
uint16_t report_size;
uint8_t protocol;
@@ -28,7 +29,6 @@ struct usbh_hid {
extern "C" {
#endif
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen);
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);

View File

@@ -33,11 +33,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_hub *usbh_hub_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
return &g_hub_class[devno];
@@ -48,10 +48,10 @@ static struct usbh_hub *usbh_hub_class_alloc(void)
static void usbh_hub_class_free(struct usbh_hub *hub_class)
{
uint8_t devno = hub_class->index - EXTHUB_FIRST_INDEX;
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
@@ -734,9 +734,9 @@ const struct usbh_class_driver hub_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = USB_DEVICE_CLASS_HUB,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.class = USB_DEVICE_CLASS_HUB,
.subclass = 0,
.protocol = 0,
.id_table = NULL,
.class_driver = &hub_class_driver
};

View File

@@ -109,7 +109,7 @@ void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
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");
}
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)(uint32_t)busid);
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)busid);
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");
}
@@ -915,7 +915,7 @@ static void usbdev_msc_thread(void *argument)
{
uintptr_t event;
int ret;
uint8_t busid = (uint8_t)(uint32_t)argument;
uint8_t busid = (uint8_t)argument;
while (1) {
ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
@@ -977,9 +977,9 @@ struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *
for (uint8_t i = 0u; i <= g_usbd_msc[busid].max_lun; i++) {
usbd_msc_get_cap(busid, i, &g_usbd_msc[busid].scsi_blk_nbr[i], &g_usbd_msc[busid].scsi_blk_size[i]);
if (CONFIG_USBDEV_MSC_MAX_BUFSIZE % g_usbd_msc[busid].scsi_blk_size[i]) {
USB_LOG_ERR("CONFIG_USBDEV_MSC_MAX_BUFSIZE must be a multiple of block size\r\n");
while(1){}
if (g_usbd_msc[busid].scsi_blk_size[i] > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
USB_LOG_ERR("msc block buffer overflow\r\n");
return NULL;
}
}

View File

@@ -23,11 +23,11 @@ static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
static struct usbh_msc *usbh_msc_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
g_msc_class[devno].sdchar = 'a' + devno;
return &g_msc_class[devno];
@@ -38,10 +38,10 @@ static struct usbh_msc *usbh_msc_class_alloc(void)
static void usbh_msc_class_free(struct usbh_msc *msc_class)
{
uint8_t devno = msc_class->sdchar - 'a';
int devno = msc_class->sdchar - 'a';
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
}
@@ -278,12 +278,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
if (ret < 0) {
if (ret == -USB_ERR_STALL) {
USB_LOG_WRN("Device does not support multiple LUNs\r\n");
g_msc_buf[msc_class->sdchar - 'a'][0] = 0;
} else {
return ret;
}
return ret;
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][0] + 1);
@@ -377,6 +372,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
@@ -443,9 +439,9 @@ const struct usbh_class_driver msc_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE,
.bInterfaceSubClass = MSC_SUBCLASS_SCSI,
.bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY,
.class = USB_DEVICE_CLASS_MASS_STORAGE,
.subclass = MSC_SUBCLASS_SCSI,
.protocol = MSC_PROTOCOL_BULK_ONLY,
.id_table = NULL,
.class_driver = &msc_class_driver
};

View File

@@ -9,11 +9,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_xxx *usbh_xxx_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
g_xxx_class[devno].minor = devno;
return &g_xxx_class[devno];
@@ -24,10 +24,10 @@ static struct usbh_xxx *usbh_xxx_class_alloc(void)
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
{
uint8_t devno = xxx_class->minor;
int devno = xxx_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
}
@@ -89,9 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = 0,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.class = 0,
.subclass = 0,
.protocol = 0,
.id_table = NULL,
.class_driver = &xxx_class_driver
};

View File

@@ -70,7 +70,7 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
setup->wLength = size;
ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
if (ret < 8) {
if (ret < 0) {
return ret;
}
memcpy(data, g_asix_buf, ret - 8);
@@ -98,12 +98,9 @@ static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
setup->wIndex = index;
setup->wLength = size;
if (data && size) {
memcpy(g_asix_buf, data, size);
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
} else {
return usbh_control_transfer(asix_class->hport, setup, NULL);
}
memcpy(g_asix_buf, data, size);
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
}
static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val)
@@ -817,9 +814,9 @@ static const struct usbh_class_driver asix_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = asix_id_table,
.class_driver = &asix_class_driver
};

View File

@@ -961,7 +961,7 @@ static int usbh_rtl8152_read_regs(struct usbh_rtl8152 *rtl8152_class,
setup->wLength = size;
ret = usbh_control_transfer(rtl8152_class->hport, setup, g_rtl8152_buf);
if (ret < 8) {
if (ret < 0) {
return ret;
}
memcpy(data, g_rtl8152_buf, ret - 8);
@@ -997,10 +997,9 @@ static int generic_ocp_read(struct usbh_rtl8152 *tp, uint16_t index, uint16_t si
{
uint16_t limit = 64;
int ret = 0;
uint8_t *buf = data;
/* both size and indix must be 4 bytes align */
if ((size & 3) || !size || (index & 3) || !buf)
if ((size & 3) || !size || (index & 3) || !data)
return -USB_ERR_INVAL;
if ((uint32_t)index + (uint32_t)size > 0xffff)
@@ -1008,20 +1007,20 @@ static int generic_ocp_read(struct usbh_rtl8152 *tp, uint16_t index, uint16_t si
while (size) {
if (size > limit) {
ret = usbh_rtl8152_read_regs(tp, index, type, limit, buf);
ret = usbh_rtl8152_read_regs(tp, index, type, limit, data);
if (ret < 0)
break;
index += limit;
buf += limit;
data += limit;
size -= limit;
} else {
ret = usbh_rtl8152_read_regs(tp, index, type, size, buf);
ret = usbh_rtl8152_read_regs(tp, index, type, size, data);
if (ret < 0)
break;
index += size;
buf += size;
data += size;
size = 0;
break;
}
@@ -1036,10 +1035,9 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
int ret;
uint16_t byteen_start, byteen_end, byen;
uint16_t limit = 512;
uint8_t *buf = data;
/* both size and indix must be 4 bytes align */
if ((size & 3) || !size || (index & 3) || !buf)
if ((size & 3) || !size || (index & 3) || !data)
return -USB_ERR_INVAL;
if ((uint32_t)index + (uint32_t)size > 0xffff)
@@ -1052,12 +1050,12 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
/* Split the first DWORD if the byte_en is not 0xff */
if (byen != BYTE_EN_DWORD) {
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, buf);
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, data);
if (ret < 0)
goto error1;
index += 4;
buf += 4;
data += 4;
size -= 4;
}
@@ -1072,22 +1070,22 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
if (size > limit) {
ret = usbh_rtl8152_write_regs(tp, index,
type | BYTE_EN_DWORD,
limit, buf);
limit, data);
if (ret < 0)
goto error1;
index += limit;
buf += limit;
data += limit;
size -= limit;
} else {
ret = usbh_rtl8152_write_regs(tp, index,
type | BYTE_EN_DWORD,
size, buf);
size, data);
if (ret < 0)
goto error1;
index += size;
buf += size;
data += size;
size = 0;
break;
}
@@ -1095,7 +1093,7 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
/* Set the last DWORD */
if (byen != BYTE_EN_DWORD)
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, buf);
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, data);
}
error1:
@@ -2272,9 +2270,9 @@ static const struct usbh_class_driver rtl8152_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info rtl8152_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = rtl_id_table,
.class_driver = &rtl8152_class_driver
};

View File

@@ -17,11 +17,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x));
g_ch34x_class[devno].minor = devno;
return &g_ch34x_class[devno];
@@ -32,10 +32,10 @@ static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class)
{
uint8_t devno = ch34x_class->minor;
int devno = ch34x_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(ch34x_class, 0, sizeof(struct usbh_ch34x));
}
@@ -370,9 +370,9 @@ const struct usbh_class_driver ch34x_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ch34x_id_table,
.class_driver = &ch34x_class_driver
};

View File

@@ -17,11 +17,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x));
g_cp210x_class[devno].minor = devno;
return &g_cp210x_class[devno];
@@ -32,10 +32,10 @@ static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
{
uint8_t devno = cp210x_class->minor;
int devno = cp210x_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cp210x_class, 0, sizeof(struct usbh_cp210x));
}
@@ -319,9 +319,9 @@ const struct usbh_class_driver cp210x_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = cp210x_id_table,
.class_driver = &cp210x_class_driver
};

View File

@@ -17,11 +17,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi));
g_ftdi_class[devno].minor = devno;
return &g_ftdi_class[devno];
@@ -32,10 +32,10 @@ static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class)
{
uint8_t devno = ftdi_class->minor;
int devno = ftdi_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(ftdi_class, 0, sizeof(struct usbh_ftdi));
}
@@ -392,9 +392,9 @@ const struct usbh_class_driver ftdi_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ftdi_id_table,
.class_driver = &ftdi_class_driver
};

View File

@@ -25,11 +25,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_PL2303_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_pl2303_class[devno], 0, sizeof(struct usbh_pl2303));
g_pl2303_class[devno].minor = devno;
return &g_pl2303_class[devno];
@@ -40,10 +40,10 @@ static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
static void usbh_pl2303_class_free(struct usbh_pl2303 *pl2303_class)
{
uint8_t devno = pl2303_class->minor;
int devno = pl2303_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(pl2303_class, 0, sizeof(struct usbh_pl2303));
}
@@ -440,9 +440,9 @@ const struct usbh_class_driver pl2303_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = pl2303_id_table,
.class_driver = &pl2303_class_driver
};

View File

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

View File

@@ -15,11 +15,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_xbox *usbh_xbox_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << 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];
@@ -30,10 +30,10 @@ static struct usbh_xbox *usbh_xbox_class_alloc(void)
static void usbh_xbox_class_free(struct usbh_xbox *xbox_class)
{
uint8_t devno = xbox_class->minor;
int devno = xbox_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(xbox_class, 0, sizeof(struct usbh_xbox));
}
@@ -220,9 +220,9 @@ static const uint16_t xbox_id_table[][2] = {
CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC,
.bInterfaceSubClass = 0x5d,
.bInterfaceProtocol = 0x01,
.class = USB_DEVICE_CLASS_VEND_SPECIFIC,
.subclass = 0x5d,
.protocol = 0x01,
.id_table = xbox_id_table,
.class_driver = &xbox_class_driver
};

View File

@@ -18,20 +18,6 @@ struct usbd_video_priv {
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
uint8_t *ep_buf0;
uint8_t *ep_buf1;
bool ep_buf0_ready;
bool ep_buf1_ready;
uint32_t ep_buf0_len;
uint32_t ep_buf1_len;
uint8_t ep_buf_idx;
bool stream_finish;
uint32_t max_packets;
uint8_t *stream_buf;
uint32_t stream_len;
uint32_t stream_offset;
uint8_t stream_frameid;
uint32_t stream_headerlen;
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -685,7 +671,7 @@ static int video_class_interface_request_handler(uint8_t busid, struct usb_setup
} else {
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
}
} else if (intf_num == 1) { /* Video Stream Inteface */
} else if (intf_num == 1) { /* Video Stream Inteface */
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
}
return -1;
@@ -714,7 +700,7 @@ static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
}
}
static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
{
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
@@ -751,47 +737,9 @@ static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dw
g_usbd_video[busid].commit.bPreferedVersion = 0;
g_usbd_video[busid].commit.bMinVersion = 0;
g_usbd_video[busid].commit.bMaxVersion = 0;
g_usbd_video[busid].stream_frameid = 0;
g_usbd_video[busid].stream_headerlen = 2;
}
static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
{
struct video_payload_header *header;
uint32_t len;
uint32_t offset;
len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
offset = 0;
while (len > 0) {
header = (struct video_payload_header *)&ep_buf[offset];
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
header->headerInfoUnion.bmheaderInfo = 0;
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
len2);
g_usbd_video[busid].stream_offset += len2;
len -= len2;
offset += (len2 + g_usbd_video[busid].stream_headerlen);
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
}
}
return offset;
}
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
struct usbd_interface *intf,
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize)
@@ -815,70 +763,28 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid,
return intf;
}
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
{
uint32_t remain;
uint32_t packets;
uint32_t last_packet_size;
uint32_t picture_pos = 0;
static uint8_t uvc_header[2] = { 0x02, 0x80 };
if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf_idx = 1;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
} else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
} else {
if (g_usbd_video[busid].stream_finish) {
return true;
}
}
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
if (!g_usbd_video[busid].ep_buf0_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
for (size_t i = 0; i < packets; i++) {
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
if (i == (packets - 1)) {
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
} else {
g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
g_usbd_video[busid].ep_buf0_ready = true;
if (!g_usbd_video[busid].ep_buf1_ready) {
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
}
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
}
}
if (!g_usbd_video[busid].ep_buf1_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
} else {
g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
g_usbd_video[busid].ep_buf1_ready = true;
}
}
return false;
}
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
{
if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
return -1;
}
g_usbd_video[busid].ep_buf0 = ep_buf0;
g_usbd_video[busid].ep_buf1 = ep_buf1;
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
g_usbd_video[busid].stream_finish = false;
g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
g_usbd_video[busid].stream_buf = stream_buf;
g_usbd_video[busid].stream_len = stream_len;
g_usbd_video[busid].stream_offset = 0;
usbd_video_stream_split_transfer(busid, ep);
return 0;
}
uvc_header[1] ^= 1;
*out_len = (input_len + 2 * packets);
return packets;
}

View File

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

View File

@@ -34,11 +34,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_video *usbh_video_class_alloc(void)
{
uint8_t devno;
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
g_video_class[devno].minor = devno;
return &g_video_class[devno];
@@ -49,10 +49,10 @@ static struct usbh_video *usbh_video_class_alloc(void)
static void usbh_video_class_free(struct usbh_video *video_class)
{
uint8_t devno = video_class->minor;
int devno = video_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(video_class, 0, sizeof(struct usbh_video));
}
@@ -531,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
.bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL,
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOCONTROL,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.id_table = NULL,
.class_driver = &video_ctrl_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
.bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING,
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOSTREAMING,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.id_table = NULL,
.class_driver = &video_streaming_class_driver
};

View File

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

View File

@@ -18,8 +18,7 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep, uint8_t mac[6]);
void usbd_rndis_data_recv_done(uint32_t len);
void usbd_rndis_data_send_done(uint32_t len);
void usbd_rndis_data_recv_done(void);
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
struct pbuf *usbd_rndis_eth_rx(void);

View File

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

View File

@@ -13,7 +13,7 @@
#define DEV_FORMAT "/dev/rndis"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[512];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
@@ -80,7 +80,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(g_rndis_buf);
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -138,7 +138,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(g_rndis_buf);
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -195,7 +195,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(g_rndis_buf);
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -262,7 +262,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(g_rndis_buf);
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -387,14 +387,14 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
}
uint32_t packet_filter = 0x0f;
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
if (ret < 0) {
return ret;
}
@@ -600,9 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x03,
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x03,
.id_table = NULL,
.class_driver = &rndis_class_driver
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -175,7 +175,7 @@ static const uint8_t adb_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -144,7 +144,7 @@ const uint8_t audio_v1_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -139,7 +139,7 @@ const uint8_t audio_v1_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -196,7 +196,7 @@ uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -95,7 +95,7 @@ const uint8_t msc_bootuf2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

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

View File

@@ -58,7 +58,7 @@ static const uint8_t device_quality_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
};
@@ -173,7 +173,7 @@ static const uint8_t cdc_msc_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -113,7 +113,7 @@ static const uint8_t cdc_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -98,7 +98,7 @@ static const uint8_t cdc_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

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

View File

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

View File

@@ -136,7 +136,7 @@ const uint8_t dfu_flash_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -146,7 +146,7 @@ static const uint8_t hid_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

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

View File

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

View File

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

View File

@@ -145,7 +145,7 @@ const uint8_t midi_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -94,7 +94,7 @@ const uint8_t msc_ram_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -97,7 +97,7 @@ const uint8_t msc_storage_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

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

View File

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

View File

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

View File

@@ -7,8 +7,6 @@
#include "usbd_video.h"
#include "cherryusb_mjpeg.h"
#define MAX_PACKETS_IN_ONE_TRANSFER 1
#define VIDEO_IN_EP 0x81
#define VIDEO_INT_EP 0x83
@@ -36,7 +34,7 @@
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1, 1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1,1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
#define USB_VIDEO_DESC_SIZ (unsigned long)(9 + \
VIDEO_VC_NOEP_DESCRIPTOR_LEN + \
@@ -131,7 +129,7 @@ const uint8_t video_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
0x00
@@ -182,10 +180,8 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (usbd_video_stream_split_transfer(busid, ep)) {
/* one frame has done */
iso_tx_busy = false;
}
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
iso_tx_busy = false;
}
static struct usbd_endpoint video_in_ep = {
@@ -206,21 +202,48 @@ void video_init(uint8_t busid, uintptr_t reg_base)
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
void video_test(uint8_t busid)
{
memset(packet_buffer, 0, sizeof(packet_buffer));
uint32_t out_len;
uint32_t packets;
(void)packets;
memset(packet_buffer, 0, 40 * 1024);
while (1) {
if (tx_flag) {
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len);
#if 1
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
}
}
#else
/* dwc2 must use this method */
for (uint32_t i = 0; i < packets; i++) {
if (i == (packets - 1)) {
iso_tx_busy = true;
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
}
}
} else {
iso_tx_busy = true;
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
}
}
}
}
#endif
}
}
}

View File

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

View File

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

View File

@@ -326,7 +326,7 @@ const uint8_t winusb_descriptor[] = {
0x02,
0x01,
0x40,
0x00,
0x01,
0x00,
#endif
0x00

View File

@@ -219,7 +219,7 @@ const uint8_t winusbv2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
/* End */

View File

@@ -255,7 +255,7 @@ const uint8_t winusbv2_descriptor[] = {
0x00,
0x00,
0x40,
0x00,
0x01,
0x00,
#endif
/* End */

1
docs/.gitignore vendored
View File

@@ -1 +0,0 @@
*build

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,7 +1,7 @@
USB CONFIG 说明
USB CONFIG
=========================
通用 CONFIG
通用 CONFIG
---------------------
CONFIG_USB_PRINTF
@@ -29,13 +29,13 @@ USB_NOCACHE_RAM_SECTION
如果芯片没有 cache 功能,此宏无效。如果有,则 USB 的输入输出 buffer 必须放在 nocache ram 中,保证数据一致性。
设备协议栈 CONFIG
设备相关 CONFIG
---------------------
CONFIG_USBDEV_REQUEST_BUFFER_LEN
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
控制传输接收和发送的 buffer 最大长度,默认是 512
控制传输接收和发送的 buffer 最大长度,默认是 256
CONFIG_USBDEV_SETUP_LOG_PRINT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ CONFIG_USBDEV_MSC_MAX_BUFSIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
msc 缓存的最大长度缓存越大USB 的速度越高,因为介质一般多个 block 读写速度比单个 block 高很多,比如 sd 卡。
默认 512 ,如果是 flash 需要改成 4K, 缓存的大小需要是介质的一个 block size 的整数倍。
默认 512 ,如果是 flash 需要改成 4K, 缓存的大小需要是 介质的一个 block size 的整数倍。
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,11 +66,6 @@ CONFIG_USBDEV_MSC_PRODUCT_STRING
CONFIG_USBDEV_MSC_VERSION_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_MSC_POLLING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
将 usbd_msc_sector_read 和 usbd_msc_sector_write 操作放在 while1 中运行,裸机下使用。
CONFIG_USBDEV_MSC_THREAD
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +90,7 @@ rndis 控制传输最大接收和发送的长度,根据 RNDIS options list 决
CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rndis 以太网帧的最大长度,默认 1580
rndis 以太网帧的最大长度,默认 1536
CONFIG_USBDEV_RNDIS_VENDOR_ID
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -108,7 +103,7 @@ CONFIG_USBDEV_RNDIS_USING_LWIP
rndis 与 lwip 接口的对接
主机协议栈 CONFIG
主机相关 CONFIG
---------------------
以下参数决定了支持的最大外部hub数量接口数每个接口的端点数和 altsetting 数量,更改此值会影响 ram 的大小,建议根据实际情况更改。

View File

@@ -1,4 +1,4 @@
主从驱动
Porting
=========================
.. note:: 请注意v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
@@ -37,7 +37,6 @@ usbd_set_address
int usbd_set_address(const uint8_t addr);
- **addr** 设备地址
- **return** 返回 0 表示正确,其他表示错误
usbd_ep_open
@@ -47,9 +46,8 @@ usbd_ep_open
.. code-block:: C
int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
- **ep** 端点描述符
- **return** 返回 0 表示正确,其他表示错误
usbd_ep_close
@@ -61,7 +59,7 @@ usbd_ep_close
int usbd_ep_close(const uint8_t ep);
- **ep** 端点地址
- **event**
- **return** 返回 0 表示正确,其他表示错误
usbd_ep_set_stall
@@ -128,9 +126,7 @@ usbd_ep_start_read
- **data_len** 接收长度,原则上无限长,推荐 16K 字节以内,并且推荐是最大包长的整数倍
- **return** 返回 0 表示正确,其他表示错误
.. note:: 启动接收以后以下两种情况会进入传输完成中断1、最后一包为短包(小于 EP MPS2、接收总长度等于 data_len
.. note:: 对于 bulk 传输data_len 通常设计为 EP MPS以下三种情况可以修改为多个 EP MPS: 固定长度自定义协议并携带长度MSC; 主机手动发送 ZLP 或者短包RNDIS
.. note:: 启动接收以后以下两种情况会进入传输完成中断1、最后一包为短包2、接收总长度等于 data_len
host controller(hcd)
------------------------
@@ -146,17 +142,6 @@ usb_hc_init
- **return** 返回 0 表示正确,其他表示错误
usb_hc_deinit
""""""""""""""""""""""""""""""""""""
``usb_hc_deinit`` 用于反初始化 usb host controller 寄存器。 **此函数不对用户开放**
.. code-block:: C
int usb_hc_deinit(void);
- **return** 返回 0 表示正确,其他表示错误
usbh_roothub_control
""""""""""""""""""""""""""""""""""""

View File

@@ -3,11 +3,11 @@
# -- Project information
project = 'CherryUSB'
copyright = '2022 ~ 2024, sakumisu'
copyright = '2024, sakumisu'
author = 'sakumisu'
release = '1.4.2'
version = '1.4.2'
release = '1.4.0'
version = '1.4.0'
# -- General configuration

View File

@@ -1,2 +0,0 @@
usbd_audiov1
===============

View File

@@ -1,2 +0,0 @@
usbd_audiov2
===============

View File

@@ -1,104 +0,0 @@
usbd_cdc_acm
===============
本 demo 主要用于演示 cdc acm 功能包含收发测试DTR 控制ZLP 测试,性能测试。
- 开辟读写 buffer用于收发数据并且buffer需要用 nocache 修饰,这里我们读写都是用 2048字节是为了后面的 ZLP 测试和性能测试使用。
.. code-block:: C
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
- 在协议栈事件回调中,我们需要在枚举完成后启动第一次传输,并清除相关 flag可以在 reset 事件中清除,也可以在 configured 事件中清除。
.. code-block:: C
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
- 在接收完成中断中继续发起接收;在发送完成中断中判断是否需要发送 ZLP。
.. code-block:: C
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
// printf("%02x ", read_buffer[i]);
// }
// printf("\r\n");
/* setup next out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
- 以下是为了测试 DTR 功能并控制 USB 发送DTR 和 RTS 只用于搭配 UART 使用,如果是纯 USB没什么用这里仅做测试。DTR 开关使用任意串口上位机并勾选 DTR。
.. code-block:: C
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
} else {
dtr_enable = 0;
}
}
- 在主函数中一直调用发送即可
.. code-block:: C
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
ep_tx_busy_flag = true;
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
}
- 上述我们需要注意,长度设置为 2048 是为了测试 ZLP 功能,通常实际使用时,接收长度应该使用 CDC_MAX_MPS 。具体原因参考 :ref:`usb_ext`
- 如果需要做性能测试,使用 tools/test_srcipts/test_cdc_speed.py 进行测试,并在测试之前删除 `usbd_cdc_acm_bulk_out``usbd_cdc_acm_bulk_in` 中的打印,否则会影响测试结果。
此外,对于 CDC ACM 搭配 OS 的情况,通常我们 read 使用异步并将数据存储到 ringbuffer 中write 使用同步搭配 sem 使用。

View File

@@ -1,2 +0,0 @@
usbd_cdc_ecm
===============

View File

@@ -1,4 +0,0 @@
usbd_hid
===============
HID 功能比较简单,因此不作赘述,需要注意,使用 hid custom 例程时,需要搭配 `tools/test_srcipts/test_hid_inout.py` 使用。

View File

@@ -1,39 +0,0 @@
usbd_msc
===============
本节主要演示 USB 模拟 U 盘功能。默认使用RAM 作为存储介质模拟 U 盘。
- 实现 U 盘的读写和获取容量接口,注意,容量 block_num 为虚拟的,实际没有这么多 block读写的数据超过 BLOCK_COUNT 会丢弃。
block_size 一般为 512/2048/4096。
.. code-block:: C
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < BLOCK_COUNT)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < BLOCK_COUNT)
memcpy(mass_block[sector].BlockSpace, buffer, length);
return 0;
}
- 默认上述 API 在中断中执行,如果需要在非中断中执行,可以选择如下:
1裸机下开启 `CONFIG_USBDEV_MSC_POLLING` 并在 while1 中调用 `usbd_msc_polling`,则读写函数在 while1 中执行。
2, OS 下开启 `CONFIG_USBDEV_MSC_THREAD`,则读写函数在线程中执行。
- 修改 `CONFIG_USBDEV_MSC_STACKSIZE` 会影响 U 盘的读写速度,必须是 block_size 的整数倍,当然,也会增加 RAM 的占用。
- 如果 RAM 例程可以用,但是介质更换成 SD 或者 FLASH 后不可用,则一定是介质驱动问题。

View File

@@ -1,2 +0,0 @@
usbd_rndis
===============

View File

@@ -1,44 +0,0 @@
vendor device 驱动编写
===========================
本节主要介绍如何编写一个 vendor device 驱动。
- 首先复制一份 class/template/usbd_xxx.c 文件
- 实现以下三个回调函数通常来说vendor 驱动只需要实现 vendor_handler
.. code-block:: C
intf->class_interface_handler = xxx_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = xxx_notify_handler;
- 举例如下
case1 演示对于主机 IN 数据的处理,将数据拷贝到 *data 中,并指定*len 的长度。协议栈会自动发送给主机,不需要用户手动调用发送 API。
case2 演示对于主机 OUT 数据的处理,当执行到此函数时,说明数据都已经接收完成,可以直接读取 *data 中的数据,长度为 *len。
.. code-block:: C
static int xxx_vendor_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_WRN("XXX Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case 1:
memcpy(*data, xxx, sizeof(xxx));
*len = sizeof(xxx);
case 2:
hexdump(*data, *len);
default:
USB_LOG_WRN("Unhandled XXX Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
- 最后使用形如 usbd_add_interface(busid, usbd_xxx_init_intf(&intf)) 注册接口

View File

@@ -1,83 +0,0 @@
usbd_video
===============
本节主要演示 USB UAC 功能,支持 YUYV, MJPEG, H264 格式。为了方便演示,都采用的静态图。
demo 包含 **video_static_yuyv_template**, **video_static_mjpeg_template**, **video_static_h264_template**, 仅描述符和图片数据不同。
- 在高速模式下默认最大是1024字节但是如果芯片支持 additional transcations可以配置为最高 2048字节或者3072字节这样可以提高传输效率。
.. code-block:: C
#ifdef CONFIG_USB_HS
#define MAX_PAYLOAD_SIZE 1024 // for high speed with one transcations every one micro frame
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
// #define MAX_PAYLOAD_SIZE 2048 // for high speed with two transcations every one micro frame
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11))
// #define MAX_PAYLOAD_SIZE 3072 // for high speed with three transcations every one micro frame
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
#else
#define MAX_PAYLOAD_SIZE 1020
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
#endif
- 通常只需要修改 WIDTH 和 HEIGHT
.. code-block:: C
#define WIDTH (unsigned int)(640)
#define HEIGHT (unsigned int)(480)
#define CAM_FPS (30)
#define INTERVAL (unsigned long)(10000000 / CAM_FPS)
#define MIN_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
- USB 端点配置,默认 interval 为 1也就是全速模式下 1ms高速模式下 125us。同步类型使用异步模式。
.. code-block:: C
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
- 使用 `usbd_video_stream_start_write` 传输数据
1传输采用双缓冲的形式 **MAX_PACKETS_IN_ONE_TRANSFER** 表示一次传输可以携带多少个 **MAX_PAYLOAD_SIZE**,通常 IP 只能为 1。
2在中断完成中调用 `usbd_video_stream_split_transfer` 继续下一次传输,直到返回为 true 表示传输完成。这边的分裂传输只是表示将图片数据拆成 **MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE** 份传输。
3通常 IP 不支持一次传输非常大的数据,比如传输 1MB因此需要做分裂传输但是会增加中断次数。并且一次传输非常大数据也是需要足够的 RAM。
.. code-block:: C
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (usbd_video_stream_split_transfer(busid, ep)) {
/* one frame has done */
iso_tx_busy = false;
}
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
void video_test(uint8_t busid)
{
memset(packet_buffer, 0, sizeof(packet_buffer));
while (1) {
if (tx_flag) {
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
while (iso_tx_busy) {
if (tx_flag == 0) {
break;
}
}
}
}
}

View File

@@ -1,21 +0,0 @@
usbd_webusb
===============
本 demo 主要演示 webusb 功能webusb 主要用于弹出网页并对 USB 设备进行访问。示例使用 webusb_hid_template.c。
- 在注册描述符时注册 BOS, MSOSV2, WEBUSB 描述符即可。
.. code-block:: C
usbd_bos_desc_register(busid, &bos_desc);
usbd_msosv2_desc_register(busid, &msosv2_desc);
usbd_webusb_desc_register(busid, &webusb_url_desc);
- 增加一个接口描述符用于 webusb
.. code-block:: C
USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00)
- 其余使用 hid 描述符,不再赘述
- 枚举完成后,电脑右下角会弹出网页信息,点击即可打开网页

View File

@@ -1,32 +0,0 @@
usbd_winusb
===============
本节主要介绍 winusb 驱动。winusb 是 windows 为了让用户友好的访问 USB 自定义类设备提供的一套通用驱动,其实本质就是 CDC ACM。
WINUSB 版本根据 USB 版本分为 V1/V2 版本V2 版本需要包含 BOS 描述符V1 版本不需要。V2 版本需要在设备描述符中设置为 USB2.1 的版本号。
- V1 版本注册描述符
.. code-block:: C
usbd_msosv1_desc_register(busid, &msosv1_desc);
- V2 版本注册描述符
.. code-block:: C
usbd_bos_desc_register(busid, &bos_desc);
usbd_msosv2_desc_register(busid, &msosv2_desc);
- 接口描述符注册
.. code-block:: C
/* Interface 0 */
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
/* Endpoint OUT 2 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
/* Endpoint IN 1 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
- 其余操作与 CDC ACM 相同,不再赘述

View File

@@ -1,2 +0,0 @@
usbh_bluetooth
===============

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