Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1435548e7 | ||
|
|
a8d40eb706 | ||
|
|
aeffaea016 | ||
|
|
9ce7b0ceb7 | ||
|
|
1c31156a37 | ||
|
|
e795ab73a0 | ||
|
|
5e689dfe15 | ||
|
|
d10cbd5daf | ||
|
|
40a019e063 | ||
|
|
2080cf1206 | ||
|
|
ae521bf95c | ||
|
|
a2f7b67dc4 | ||
|
|
e79319cac9 | ||
|
|
7acb667e20 | ||
|
|
a04b1fa551 | ||
|
|
c37c60c7c7 | ||
|
|
0738c09a4d | ||
|
|
cf4dfde49d | ||
|
|
d4ba2eef57 | ||
|
|
3d96f64f94 | ||
|
|
a746eb4bb1 | ||
|
|
c84e769f78 | ||
|
|
d11260ef67 | ||
|
|
e6193bd131 | ||
|
|
dd1f1d3ba8 | ||
|
|
bc1e7c4bd5 | ||
|
|
7d76b4bae1 | ||
|
|
7c0ef50bb3 | ||
|
|
0f2cb9f900 | ||
|
|
7c1fae04b2 | ||
|
|
14f5dd2dd3 | ||
|
|
9029f8c5b1 | ||
|
|
b9915e0e1b | ||
|
|
1387790744 | ||
|
|
c5fc9f338e | ||
|
|
4d61e5e053 | ||
|
|
1a7259649b | ||
|
|
628e4ee928 | ||
|
|
749369b6fc | ||
|
|
89cd77374c | ||
|
|
3792ad4905 | ||
|
|
2789633b50 | ||
|
|
94505f9e41 | ||
|
|
c8b832e1a0 | ||
|
|
d3aa9449e1 | ||
|
|
4d7938e349 | ||
|
|
4777a65f54 | ||
|
|
96c0b655fd | ||
|
|
61da3794cf | ||
|
|
45ea9928bc | ||
|
|
64e2b8d480 | ||
|
|
fed6f26ebd | ||
|
|
513772a534 | ||
|
|
e45a2857df | ||
|
|
c8ecf31c99 | ||
|
|
4395c7f039 | ||
|
|
3057f41020 | ||
|
|
47c0255cdc | ||
|
|
d53e8a2adf | ||
|
|
3bdb3bbf84 | ||
|
|
3c1168d58c | ||
|
|
f672591d58 | ||
|
|
84598eed7c | ||
|
|
7574063e94 | ||
|
|
0d916af297 | ||
|
|
b90d6a727e | ||
|
|
d0d6f99c90 | ||
|
|
9673b2cf67 | ||
|
|
7061367484 | ||
|
|
faf90663a9 | ||
|
|
bb58348510 | ||
|
|
8253f074ce | ||
|
|
8a93ca4bce | ||
|
|
8968b7b3c9 | ||
|
|
2ca22deaad | ||
|
|
340fa4e024 | ||
|
|
822cd9d679 | ||
|
|
e061b8e784 | ||
|
|
8856361be0 | ||
|
|
1c7110bd86 | ||
|
|
48efbfe521 | ||
|
|
c540080c96 | ||
|
|
d970f88f06 | ||
|
|
2d1b4b8b82 | ||
|
|
9bac9537db | ||
|
|
f35b345680 | ||
|
|
56868b513a |
35
.readthedocs.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
# Read the Docs configuration file for Sphinx projects
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the OS, Python version and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
# You can also specify other tool versions:
|
||||
# nodejs: "20"
|
||||
# rust: "1.70"
|
||||
# golang: "1.20"
|
||||
|
||||
# Build documentation in the "docs/" directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/source/conf.py
|
||||
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
|
||||
# builder: "dirhtml"
|
||||
# Fail on all warnings to avoid broken references
|
||||
# fail_on_warning: true
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
# formats:
|
||||
# - pdf
|
||||
# - epub
|
||||
|
||||
# Optional but recommended, declare the Python requirements required
|
||||
# to build your documentation
|
||||
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
@@ -1,56 +1,57 @@
|
||||
## Script for hpmicro ##
|
||||
sdk_inc(common)
|
||||
sdk_inc(osal)
|
||||
sdk_inc(core)
|
||||
sdk_inc(class/cdc)
|
||||
sdk_inc(class/hid)
|
||||
sdk_inc(class/msc)
|
||||
sdk_inc(class/audio)
|
||||
sdk_inc(class/video)
|
||||
sdk_inc(class/hub)
|
||||
add_library(cherryusb STATIC)
|
||||
|
||||
target_include_directories(cherryusb PUBLIC
|
||||
common
|
||||
core
|
||||
osal
|
||||
class/cdc
|
||||
class/hid
|
||||
class/msc
|
||||
class/audio
|
||||
class/video
|
||||
class/hub
|
||||
class/wireless
|
||||
)
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE)
|
||||
sdk_src(core/usbd_core.c)
|
||||
sdk_src(port/hpm/usb_dc_hpm.c)
|
||||
sdk_compile_definitions(-DCONFIG_USB_HS)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
||||
sdk_src(class/cdc/usbd_cdc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||
sdk_src(class/hid/usbd_hid.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_MSC)
|
||||
sdk_src(class/msc/usbd_msc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
|
||||
sdk_src(class/audio/usbd_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
|
||||
sdk_src(class/video/usbd_video.c)
|
||||
target_sources(cherryusb PRIVATE core/usbd_core.c)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
||||
target_sources(cherryusb PRIVATE class/cdc/usbd_cdc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||
target_sources(cherryusb PRIVATE class/hid/usbd_hid.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_MSC)
|
||||
target_sources(cherryusb PRIVATE class/msc/usbd_msc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
|
||||
target_sources(cherryusb PRIVATE class/audio/usbd_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
|
||||
target_sources(cherryusb PRIVATE class/video/usbd_video.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE_DEMO_CDC)
|
||||
sdk_src(demo/cdc_acm_template.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE_DEMO_CDC_MSC)
|
||||
sdk_src(demo/cdc_acm_msc_template.c)
|
||||
endif()
|
||||
|
||||
elseif(CONFIG_CHERRYUSB_HOST)
|
||||
sdk_src(core/usbh_core.c)
|
||||
sdk_src(class/hub/usbh_hub.c)
|
||||
sdk_src(port/ehci/usb_hc_ehci.c)
|
||||
sdk_src(port/ehci/usb_glue_hpm.c)
|
||||
sdk_src(osal/usb_osal_freertos.c)
|
||||
sdk_src(class/cdc/usbh_cdc_acm.c)
|
||||
sdk_src(class/msc/usbh_msc.c)
|
||||
sdk_src(class/hid/usbh_hid.c)
|
||||
sdk_src(class/wireless/usbh_rndis.c)
|
||||
if(CONFIG_CHERRYUSB_HOST_DEMO)
|
||||
sdk_src(demo/usb_host.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST)
|
||||
target_sources(cherryusb PRIVATE
|
||||
core/usbh_core.c
|
||||
class/hub/usbh_hub.c
|
||||
class/cdc/usbh_cdc_acm.c
|
||||
class/hid/usbh_hid.c
|
||||
class/msc/usbh_msc.c
|
||||
class/audio/usbh_audio.c
|
||||
class/video/usbh_video.c
|
||||
class/wireless/usbh_rndis.c
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
||||
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_freertos.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_rtthread.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_yoc.c)
|
||||
endif()
|
||||
endif()
|
||||
69
README.md
@@ -4,7 +4,7 @@
|
||||
|
||||
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
|
||||
|
||||

|
||||

|
||||
|
||||
## Why choose
|
||||
|
||||
@@ -85,12 +85,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 | 3263 | 384 | 17 | 0 |
|
||||
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 501 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|
||||
|usbd_video.c | 2272 | 0 | 82 | 0 |
|
||||
|usbd_core.c | 3516 | 256(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
|
||||
|
||||
@@ -116,13 +117,14 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|
||||
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|
||||
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|
||||
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|
||||
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|
||||
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
|
||||
@@ -134,6 +136,18 @@ Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affe
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
x is affected by the following macros:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## Documentation Tutorial
|
||||
|
||||
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
||||
@@ -148,23 +162,22 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|
||||
|
||||
## Demo Repo
|
||||
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url |Current version|
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.7.0 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|latest |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Phytium | PhytiumPI | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|
||||
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|
||||
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|
||||
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
69
README_zh.md
@@ -4,7 +4,7 @@
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
||||
|
||||

|
||||

|
||||
|
||||
## 为什么选择
|
||||
|
||||
@@ -83,12 +83,13 @@ CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3263 | 384 | 17 | 0 |
|
||||
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 501 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|
||||
|usbd_video.c | 2272 | 0 | 82 | 0 |
|
||||
|usbd_core.c | 3516 | 256(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 协议栈简介
|
||||
|
||||
@@ -114,13 +115,14 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|
||||
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|
||||
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|
||||
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|
||||
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|
||||
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
|
||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||
|
||||
@@ -132,6 +134,18 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
x 受以下宏影响:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## 文档教程
|
||||
|
||||
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
|
||||
@@ -146,23 +160,22 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
|
||||
|
||||
## 示例仓库
|
||||
|
||||
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
|
||||
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 当前版本 |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.7.0 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|latest |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Phytium | e2000 | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|
||||
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|
||||
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|
||||
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
29
SConscript
@@ -16,7 +16,9 @@ CPPDEFINES = []
|
||||
|
||||
# USB DEVICE
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
path += [cwd + '/osal']
|
||||
src += Glob('core/usbd_core.c')
|
||||
src += Glob('osal/usb_osal_rtthread.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||
CPPDEFINES+=['CONFIG_USB_HS']
|
||||
@@ -44,6 +46,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
src += Glob('demo/hid_keyboard_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
|
||||
src += Glob('demo/msc_ram_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
|
||||
src += Glob('demo/msc_storage_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
|
||||
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
|
||||
@@ -81,6 +85,12 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
else:
|
||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/common']
|
||||
path += [cwd + '/port/pusb2/fpusb2']
|
||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||
src += Glob('port/pusb2/usb_dc_pusb2.c')
|
||||
|
||||
# USB HOST
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
path += [cwd + '/osal']
|
||||
@@ -97,6 +107,7 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
src += Glob('class/msc/usbh_msc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
|
||||
src += Glob('class/wireless/usbh_rndis.c')
|
||||
src += Glob('third_party/rt-thread-4.1.1/rndis_host/rndis_host.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
@@ -111,9 +122,27 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
|
||||
src += Glob('port/ehci/usb_glue_hpm.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
|
||||
src += Glob('port/xhci/usb_hc_xhci.c')
|
||||
src += Glob('port/xhci/xhci_dbg.c')
|
||||
src += Glob('port/xhci/xhci.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/common']
|
||||
path += [cwd + '/port/pusb2/fpusb2']
|
||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||
src += Glob('port/pusb2/usb_hc_pusb2.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
||||
src += Glob('demo/usb_host.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
|
||||
path += [cwd + '/class/vendor/cp201x']
|
||||
src += Glob('class/vendor/cp201x/usbh_cp210x.c')
|
||||
src += Glob('third_party/rt-thread-4.1.1/dfs/drv_usbh_cp210x_rtt.c')
|
||||
|
||||
src += Glob('third_party/rt-thread-4.1.1/msh_cmd.c')
|
||||
|
||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x000900
|
||||
#define CHERRYUSB_VERSION 0x001002
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
@@ -44,27 +44,6 @@
|
||||
/* Enable test mode */
|
||||
// #define CONFIG_USBDEV_TEST_MODE
|
||||
|
||||
//#define CONFIG_USBDEV_TX_THREAD
|
||||
//#define CONFIG_USBDEV_RX_THREAD
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_THREAD
|
||||
#ifndef CONFIG_USBDEV_TX_PRIO
|
||||
#define CONFIG_USBDEV_TX_PRIO 4
|
||||
#endif
|
||||
#ifndef CONFIG_USBDEV_TX_STACKSIZE
|
||||
#define CONFIG_USBDEV_TX_STACKSIZE 2048
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_RX_THREAD
|
||||
#ifndef CONFIG_USBDEV_RX_PRIO
|
||||
#define CONFIG_USBDEV_RX_PRIO 4
|
||||
#endif
|
||||
#ifndef CONFIG_USBDEV_RX_STACKSIZE
|
||||
#define CONFIG_USBDEV_RX_STACKSIZE 2048
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
|
||||
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
|
||||
#endif
|
||||
@@ -81,16 +60,18 @@
|
||||
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_AUDIO_VERSION
|
||||
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
#define CONFIG_USBDEV_MSC_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
|
||||
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
|
||||
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
|
||||
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
@@ -116,6 +97,12 @@
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
||||
#ifndef CONFIG_USBHOST_PSC_PRIO
|
||||
@@ -127,6 +114,9 @@
|
||||
|
||||
//#define CONFIG_USBHOST_GET_STRING_DESC
|
||||
|
||||
// #define CONFIG_USBHOST_MSOS_ENABLE
|
||||
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
|
||||
|
||||
/* Ep0 max transfer buffer */
|
||||
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
|
||||
|
||||
@@ -154,7 +144,7 @@
|
||||
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
|
||||
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
||||
// #define CONFIG_USB_EHCI_INFO_ENABLE
|
||||
// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
|
||||
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||
// #define CONFIG_USB_EHCI_CONFIGFLAG
|
||||
// #define CONFIG_USB_EHCI_PORT_POWER
|
||||
|
||||
|
||||
@@ -812,6 +812,19 @@ struct audio_cs_ep_ep_general_descriptor {
|
||||
|
||||
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
|
||||
|
||||
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
bNumEndpoints, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_MIDISTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
|
||||
0x00 /* iInterface */
|
||||
|
||||
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT_LEN 0x09
|
||||
|
||||
struct audio_v2_channel_cluster_descriptor {
|
||||
uint8_t bNrChannels;
|
||||
uint32_t bmChannelConfig;
|
||||
@@ -1072,7 +1085,7 @@ struct audio_v2_control_range3_param_block {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
|
||||
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
|
||||
bInterval, /* bInterval */ \
|
||||
0x08, /* bLength */ \
|
||||
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
|
||||
@@ -6,109 +6,71 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_audio.h"
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
struct usbd_audio_volume_info {
|
||||
uint16_t vol_min;
|
||||
uint16_t vol_max;
|
||||
uint16_t vol_res;
|
||||
uint16_t vol_current;
|
||||
struct audio_entity_param {
|
||||
uint32_t wCur;
|
||||
uint32_t wMin;
|
||||
uint32_t wMax;
|
||||
uint32_t wRes;
|
||||
};
|
||||
|
||||
struct usbd_audio_attribute_control {
|
||||
struct usbd_audio_volume_info volume[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
uint8_t automatic_gain[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
};
|
||||
#else
|
||||
struct audio_v2_control_range2_param_block_default {
|
||||
uint16_t wNumSubRanges;
|
||||
struct
|
||||
{
|
||||
uint16_t wMin;
|
||||
uint16_t wMax;
|
||||
uint16_t wRes;
|
||||
} subrange[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
} __PACKED;
|
||||
struct usbd_audio_priv {
|
||||
struct audio_entity_info *table;
|
||||
uint8_t num;
|
||||
uint16_t uac_version;
|
||||
} g_usbd_audio;
|
||||
|
||||
struct usbd_audio_attribute_control {
|
||||
uint32_t volume_bCUR;
|
||||
uint32_t mute_bCUR;
|
||||
struct audio_v2_control_range2_param_block_default volume;
|
||||
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
};
|
||||
#endif
|
||||
struct audio_entity_info {
|
||||
usb_slist_t list;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bEntityId;
|
||||
void *priv[2];
|
||||
};
|
||||
|
||||
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t control_selector;
|
||||
uint32_t sampling_freq = 0;
|
||||
uint8_t pitch_enable;
|
||||
uint8_t ep;
|
||||
|
||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
|
||||
control_selector = HI_BYTE(setup->wValue);
|
||||
ep = LO_BYTE(setup->wIndex);
|
||||
control_selector = HI_BYTE(setup->wValue);
|
||||
ep = LO_BYTE(setup->wIndex);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
|
||||
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
||||
USB_LOG_DBG("Set ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(0, ep, sampling_freq);
|
||||
break;
|
||||
case AUDIO_EP_CONTROL_PITCH:
|
||||
pitch_enable = (*data)[0];
|
||||
usbd_audio_set_pitch(ep, pitch_enable);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
sampling_freq = 16000;
|
||||
memcpy(*data, &sampling_freq, 4);
|
||||
*len = 4;
|
||||
USB_LOG_DBG("Get ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
switch (control_selector) {
|
||||
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
||||
memcpy(*data, &sampling_freq, 3);
|
||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
*len = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("AUDIO Class request: "
|
||||
USB_LOG_DBG("Audio Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
struct audio_entity_info *current_entity_info = NULL;
|
||||
struct usbd_audio_attribute_control *current_feature_control = NULL;
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
uint32_t *sampling_freq;
|
||||
#endif
|
||||
usb_slist_t *i;
|
||||
uint8_t entity_id;
|
||||
uint8_t ep;
|
||||
uint8_t subtype = 0x01;
|
||||
uint8_t control_selector;
|
||||
uint8_t ch;
|
||||
uint8_t mute;
|
||||
uint16_t volume;
|
||||
int volume_db = 0;
|
||||
uint32_t sampling_freq = 0;
|
||||
|
||||
const char *mute_string[2] = { "off", "on" };
|
||||
|
||||
entity_id = HI_BYTE(setup->wIndex);
|
||||
@@ -116,211 +78,189 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
||||
ch = LO_BYTE(setup->wValue);
|
||||
|
||||
ARG_UNUSED(mute_string);
|
||||
if (ch > (CONFIG_USBDEV_AUDIO_MAX_CHANNEL - 1)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
usb_slist_for_each(i, &usbd_audio_entity_info_head)
|
||||
{
|
||||
struct audio_entity_info *tmp_entity_info = usb_slist_entry(i, struct audio_entity_info, list);
|
||||
if (tmp_entity_info->bEntityId == entity_id) {
|
||||
current_entity_info = tmp_entity_info;
|
||||
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
|
||||
if (g_usbd_audio.table[i].bEntityId == entity_id) {
|
||||
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
|
||||
ep = g_usbd_audio.table[i].ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_entity_info == NULL) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
sampling_freq = (uint32_t *)current_entity_info->priv[1];
|
||||
#endif
|
||||
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
float volume2db = 0.0;
|
||||
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
mute = (*data)[0];
|
||||
current_feature_control->mute[ch] = mute;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
|
||||
usbd_audio_set_mute(entity_id, ch, mute);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
(*data)[0] = current_feature_control->mute[ch];
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
|
||||
current_feature_control->volume[ch].vol_current = volume;
|
||||
|
||||
if (volume < 0x8000) {
|
||||
volume2db = 0.00390625 * volume;
|
||||
} else if (volume > 0x8000) {
|
||||
volume2db = -0.00390625 * (0xffff - volume + 1);
|
||||
}
|
||||
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] %0.4f dB\r\n", entity_id, ch, volume2db);
|
||||
usbd_audio_set_volume(entity_id, ch, volume2db);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_current, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_min, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_max, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_res, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_SET_RES:
|
||||
memcpy(¤t_feature_control->volume[ch].vol_res, *data, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = current_feature_control->mute_bCUR;
|
||||
*len = 1;
|
||||
} else {
|
||||
mute = (*data)[0];
|
||||
current_feature_control->mute_bCUR = mute;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
|
||||
usbd_audio_set_mute(entity_id, ch, mute);
|
||||
}
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = current_feature_control->volume_bCUR & 0XFF;
|
||||
(*data)[1] = (current_feature_control->volume_bCUR >> 8) & 0xff;
|
||||
*len = 2;
|
||||
} else {
|
||||
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
|
||||
current_feature_control->volume_bCUR = volume;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] %d dB\r\n", entity_id, ch, volume);
|
||||
usbd_audio_set_volume(entity_id, ch, volume);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
*((uint16_t *)(*data + 0)) = current_feature_control->volume.wNumSubRanges;
|
||||
*((uint16_t *)(*data + 2)) = current_feature_control->volume.subrange[ch].wMin;
|
||||
*((uint16_t *)(*data + 4)) = current_feature_control->volume.subrange[ch].wMax;
|
||||
*((uint16_t *)(*data + 6)) = current_feature_control->volume.subrange[ch].wRes;
|
||||
*len = 8;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
else if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
memcpy(*data, &sampling_freq[ch], sizeof(uint32_t));
|
||||
USB_LOG_DBG("Get ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
|
||||
*len = 4;
|
||||
} else {
|
||||
memcpy(&sampling_freq[ch], *data, setup->wLength);
|
||||
USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
|
||||
usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq[ch]);
|
||||
}
|
||||
break;
|
||||
case AUDIO_CS_CONTROL_CLOCK_VALID:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = 1;
|
||||
*len = 1;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
uint8_t *sampling_freq_table = NULL;
|
||||
uint16_t num;
|
||||
|
||||
usbd_audio_get_sampling_freq_table(entity_id, &sampling_freq_table);
|
||||
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
||||
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
||||
*len = (12 * num + 2);
|
||||
USB_LOG_DBG("Get sampling_freq_table entity_id:%d ch[%d] addr:%x\r\n", entity_id, ch, (uint32_t)sampling_freq_table);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (subtype == 0x01) {
|
||||
USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
|
||||
|
||||
switch (subtype) {
|
||||
case AUDIO_CONTROL_FEATURE_UNIT:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
if (g_usbd_audio.uac_version < 0x0200) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
mute = (*data)[0];
|
||||
usbd_audio_set_mute(ep, ch, mute);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
||||
*len = 1;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
||||
*len = 1;
|
||||
} else {
|
||||
mute = (*data)[0];
|
||||
usbd_audio_set_mute(ep, ch, mute);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (g_usbd_audio.uac_version < 0x0200) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
memcpy(&volume, *data, *len);
|
||||
if (volume < 0x8000) {
|
||||
volume_db = volume / 256;
|
||||
} else if (volume > 0x8000) {
|
||||
volume_db = (0xffff - volume + 1) / -256;
|
||||
}
|
||||
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(ep, ch, volume_db);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
volume_db = usbd_audio_get_volume(ep, ch);
|
||||
volume_db -= 128;
|
||||
if (volume_db >= 0) {
|
||||
volume = volume_db * 256;
|
||||
} else {
|
||||
volume = volume_db * 256 + 0xffff + 1;
|
||||
}
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
(*data)[0] = 0x00; /* -2560/256 dB */
|
||||
(*data)[1] = 0xdb;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
(*data)[0] = 0x00; /* 0 dB */
|
||||
(*data)[1] = 0x00;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
(*data)[0] = 0x00; /* -256/256 dB */
|
||||
(*data)[1] = 0x01;
|
||||
*len = 2;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
volume_db = usbd_audio_get_volume(ep, ch);
|
||||
volume = volume_db;
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
} else {
|
||||
memcpy(&volume, *data, *len);
|
||||
volume_db = volume;
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
|
||||
usbd_audio_set_volume(ep, ch, volume_db);
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
*((uint16_t *)(*data + 0)) = 1;
|
||||
*((uint16_t *)(*data + 2)) = 0;
|
||||
*((uint16_t *)(*data + 4)) = 100;
|
||||
*((uint16_t *)(*data + 6)) = 1;
|
||||
*len = 8;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_CONTROL_CLOCK_SOURCE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
||||
memcpy(*data, &sampling_freq, 4);
|
||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
*len = 4;
|
||||
} else {
|
||||
memcpy(&sampling_freq, *data, setup->wLength);
|
||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
uint8_t *sampling_freq_table = NULL;
|
||||
uint16_t num;
|
||||
|
||||
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
|
||||
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
||||
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
||||
*len = (12 * num + 2);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_CS_CONTROL_CLOCK_VALID:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = 1;
|
||||
*len = 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -333,7 +273,7 @@ static void audio_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
case USBD_EVENT_SET_INTERFACE: {
|
||||
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
||||
if (intf->bAlternateSetting == 1) {
|
||||
if (intf->bAlternateSetting) {
|
||||
usbd_audio_open(intf->bInterfaceNumber);
|
||||
} else {
|
||||
usbd_audio_close(intf->bInterfaceNumber);
|
||||
@@ -347,86 +287,57 @@ static void audio_notify_handler(uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf)
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
||||
uint16_t uac_version,
|
||||
struct audio_entity_info *table,
|
||||
uint8_t num)
|
||||
{
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
|
||||
#else
|
||||
intf->class_endpoint_handler = NULL;
|
||||
#endif
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
if (uac_version < 0x0200) {
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
} else {
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
}
|
||||
|
||||
g_usbd_audio.uac_version = uac_version;
|
||||
g_usbd_audio.table = table;
|
||||
g_usbd_audio.num = num;
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
|
||||
{
|
||||
struct audio_entity_info *entity_info = usb_malloc(sizeof(struct audio_entity_info));
|
||||
memset(entity_info, 0, sizeof(struct audio_entity_info));
|
||||
entity_info->bEntityId = entity_id;
|
||||
entity_info->bDescriptorSubtype = bDescriptorSubtype;
|
||||
|
||||
if (bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
|
||||
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
|
||||
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
control->volume[ch].vol_min = 0xdb00;
|
||||
control->volume[ch].vol_max = 0x0000;
|
||||
control->volume[ch].vol_res = 0x0100;
|
||||
control->volume[ch].vol_current = 0xf600;
|
||||
control->mute[ch] = 0;
|
||||
control->automatic_gain[ch] = 0;
|
||||
}
|
||||
#else
|
||||
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
|
||||
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
|
||||
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
control->volume.wNumSubRanges = 1;
|
||||
control->volume.subrange[ch].wMin = 0;
|
||||
control->volume.subrange[ch].wMax = 100;
|
||||
control->volume.subrange[ch].wRes = 1;
|
||||
control->mute[ch] = 0;
|
||||
control->volume_bCUR = 0;
|
||||
control->mute_bCUR = 0;
|
||||
}
|
||||
#endif
|
||||
entity_info->priv[0] = control;
|
||||
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
|
||||
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
sampling_freq[ch] = 16000;
|
||||
}
|
||||
entity_info->priv[1] = sampling_freq;
|
||||
#else
|
||||
entity_info->priv[1] = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB)
|
||||
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
|
||||
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
}
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
|
||||
{
|
||||
}
|
||||
@@ -12,17 +12,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct audio_entity_info {
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bEntityId;
|
||||
uint8_t ep;
|
||||
};
|
||||
|
||||
/* Init audio interface driver */
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf);
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
||||
uint16_t uac_version,
|
||||
struct audio_entity_info *table,
|
||||
uint8_t num);
|
||||
|
||||
void usbd_audio_open(uint8_t intf);
|
||||
void usbd_audio_close(uint8_t intf);
|
||||
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
|
||||
void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB);
|
||||
void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable);
|
||||
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq);
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table);
|
||||
void usbd_audio_set_pitch(uint8_t ep, bool enable);
|
||||
|
||||
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
|
||||
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
|
||||
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
|
||||
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
|
||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
|
||||
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -17,33 +17,38 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
#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 int usbh_audio_devno_alloc(struct usbh_audio *audio_class)
|
||||
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_audio *usbh_audio_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
audio_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; 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];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_audio_devno_free(struct usbh_audio *audio_class)
|
||||
static void usbh_audio_class_free(struct usbh_audio *audio_class)
|
||||
{
|
||||
int devno = audio_class->minor;
|
||||
|
||||
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)
|
||||
@@ -269,14 +274,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
uint8_t format_offset = 0;
|
||||
uint8_t *p;
|
||||
|
||||
struct usbh_audio *audio_class = usb_malloc(sizeof(struct usbh_audio));
|
||||
struct usbh_audio *audio_class = usbh_audio_class_alloc();
|
||||
if (audio_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc audio_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
usbh_audio_devno_alloc(audio_class);
|
||||
audio_class->hport = hport;
|
||||
audio_class->ctrl_intf = intf;
|
||||
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
|
||||
@@ -412,8 +415,6 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_audio *audio_class = (struct usbh_audio *)hport->config.intf[intf].priv;
|
||||
|
||||
if (audio_class) {
|
||||
usbh_audio_devno_free(audio_class);
|
||||
|
||||
if (audio_class->isoin) {
|
||||
usbh_pipe_free(audio_class->isoin);
|
||||
}
|
||||
@@ -427,8 +428,7 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_audio_stop(audio_class);
|
||||
}
|
||||
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
usb_free(audio_class);
|
||||
usbh_audio_class_free(audio_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -212,6 +212,57 @@
|
||||
#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
|
||||
#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
|
||||
|
||||
#define CDC_ECM_XMIT_OK (1 << 0)
|
||||
#define CDC_ECM_RVC_OK (1 << 1)
|
||||
#define CDC_ECM_XMIT_ERROR (1 << 2)
|
||||
#define CDC_ECM_RCV_ERROR (1 << 3)
|
||||
#define CDC_ECM_RCV_NO_BUFFER (1 << 4)
|
||||
#define CDC_ECM_DIRECTED_BYTES_XMIT (1 << 5)
|
||||
#define CDC_ECM_DIRECTED_FRAMES_XMIT (1 << 6)
|
||||
#define CDC_ECM_MULTICAST_BYTES_XMIT (1 << 7)
|
||||
#define CDC_ECM_MULTICAST_FRAMES_XMIT (1 << 8)
|
||||
#define CDC_ECM_BROADCAST_BYTES_XMIT (1 << 9)
|
||||
#define CDC_ECM_BROADCAST_FRAMES_XMIT (1 << 10)
|
||||
#define CDC_ECM_DIRECTED_BYTES_RCV (1 << 11)
|
||||
#define CDC_ECM_DIRECTED_FRAMES_RCV (1 << 12)
|
||||
#define CDC_ECM_MULTICAST_BYTES_RCV (1 << 13)
|
||||
#define CDC_ECM_MULTICAST_FRAMES_RCV (1 << 14)
|
||||
#define CDC_ECM_BROADCAST_BYTES_RCV (1 << 15)
|
||||
#define CDC_ECM_BROADCAST_FRAMES_RCV (1 << 16)
|
||||
#define CDC_ECM_RCV_CRC_ERROR (1 << 17)
|
||||
#define CDC_ECM_TRANSMIT_QUEUE_LENGTH (1 << 18)
|
||||
#define CDC_ECM_RCV_ERROR_ALIGNMENT (1 << 19)
|
||||
#define CDC_ECM_XMIT_ONE_COLLISION (1 << 20)
|
||||
#define CDC_ECM_XMIT_MORE_COLLISIONS (1 << 21)
|
||||
#define CDC_ECM_XMIT_DEFERRED (1 << 22)
|
||||
#define CDC_ECM_XMIT_MAX_COLLISIONS (1 << 23)
|
||||
#define CDC_ECM_RCV_OVERRUN (1 << 24)
|
||||
#define CDC_ECM_XMIT_UNDERRUN (1 << 25)
|
||||
#define CDC_ECM_XMIT_HEARTBEAT_FAILURE (1 << 26)
|
||||
#define CDC_ECM_XMIT_TIMES_CRS_LOST (1 << 27)
|
||||
#define CDC_ECM_XMIT_LATE_COLLISIONS (1 << 28)
|
||||
|
||||
#define CDC_ECM_MAC_STR_DESC (uint8_t *)"010202030000"
|
||||
#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
|
||||
#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
|
||||
#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
|
||||
#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
|
||||
#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
|
||||
#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
|
||||
|
||||
#define CDC_ECM_NET_DISCONNECTED 0x00U
|
||||
#define CDC_ECM_NET_CONNECTED 0x01U
|
||||
|
||||
#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
|
||||
#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
|
||||
|
||||
#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
|
||||
#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
|
||||
|
||||
#define CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION 0x00
|
||||
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
|
||||
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Structures based on usbcdc11.pdf (www.usb.org)
|
||||
*----------------------------------------------------------------------------*/
|
||||
@@ -299,11 +350,19 @@ struct cdc_ecm_descriptor {
|
||||
uint8_t bNumberPowerFilters;
|
||||
} __PACKED;
|
||||
|
||||
struct cdc_ecm_notification {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bNotificationType;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
uint8_t data[8];
|
||||
} __PACKED;
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
|
||||
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
@@ -359,24 +418,100 @@ struct cdc_ecm_descriptor {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#else
|
||||
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
|
||||
// clang-format on
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
|
||||
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -384,8 +519,8 @@ struct cdc_ecm_descriptor {
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
|
||||
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -393,23 +528,23 @@ struct cdc_ecm_descriptor {
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x02, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
/* CDC_ECM Functional Descriptor */ \
|
||||
0x0D, /* bFunctionLength */\
|
||||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
|
||||
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
|
||||
str_idx, /* Device's MAC string index */\
|
||||
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
|
||||
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
|
||||
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
|
||||
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -424,151 +559,14 @@ struct cdc_ecm_descriptor {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#else
|
||||
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_CDC_H */
|
||||
|
||||
@@ -16,7 +16,6 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
setup->bRequest);
|
||||
|
||||
struct cdc_line_coding line_coding;
|
||||
struct cdc_line_coding line_coding_last;
|
||||
bool dtr, rts;
|
||||
uint8_t intf_num = LO_BYTE(setup->wIndex);
|
||||
|
||||
@@ -48,15 +47,10 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
parity_name[line_coding.bParityType],
|
||||
stop_name[line_coding.bCharFormat]);
|
||||
|
||||
/* check if current line coding is the same with last, if they are the same, do not set line coding */
|
||||
usbd_cdc_acm_get_line_coding(intf_num, &line_coding_last);
|
||||
if (memcmp(&line_coding_last, &line_coding, sizeof(struct cdc_line_coding))) {
|
||||
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
|
||||
}
|
||||
|
||||
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE: {
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||
dtr = (setup->wValue & 0x0001);
|
||||
rts = (setup->wValue & 0x0002);
|
||||
USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
|
||||
@@ -65,7 +59,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
rts);
|
||||
usbd_cdc_acm_set_dtr(intf_num, dtr);
|
||||
usbd_cdc_acm_set_rts(intf_num, rts);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_GET_LINE_CODING:
|
||||
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
|
||||
@@ -78,7 +72,9 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
line_coding.bParityType,
|
||||
line_coding.bDataBits);
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SEND_BREAK:
|
||||
usbd_cdc_acm_send_break(intf_num);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
@@ -115,4 +111,8 @@ __WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_cod
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
237
class/cdc/usbd_cdc_ecm.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2023, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#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
|
||||
|
||||
/* Describe EndPoints configuration */
|
||||
static struct usbd_endpoint cdc_ecm_ep_data[3];
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_ECM_MAX_PACKET_SIZE 512
|
||||
#else
|
||||
#define CDC_ECM_MAX_PACKET_SIZE 64
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
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;
|
||||
|
||||
static volatile uint8_t g_current_net_status = 0;
|
||||
static volatile uint8_t g_cmd_intf = 0;
|
||||
|
||||
static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
|
||||
CDC_ECM_CONNECT_SPEED_DOWNSTREAM };
|
||||
|
||||
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
|
||||
{
|
||||
struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
|
||||
uint8_t bytes2send = 0;
|
||||
|
||||
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
|
||||
notify->bNotificationType = notifycode;
|
||||
|
||||
switch (notifycode) {
|
||||
case CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION:
|
||||
notify->wValue = value;
|
||||
notify->wIndex = g_cmd_intf;
|
||||
notify->wLength = 0U;
|
||||
|
||||
for (uint8_t i = 0U; i < 8U; i++) {
|
||||
notify->data[i] = 0U;
|
||||
}
|
||||
bytes2send = 8U;
|
||||
break;
|
||||
case CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE:
|
||||
notify->wValue = 0U;
|
||||
notify->wIndex = g_cmd_intf;
|
||||
notify->wLength = 0U;
|
||||
for (uint8_t i = 0U; i < 8U; i++) {
|
||||
notify->data[i] = 0U;
|
||||
}
|
||||
bytes2send = 8U;
|
||||
break;
|
||||
case CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE:
|
||||
notify->wValue = 0U;
|
||||
notify->wIndex = g_cmd_intf;
|
||||
notify->wLength = 0x0008U;
|
||||
bytes2send = 16U;
|
||||
|
||||
memcpy(notify->data, speed, 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes2send) {
|
||||
usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
|
||||
}
|
||||
}
|
||||
|
||||
static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("CDC ECM Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
g_cmd_intf = LO_BYTE(setup->wIndex);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
|
||||
/* bit0 Promiscuous
|
||||
* bit1 ALL Multicast
|
||||
* bit2 Directed
|
||||
* bit3 Broadcast
|
||||
* bit4 Multicast
|
||||
*/
|
||||
if (g_current_net_status == 0) {
|
||||
g_current_net_status = 1;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cdc_ecm_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_current_net_status = 0;
|
||||
g_cdc_ecm_rx_data_length = 0;
|
||||
g_cdc_ecm_tx_data_length = 0;
|
||||
g_cdc_ecm_rx_data_buffer = NULL;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
g_cdc_ecm_rx_data_length += nbytes;
|
||||
|
||||
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
|
||||
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
|
||||
usbd_cdc_ecm_data_recv_done();
|
||||
} else {
|
||||
usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(ep, NULL, 0);
|
||||
} else {
|
||||
g_cdc_ecm_tx_data_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if (g_current_net_status == 1) {
|
||||
g_current_net_status = 2;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
struct pbuf *usbd_cdc_ecm_eth_rx(void)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
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) {
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
g_cdc_ecm_rx_data_length = 0;
|
||||
g_cdc_ecm_rx_data_buffer = NULL;
|
||||
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int usbd_cdc_ecm_eth_tx(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
|
||||
if (g_cdc_ecm_tx_data_length > 0) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
|
||||
p->tot_len = sizeof(g_cdc_ecm_tx_buffer);
|
||||
}
|
||||
|
||||
buffer = g_cdc_ecm_tx_buffer;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
g_cdc_ecm_tx_data_length = p->tot_len;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
|
||||
return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
intf->class_interface_handler = cdc_ecm_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = cdc_ecm_notify_handler;
|
||||
|
||||
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr = out_ep;
|
||||
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_cb = cdc_ecm_bulk_out;
|
||||
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr = in_ep;
|
||||
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_cb = cdc_ecm_bulk_in;
|
||||
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
|
||||
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
|
||||
|
||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
|
||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
|
||||
{
|
||||
memcpy(g_connect_speed_table, speed, 8);
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_ecm_data_recv_done(void)
|
||||
{
|
||||
}
|
||||
36
class/cdc/usbd_cdc_ecm.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_CDC_ECM_H
|
||||
#define USBD_CDC_ECM_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Ethernet Maximum Segment size, typically 1514 bytes */
|
||||
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
|
||||
/* Init cdc ecm interface driver */
|
||||
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
|
||||
void usbd_cdc_ecm_data_recv_done(void);
|
||||
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
#include <lwip/pbuf.h>
|
||||
struct pbuf *usbd_cdc_ecm_eth_rx(void);
|
||||
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_CDC_ECM_H */
|
||||
@@ -8,32 +8,34 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyACM%d"
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
|
||||
|
||||
static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *cdc_acm_class)
|
||||
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
cdc_acm_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; 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];
|
||||
}
|
||||
}
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *cdc_acm_class)
|
||||
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
int devno = cdc_acm_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
@@ -91,14 +93,12 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_cdc_acm *cdc_acm_class = usb_malloc(sizeof(struct usbh_cdc_acm));
|
||||
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
|
||||
if (cdc_acm_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
|
||||
usbh_cdc_acm_devno_alloc(cdc_acm_class);
|
||||
cdc_acm_class->hport = hport;
|
||||
cdc_acm_class->ctrl_intf = intf;
|
||||
cdc_acm_class->data_intf = intf + 1;
|
||||
@@ -151,8 +151,6 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv;
|
||||
|
||||
if (cdc_acm_class) {
|
||||
usbh_cdc_acm_devno_free(cdc_acm_class);
|
||||
|
||||
if (cdc_acm_class->bulkin) {
|
||||
usbh_pipe_free(cdc_acm_class->bulkin);
|
||||
}
|
||||
@@ -166,8 +164,7 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_cdc_acm_stop(cdc_acm_class);
|
||||
}
|
||||
|
||||
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
|
||||
usb_free(cdc_acm_class);
|
||||
usbh_cdc_acm_class_free(cdc_acm_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
330
class/cdc/usbh_cdc_ecm.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_cdc_ecm.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/cdc_ether"
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
|
||||
|
||||
/* interface descriptor field offsets */
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
|
||||
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
|
||||
|
||||
static struct usbh_cdc_ecm g_cdc_ecm_class;
|
||||
|
||||
static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class, uint16_t filter_value)
|
||||
{
|
||||
struct usb_setup_packet *setup = cdc_ecm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
|
||||
setup->wValue = filter_value;
|
||||
setup->wIndex = cdc_ecm_class->ctrl_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(cdc_ecm_class->hport->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_cdc_ecm_get_notification(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_ecm_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
|
||||
cdc_ecm_class->connect_status = g_cdc_ecm_inttx_buffer[2];
|
||||
} else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
|
||||
memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint8_t altsetting = 0;
|
||||
char mac_buffer[12];
|
||||
uint8_t *p;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t mac_str_idx = 0xff;
|
||||
|
||||
struct usbh_cdc_ecm *cdc_ecm_class = &g_cdc_ecm_class;
|
||||
|
||||
cdc_ecm_class->hport = hport;
|
||||
cdc_ecm_class->ctrl_intf = intf;
|
||||
cdc_ecm_class->data_intf = intf + 1;
|
||||
|
||||
hport->config.intf[intf].priv = cdc_ecm_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
p = hport->raw_config_desc;
|
||||
while (p[DESC_bLength]) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
|
||||
break;
|
||||
case CDC_CS_INTERFACE:
|
||||
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
||||
struct cdc_ecm_descriptor *desc = (struct cdc_ecm_descriptor *)p;
|
||||
mac_str_idx = desc->iMACAddress;
|
||||
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
|
||||
goto get_mac;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
}
|
||||
|
||||
get_mac:
|
||||
if (mac_str_idx == 0xff) {
|
||||
USB_LOG_ERR("Do not find cdc ecm mac string\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mac_buffer, 0, 8);
|
||||
ret = usbh_get_string_desc(cdc_ecm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < 12; i += 2, j++) {
|
||||
char byte_str[3];
|
||||
byte_str[0] = mac_buffer[i];
|
||||
byte_str[1] = mac_buffer[i + 1];
|
||||
byte_str[2] = '\0';
|
||||
|
||||
uint32_t byte = strtoul(byte_str, NULL, 16);
|
||||
cdc_ecm_class->mac[j] = (unsigned char)byte;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("CDC ECM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
cdc_ecm_class->mac[0],
|
||||
cdc_ecm_class->mac[1],
|
||||
cdc_ecm_class->mac[2],
|
||||
cdc_ecm_class->mac[3],
|
||||
cdc_ecm_class->mac[4],
|
||||
cdc_ecm_class->mac[5]);
|
||||
|
||||
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE) {
|
||||
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE, cdc_ecm_class->max_segment_size);
|
||||
} else {
|
||||
USB_LOG_INFO("CDC ECM Max Segment Size:%u\r\n", cdc_ecm_class->max_segment_size);
|
||||
}
|
||||
|
||||
/* enable int ep */
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->intin, hport, ep_desc);
|
||||
|
||||
if (hport->config.intf[intf + 1].altsetting_num > 1) {
|
||||
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Select cdc ecm altsetting: %d\r\n", altsetting);
|
||||
usbh_set_interface(cdc_ecm_class->hport, cdc_ecm_class->data_intf, altsetting);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* bit0 Promiscuous
|
||||
* bit1 ALL Multicast
|
||||
* bit2 Directed
|
||||
* bit3 Broadcast
|
||||
* bit4 Multicast
|
||||
*/
|
||||
ret = usbh_cdc_ecm_set_eth_packet_filter(cdc_ecm_class, CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("Set CDC ECM packet filter:%04x\r\n", CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_cdc_ecm_run(cdc_ecm_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)hport->config.intf[intf].priv;
|
||||
|
||||
if (cdc_ecm_class) {
|
||||
if (cdc_ecm_class->bulkin) {
|
||||
usbh_pipe_free(cdc_ecm_class->bulkin);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->bulkout) {
|
||||
usbh_pipe_free(cdc_ecm_class->bulkout);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->intin) {
|
||||
usbh_pipe_free(cdc_ecm_class->intin);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_cdc_ecm_stop(cdc_ecm_class);
|
||||
}
|
||||
|
||||
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usbh_cdc_ecm_rx_thread(void *argument)
|
||||
{
|
||||
uint32_t g_cdc_ecm_rx_length;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
uint16_t ep_mps;
|
||||
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
while (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
|
||||
usb_osal_msleep(1000);
|
||||
}
|
||||
|
||||
while (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
|
||||
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_class.hport->speed == USB_SPEED_FULL) {
|
||||
ep_mps = 64;
|
||||
} else {
|
||||
ep_mps = 512;
|
||||
}
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
|
||||
|
||||
if (g_cdc_ecm_rx_length % ep_mps) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer = g_cdc_ecm_tx_buffer;
|
||||
|
||||
if (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
|
||||
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif)
|
||||
{
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, netif);
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_ecm_class_driver = {
|
||||
.driver_name = "cdc_ecm",
|
||||
.connect = usbh_cdc_ecm_connect,
|
||||
.disconnect = usbh_cdc_ecm_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_CDC,
|
||||
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
|
||||
.protocol = CDC_COMMON_PROTOCOL_NONE,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &cdc_ecm_class_driver
|
||||
};
|
||||
50
class/cdc/usbh_cdc_ecm.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_CDC_ECM_H
|
||||
#define USBH_CDC_ECM_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
struct usbh_cdc_ecm {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
uint8_t mac[6];
|
||||
uint32_t max_segment_size;
|
||||
uint8_t connect_status;
|
||||
uint32_t speed[2];
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint */
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb intin_urb;
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_CDC_ACM_H */
|
||||
@@ -23,7 +23,7 @@
|
||||
#define FLASH_ERASE_TIME 50
|
||||
#endif
|
||||
|
||||
struct dfu_cfg_priv {
|
||||
struct usbd_dfu_priv {
|
||||
struct dfu_info info;
|
||||
union {
|
||||
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
|
||||
@@ -40,26 +40,26 @@ struct dfu_cfg_priv {
|
||||
uint8_t dev_state;
|
||||
uint8_t manif_state;
|
||||
uint8_t firmwar_flag;
|
||||
} usbd_dfu_cfg;
|
||||
} g_usbd_dfu;
|
||||
|
||||
static void dfu_reset(void)
|
||||
{
|
||||
memset(&usbd_dfu_cfg, 0, sizeof(usbd_dfu_cfg));
|
||||
memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
|
||||
|
||||
usbd_dfu_cfg.alt_setting = 0U;
|
||||
usbd_dfu_cfg.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
g_usbd_dfu.alt_setting = 0U;
|
||||
g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[5] = 0U;
|
||||
}
|
||||
|
||||
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
|
||||
@@ -84,21 +84,21 @@ static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
|
||||
|
||||
static void dfu_request_detach(void)
|
||||
{
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /*iString*/
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
g_usbd_dfu.dev_status[5] = 0U; /*iString*/
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,62 +109,62 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
uint8_t *phaddr;
|
||||
/* Data setup request */
|
||||
if (req->wLength > 0U) {
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
/* Update the global length and block number */
|
||||
usbd_dfu_cfg.wblock_num = req->wValue;
|
||||
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
g_usbd_dfu.wblock_num = req->wValue;
|
||||
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
|
||||
/* DFU Get Command */
|
||||
if (usbd_dfu_cfg.wblock_num == 0U) {
|
||||
if (g_usbd_dfu.wblock_num == 0U) {
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = (usbd_dfu_cfg.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/* Store the values of all supported commands */
|
||||
usbd_dfu_cfg.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
|
||||
usbd_dfu_cfg.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
|
||||
usbd_dfu_cfg.buffer.d8[2] = DFU_CMD_ERASE;
|
||||
g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
|
||||
g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
|
||||
g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.buffer.d8, 3);
|
||||
memcpy(*data, g_usbd_dfu.buffer.d8, 3);
|
||||
*len = 3;
|
||||
} else if (usbd_dfu_cfg.wblock_num > 1U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
} else if (g_usbd_dfu.wblock_num > 1U) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
|
||||
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
|
||||
|
||||
/* Return the physical address where data are stored */
|
||||
phaddr = dfu_read_flash((uint8_t *)addr, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
|
||||
phaddr = dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
|
||||
*len = usbd_dfu_cfg.wlength;
|
||||
} else /* unsupported usbd_dfu_cfg.wblock_num */
|
||||
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
*len = g_usbd_dfu.wlength;
|
||||
} else /* unsupported g_usbd_dfu.wblock_num */
|
||||
{
|
||||
usbd_dfu_cfg.dev_state = DFU_STATUS_ERR_STALLEDPKT;
|
||||
g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported usbd_dfu_cfg.wblock_num\r\n");
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
|
||||
}
|
||||
}
|
||||
/* Unsupported state */
|
||||
else {
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
|
||||
@@ -172,12 +172,12 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
}
|
||||
/* No Data setup request */
|
||||
else {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,19 +186,19 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
/* Data setup request */
|
||||
struct usb_setup_packet *req = setup;
|
||||
if (req->wLength > 0U) {
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
|
||||
/* Update the global length and block number */
|
||||
usbd_dfu_cfg.wblock_num = req->wValue;
|
||||
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
g_usbd_dfu.wblock_num = req->wValue;
|
||||
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/*!< Data has received complete */
|
||||
memcpy((uint8_t *)usbd_dfu_cfg.buffer.d8, (uint8_t *)*data, usbd_dfu_cfg.wlength);
|
||||
memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
|
||||
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
|
||||
usbd_dfu_cfg.firmwar_flag = 1;
|
||||
g_usbd_dfu.firmwar_flag = 1;
|
||||
}
|
||||
/* Unsupported state */
|
||||
else {
|
||||
@@ -208,16 +208,16 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
/* 0 Data DNLOAD request */
|
||||
else {
|
||||
/* End of DNLOAD operation*/
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE)) {
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_IN_PROGRESS;
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
} else {
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", usbd_dfu_cfg.dev_state);
|
||||
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,63 +225,63 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
static int8_t dfu_getstatus_special_handler(void)
|
||||
{
|
||||
uint32_t addr;
|
||||
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
|
||||
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
|
||||
/* Decode the Special Command */
|
||||
if (usbd_dfu_cfg.wblock_num == 0U) {
|
||||
if (usbd_dfu_cfg.wlength == 1U) {
|
||||
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
|
||||
if (g_usbd_dfu.wblock_num == 0U) {
|
||||
if (g_usbd_dfu.wlength == 1U) {
|
||||
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
|
||||
/* Nothing to do */
|
||||
}
|
||||
} else if (usbd_dfu_cfg.wlength == 5U) {
|
||||
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
|
||||
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
|
||||
} else if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE) {
|
||||
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
|
||||
} else if (g_usbd_dfu.wlength == 5U) {
|
||||
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
|
||||
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
|
||||
} else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
|
||||
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
|
||||
|
||||
USB_LOG_DBG("Erase start add %08x \r\n", usbd_dfu_cfg.data_ptr);
|
||||
USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
|
||||
/*!< Erase */
|
||||
dfu_erase_flash(usbd_dfu_cfg.data_ptr);
|
||||
dfu_erase_flash(g_usbd_dfu.data_ptr);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Reset the global length and block number */
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
/* Call the error management function (command will be NAKed) */
|
||||
USB_LOG_ERR("Reset the global length and block number\r\n");
|
||||
}
|
||||
}
|
||||
/* Regular Download Command */
|
||||
else {
|
||||
if (usbd_dfu_cfg.wblock_num > 1U) {
|
||||
if (g_usbd_dfu.wblock_num > 1U) {
|
||||
/* Decode the required address */
|
||||
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
|
||||
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
|
||||
|
||||
/* Perform the write operation */
|
||||
/* Write flash */
|
||||
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, usbd_dfu_cfg.wlength);
|
||||
dfu_write_flash(usbd_dfu_cfg.buffer.d8, (uint8_t *)addr, usbd_dfu_cfg.wlength);
|
||||
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
|
||||
dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the global length and block number */
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -289,77 +289,77 @@ static int8_t dfu_getstatus_special_handler(void)
|
||||
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
/*!< Determine whether to leave DFU mode */
|
||||
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS &&
|
||||
usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
|
||||
usbd_dfu_cfg.dev_status[1] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[2] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[3] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[4] == usbd_dfu_cfg.dev_state) {
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
|
||||
g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
|
||||
g_usbd_dfu.dev_status[1] == 0U &&
|
||||
g_usbd_dfu.dev_status[2] == 0U &&
|
||||
g_usbd_dfu.dev_status[3] == 0U &&
|
||||
g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
|
||||
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
return;
|
||||
} else {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
/* Generate system reset to allow jumping to the user code */
|
||||
dfu_leave();
|
||||
}
|
||||
}
|
||||
|
||||
switch (usbd_dfu_cfg.dev_state) {
|
||||
switch (g_usbd_dfu.dev_state) {
|
||||
case DFU_STATE_DFU_DNLOAD_SYNC:
|
||||
if (usbd_dfu_cfg.wlength != 0U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
|
||||
if (g_usbd_dfu.wlength != 0U) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
if ((usbd_dfu_cfg.wblock_num == 0U) && (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE)) {
|
||||
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_ERASE, usbd_dfu_cfg.dev_status);
|
||||
if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
|
||||
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
|
||||
} else {
|
||||
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_PROGRAM, usbd_dfu_cfg.dev_status);
|
||||
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
|
||||
}
|
||||
} else /* (usbd_dfu_cfg.wlength==0)*/
|
||||
} else /* (g_usbd_dfu.wlength==0)*/
|
||||
{
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case DFU_STATE_DFU_MANIFEST_SYNC:
|
||||
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST;
|
||||
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
} else {
|
||||
if ((usbd_dfu_cfg.manif_state == DFU_MANIFEST_COMPLETE) &&
|
||||
if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
|
||||
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -369,62 +369,62 @@ static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data
|
||||
}
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.dev_status, 6);
|
||||
memcpy(*data, g_usbd_dfu.dev_status, 6);
|
||||
*len = 6;
|
||||
|
||||
if (usbd_dfu_cfg.firmwar_flag == 1) {
|
||||
if (g_usbd_dfu.firmwar_flag == 1) {
|
||||
if (dfu_getstatus_special_handler() != 0) {
|
||||
USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
|
||||
}
|
||||
usbd_dfu_cfg.firmwar_flag = 0;
|
||||
g_usbd_dfu.firmwar_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dfu_request_clrstatus(void)
|
||||
{
|
||||
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_ERROR) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK; /* bStatus */
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
} else {
|
||||
/* State Error */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_ERROR;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
}
|
||||
}
|
||||
|
||||
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
/* Return the current state of the DFU interface */
|
||||
(*data)[0] = usbd_dfu_cfg.dev_state;
|
||||
(*data)[0] = g_usbd_dfu.dev_state;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
void dfu_request_abort(void)
|
||||
{
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,27 +17,27 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
|
||||
switch (setup->bRequest) {
|
||||
case HID_REQUEST_GET_REPORT:
|
||||
/* report id ,report type */
|
||||
usbh_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
||||
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
||||
break;
|
||||
case HID_REQUEST_GET_IDLE:
|
||||
(*data)[0] = usbh_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
|
||||
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_GET_PROTOCOL:
|
||||
(*data)[0] = usbh_hid_get_protocol(intf_num);
|
||||
(*data)[0] = usbd_hid_get_protocol(intf_num);
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_SET_REPORT:
|
||||
/* report id ,report type, report, report len */
|
||||
usbh_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
||||
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
||||
break;
|
||||
case HID_REQUEST_SET_IDLE:
|
||||
/* report id, duration */
|
||||
usbh_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
||||
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
||||
break;
|
||||
case HID_REQUEST_SET_PROTOCOL:
|
||||
/* protocol */
|
||||
usbh_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
|
||||
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -60,30 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
|
||||
return intf;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
__WEAK void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(*data[0]) = 0;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id)
|
||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbh_hid_get_protocol(uint8_t intf)
|
||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
__WEAK void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
|
||||
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
|
||||
{
|
||||
}
|
||||
@@ -20,12 +20,12 @@ void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
|
||||
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
||||
uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id);
|
||||
uint8_t usbh_hid_get_protocol(uint8_t intf);
|
||||
void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
|
||||
void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
|
||||
void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol);
|
||||
void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
||||
uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id);
|
||||
uint8_t usbd_hid_get_protocol(uint8_t intf);
|
||||
void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
|
||||
void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
|
||||
void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -8,33 +8,34 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/input%d"
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
||||
|
||||
static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
|
||||
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)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
hid_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; 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];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_hid_devno_free(struct usbh_hid *hid_class)
|
||||
static void usbh_hid_class_free(struct usbh_hid *hid_class)
|
||||
{
|
||||
int devno = hid_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
}
|
||||
|
||||
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
@@ -106,14 +107,12 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid));
|
||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||
if (hid_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hid_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usbh_hid_devno_alloc(hid_class);
|
||||
hid_class->hport = hport;
|
||||
hid_class->intf = intf;
|
||||
|
||||
@@ -159,8 +158,6 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
|
||||
|
||||
if (hid_class) {
|
||||
usbh_hid_devno_free(hid_class);
|
||||
|
||||
if (hid_class->intin) {
|
||||
usbh_pipe_free(hid_class->intin);
|
||||
}
|
||||
@@ -174,8 +171,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_hid_stop(hid_class);
|
||||
}
|
||||
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usb_free(hid_class);
|
||||
usbh_hid_class_free(hid_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static uint32_t g_devinuse = 0;
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
|
||||
|
||||
@@ -28,9 +24,6 @@ usb_osal_mq_t hub_mq;
|
||||
|
||||
struct usbh_hub roothub;
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
#endif
|
||||
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
@@ -46,26 +39,32 @@ struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int usbh_hub_devno_alloc(void)
|
||||
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_hub *usbh_hub_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
return devno;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; 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];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_hub_devno_free(uint8_t devno)
|
||||
static void usbh_hub_class_free(struct usbh_hub *hub_class)
|
||||
{
|
||||
if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
|
||||
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(hub_class, 0, sizeof(struct usbh_hub));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -109,7 +108,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -131,6 +130,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
@@ -299,7 +299,8 @@ static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
if (nbytes > 0)
|
||||
{
|
||||
usbh_hub_thread_wakeup(hub);
|
||||
}
|
||||
}
|
||||
@@ -309,21 +310,15 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
struct hub_port_status port_status;
|
||||
int ret;
|
||||
int index;
|
||||
|
||||
index = usbh_hub_devno_alloc();
|
||||
if (index > (CONFIG_USBHOST_MAX_EXTHUBS + EXTHUB_FIRST_INDEX - 1)) {
|
||||
USB_LOG_ERR("No memory to alloc hub class\r\n");
|
||||
usbh_hub_devno_free(index);
|
||||
struct usbh_hub *hub = usbh_hub_class_alloc();
|
||||
if (hub == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hub_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
struct usbh_hub *hub = &exthub[index - EXTHUB_FIRST_INDEX];
|
||||
|
||||
memset(hub, 0, sizeof(struct usbh_hub));
|
||||
hub->hub_addr = hport->dev_addr;
|
||||
hub->parent = hport;
|
||||
hub->index = index;
|
||||
|
||||
hport->config.intf[intf].priv = hub;
|
||||
|
||||
@@ -394,8 +389,6 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
|
||||
|
||||
if (hub) {
|
||||
usbh_hub_devno_free(hub->index);
|
||||
|
||||
if (hub->intin) {
|
||||
usbh_pipe_free(hub->intin);
|
||||
}
|
||||
@@ -413,11 +406,12 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
child->parent = NULL;
|
||||
}
|
||||
|
||||
usbh_hub_unregister(hub);
|
||||
memset(hub, 0, sizeof(struct usbh_hub));
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0')
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_hub_unregister(hub);
|
||||
}
|
||||
|
||||
usbh_hub_class_free(hub);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -437,6 +431,21 @@ static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hubport_enumerate_thread(void *argument)
|
||||
{
|
||||
struct usbh_hubport *child = (struct usbh_hubport *)argument;
|
||||
|
||||
/* Configure EP0 with the default maximum packet size */
|
||||
usbh_hport_activate_ep0(child);
|
||||
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
|
||||
}
|
||||
usb_osal_thread_delete(NULL);
|
||||
}
|
||||
|
||||
static void usbh_hub_events(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_hubport *child;
|
||||
@@ -453,9 +462,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
portchange_index = hub->int_buffer[0];
|
||||
portchange_index = hub->int_buffer[0];
|
||||
hub->int_buffer[0] = 0;
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
||||
|
||||
if (!(portchange_index & (1 << (port + 1)))) {
|
||||
@@ -597,14 +607,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
|
||||
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
|
||||
|
||||
/* Configure EP0 with the default maximum packet size */
|
||||
usbh_hport_activate_ep0(child);
|
||||
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1);
|
||||
}
|
||||
/* create disposable thread to enumerate device on current hport, do not block hub thread */
|
||||
child->thread = usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
@@ -624,7 +628,6 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
}
|
||||
}
|
||||
|
||||
hub->int_buffer[0] = 0;
|
||||
/* Start next hub int transfer */
|
||||
if (!hub->is_roothub && hub->connected) {
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
@@ -638,7 +641,7 @@ static void usbh_hub_thread(void *argument)
|
||||
|
||||
usb_hc_init();
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, 0xffffffff);
|
||||
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,26 @@
|
||||
#define MIDI_PITCHBEND_MIN -8192
|
||||
#define MIDI_PITCHBEND_MAX 8191
|
||||
|
||||
/*! Enumeration of MIDI code index number */
|
||||
enum MidiCodeIndexNumber {
|
||||
MIDI_CIN_MISC = 0,
|
||||
MIDI_CIN_CABLE_EVENT = 1,
|
||||
MIDI_CIN_SYSCOM_2BYTE = 2, ///< 2 byte system common message e.g MTC, SongSelect
|
||||
MIDI_CIN_SYSCOM_3BYTE = 3, ///< 3 byte system common message e.g SPP
|
||||
MIDI_CIN_SYSEX_START = 4, ///< SysEx starts or continue
|
||||
MIDI_CIN_SYSEX_END_1BYTE = 5, ///< SysEx ends with 1 data, or 1 byte system common message
|
||||
MIDI_CIN_SYSEX_END_2BYTE = 6, ///< SysEx ends with 2 data
|
||||
MIDI_CIN_SYSEX_END_3BYTE = 7, ///< SysEx ends with 3 data
|
||||
MIDI_CIN_NOTE_OFF = 8,
|
||||
MIDI_CIN_NOTE_ON = 9,
|
||||
MIDI_CIN_POLY_KEYPRESS = 10,
|
||||
MIDI_CIN_CONTROL_CHANGE = 11,
|
||||
MIDI_CIN_PROGRAM_CHANGE = 12,
|
||||
MIDI_CIN_CHANNEL_PRESSURE = 13,
|
||||
MIDI_CIN_PITCH_BEND_CHANGE = 14,
|
||||
MIDI_CIN_1BYTE_DATA = 15
|
||||
};
|
||||
|
||||
/*! Enumeration of MIDI types */
|
||||
enum MidiType {
|
||||
InvalidType = 0x00, ///< For notifying errors
|
||||
@@ -181,6 +201,13 @@ struct midi_cs_ep_ms_general_descriptor {
|
||||
#define MIDI_SIZEOF_MS_GENERAL_DESC(n) (4 + n)
|
||||
|
||||
// clang-format off
|
||||
#define MIDI_CS_HEADER_DESCRIPTOR_INIT(wTotalLength) \
|
||||
0x07, /* bLength */ \
|
||||
USB_CS_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubtype */ \
|
||||
WBVAL(0x0100), /* bcdMSC */ \
|
||||
WBVAL(wTotalLength) /* wTotalLength */
|
||||
|
||||
#define MIDI_IN_JACK_DESCRIPTOR_INIT(bJackType, bJackID) \
|
||||
0x06, \
|
||||
0x24, \
|
||||
|
||||
@@ -61,8 +61,7 @@ struct CSW {
|
||||
/*Length of template descriptor: 23 bytes*/
|
||||
#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -77,39 +76,14 @@ struct CSW {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#else
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
|
||||
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
|
||||
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_MSC_H */
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usb_scsi.h"
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
#define MSD_OUT_EP_IDX 0
|
||||
#define MSD_IN_EP_IDX 1
|
||||
@@ -23,13 +26,14 @@ enum Stage {
|
||||
};
|
||||
|
||||
/* Device data structure */
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
|
||||
/* state of the bulk-only state machine */
|
||||
enum Stage stage;
|
||||
USB_MEM_ALIGNX struct CBW cbw;
|
||||
USB_MEM_ALIGNX struct CSW csw;
|
||||
|
||||
bool readonly;
|
||||
bool popup;
|
||||
uint8_t sKey; /* Sense key */
|
||||
uint8_t ASC; /* Additional Sense Code */
|
||||
uint8_t ASQ; /* Additional Sense Qualifier */
|
||||
@@ -39,13 +43,19 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
||||
uint16_t scsi_blk_size;
|
||||
uint32_t scsi_blk_nbr;
|
||||
|
||||
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||
} usbd_msc_cfg;
|
||||
USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_t usbd_msc_mq;
|
||||
usb_osal_thread_t usbd_msc_thread;
|
||||
uint32_t nbytes;
|
||||
#endif
|
||||
} g_usbd_msc;
|
||||
|
||||
static void usbd_msc_reset(void)
|
||||
{
|
||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||
usbd_msc_cfg.readonly = false;
|
||||
g_usbd_msc.stage = MSC_READ_CBW;
|
||||
g_usbd_msc.readonly = false;
|
||||
}
|
||||
|
||||
static int msc_storage_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
@@ -60,7 +70,7 @@ static int msc_storage_class_interface_request_handler(struct usb_setup_packet *
|
||||
break;
|
||||
|
||||
case MSC_REQUEST_GET_MAX_LUN:
|
||||
(*data)[0] = usbd_msc_cfg.max_lun;
|
||||
(*data)[0] = g_usbd_msc.max_lun;
|
||||
*len = 1;
|
||||
break;
|
||||
|
||||
@@ -80,7 +90,7 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
USB_LOG_DBG("Start reading cbw\r\n");
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -90,40 +100,40 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
static void usbd_msc_bot_abort(void)
|
||||
{
|
||||
if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) {
|
||||
if ((g_usbd_msc.cbw.bmFlags == 0) && (g_usbd_msc.cbw.dDataLength != 0)) {
|
||||
usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
|
||||
}
|
||||
usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
|
||||
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
}
|
||||
|
||||
static void usbd_msc_send_csw(uint8_t CSW_Status)
|
||||
{
|
||||
usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature;
|
||||
usbd_msc_cfg.csw.bStatus = CSW_Status;
|
||||
g_usbd_msc.csw.dSignature = MSC_CSW_Signature;
|
||||
g_usbd_msc.csw.bStatus = CSW_Status;
|
||||
|
||||
/* updating the State Machine , so that we wait CSW when this
|
||||
* transfer is complete, ie when we get a bulk in callback
|
||||
*/
|
||||
usbd_msc_cfg.stage = MSC_WAIT_CSW;
|
||||
g_usbd_msc.stage = MSC_WAIT_CSW;
|
||||
|
||||
USB_LOG_DBG("Send csw\r\n");
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, sizeof(struct CSW));
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.csw, sizeof(struct CSW));
|
||||
}
|
||||
|
||||
static void usbd_msc_send_info(uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
size = MIN(size, usbd_msc_cfg.cbw.dDataLength);
|
||||
size = MIN(size, g_usbd_msc.cbw.dDataLength);
|
||||
|
||||
/* updating the State Machine , so that we send CSW when this
|
||||
* transfer is complete, ie when we get a bulk in callback
|
||||
*/
|
||||
usbd_msc_cfg.stage = MSC_SEND_CSW;
|
||||
g_usbd_msc.stage = MSC_SEND_CSW;
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size);
|
||||
|
||||
usbd_msc_cfg.csw.dDataResidue -= size;
|
||||
usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED;
|
||||
g_usbd_msc.csw.dDataResidue -= size;
|
||||
g_usbd_msc.csw.bStatus = CSW_STATUS_CMD_PASSED;
|
||||
}
|
||||
|
||||
static bool SCSI_processWrite(uint32_t nbytes);
|
||||
@@ -139,9 +149,9 @@ static bool SCSI_processRead(void);
|
||||
*/
|
||||
static void SCSI_SetSenseData(uint32_t KCQ)
|
||||
{
|
||||
usbd_msc_cfg.sKey = (uint8_t)(KCQ >> 16);
|
||||
usbd_msc_cfg.ASC = (uint8_t)(KCQ >> 8);
|
||||
usbd_msc_cfg.ASQ = (uint8_t)(KCQ);
|
||||
g_usbd_msc.sKey = (uint8_t)(KCQ >> 16);
|
||||
g_usbd_msc.ASC = (uint8_t)(KCQ >> 8);
|
||||
g_usbd_msc.ASQ = (uint8_t)(KCQ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +161,7 @@ static void SCSI_SetSenseData(uint32_t KCQ)
|
||||
|
||||
static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
@@ -163,13 +173,13 @@ static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
|
||||
uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
|
||||
@@ -193,9 +203,9 @@ static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
|
||||
0x00,
|
||||
};
|
||||
|
||||
request_sense[2] = usbd_msc_cfg.sKey;
|
||||
request_sense[12] = usbd_msc_cfg.ASC;
|
||||
request_sense[13] = usbd_msc_cfg.ASQ;
|
||||
request_sense[2] = g_usbd_msc.sKey;
|
||||
request_sense[12] = g_usbd_msc.ASC;
|
||||
request_sense[13] = g_usbd_msc.ASQ;
|
||||
#if 0
|
||||
request_sense[ 2] = 0x06; /* UNIT ATTENTION */
|
||||
request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
|
||||
@@ -269,16 +279,16 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
|
||||
memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
|
||||
if (usbd_msc_cfg.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
|
||||
if (g_usbd_msc.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
|
||||
data_len = 0x06;
|
||||
memcpy(*data, (uint8_t *)inquiry00, data_len);
|
||||
} else if (usbd_msc_cfg.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
|
||||
} else if (g_usbd_msc.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
|
||||
data_len = 0x08;
|
||||
memcpy(*data, (uint8_t *)inquiry80, data_len);
|
||||
} else { /* Request Not supported */
|
||||
@@ -286,8 +296,8 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
memcpy(*data, (uint8_t *)inquiry, data_len);
|
||||
}
|
||||
@@ -298,18 +308,19 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
|
||||
if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
|
||||
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_EJECTED;
|
||||
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
|
||||
g_usbd_msc.popup = true;
|
||||
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else {
|
||||
@@ -322,11 +333,11 @@ static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
if (usbd_msc_cfg.cbw.CB[4] == 0U) {
|
||||
if (g_usbd_msc.cbw.CB[4] == 0U) {
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else {
|
||||
//SCSI_MEDIUM_LOCKED;
|
||||
@@ -339,17 +350,17 @@ static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = 4;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
|
||||
uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (usbd_msc_cfg.readonly) {
|
||||
if (g_usbd_msc.readonly) {
|
||||
sense6[2] = 0x80;
|
||||
}
|
||||
memcpy(*data, (uint8_t *)sense6, data_len);
|
||||
@@ -360,13 +371,13 @@ static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = 27;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.CB[8] < 27) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[8];
|
||||
if (g_usbd_msc.cbw.CB[8] < 27) {
|
||||
data_len = g_usbd_msc.cbw.CB[8];
|
||||
}
|
||||
|
||||
uint8_t sense10[27] = {
|
||||
@@ -406,7 +417,7 @@ static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
@@ -415,15 +426,15 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
0x00,
|
||||
0x00,
|
||||
0x08, /* Capacity List Length */
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 24) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 16) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 24) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 16) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 0) & 0xff),
|
||||
|
||||
0x02, /* Descriptor Code: Formatted Media */
|
||||
0x00,
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
|
||||
};
|
||||
|
||||
memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
|
||||
@@ -433,21 +444,21 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 24) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 16) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 8) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 0) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 24) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 16) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 8) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 0) & 0xff),
|
||||
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 24) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 16) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 24) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 16) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
|
||||
};
|
||||
|
||||
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
|
||||
@@ -457,113 +468,123 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_read10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
|
||||
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
|
||||
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_IN;
|
||||
g_usbd_msc.stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool SCSI_read12(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
|
||||
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
|
||||
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_IN;
|
||||
g_usbd_msc.stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool SCSI_write10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != data_len) {
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SCSI_write12(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != data_len) {
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
return true;
|
||||
}
|
||||
/* do not use verify to reduce code size */
|
||||
@@ -574,41 +595,41 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
|
||||
uint32_t lba = 0;
|
||||
uint32_t blk_num = 0;
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x00U) {
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x00U) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x02U) {
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x02U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA);
|
||||
return false; /* Error, Verify Mode Not supported*/
|
||||
}
|
||||
|
||||
lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]);
|
||||
lba = GET_BE32(&g_usbd_msc.cbw.CB[2]);
|
||||
USB_LOG_DBG("lba: 0x%x\r\n", lba);
|
||||
|
||||
usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size;
|
||||
g_usbd_msc.scsi_blk_addr = lba * g_usbd_msc.scsi_blk_size;
|
||||
|
||||
/* Number of Blocks to transfer */
|
||||
blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]);
|
||||
blk_num = GET_BE16(&g_usbd_msc.cbw.CB[7]);
|
||||
|
||||
USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
|
||||
usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size;
|
||||
g_usbd_msc.scsi_blk_len = blk_num * g_usbd_msc.scsi_blk_size;
|
||||
|
||||
if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((lba + blk_num) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != g_usbd_msc.scsi_blk_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -617,23 +638,23 @@ static bool SCSI_processRead(void)
|
||||
{
|
||||
uint32_t transfer_len;
|
||||
|
||||
USB_LOG_DBG("read lba:%d\r\n", usbd_msc_cfg.start_sector);
|
||||
USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
transfer_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
|
||||
if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) {
|
||||
if (usbd_msc_sector_read(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, transfer_len) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len);
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, g_usbd_msc.block_buffer, transfer_len);
|
||||
|
||||
usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
|
||||
g_usbd_msc.start_sector += (transfer_len / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.nsectors -= (transfer_len / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.csw.dDataResidue -= transfer_len;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
usbd_msc_cfg.stage = MSC_SEND_CSW;
|
||||
if (g_usbd_msc.nsectors == 0) {
|
||||
g_usbd_msc.stage = MSC_SEND_CSW;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -642,22 +663,22 @@ static bool SCSI_processRead(void)
|
||||
static bool SCSI_processWrite(uint32_t nbytes)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector);
|
||||
USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) {
|
||||
if (usbd_msc_sector_write(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, nbytes) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= nbytes;
|
||||
g_usbd_msc.start_sector += (nbytes / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.nsectors -= (nbytes / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.csw.dDataResidue -= nbytes;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
if (g_usbd_msc.nsectors == 0) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
|
||||
} else {
|
||||
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
data_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -665,7 +686,7 @@ static bool SCSI_processWrite(uint32_t nbytes)
|
||||
|
||||
static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
{
|
||||
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
|
||||
uint8_t *buf2send = g_usbd_msc.block_buffer;
|
||||
uint32_t len2send = 0;
|
||||
bool ret = false;
|
||||
|
||||
@@ -675,15 +696,15 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
|
||||
usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
|
||||
g_usbd_msc.csw.dTag = g_usbd_msc.cbw.dTag;
|
||||
g_usbd_msc.csw.dDataResidue = g_usbd_msc.cbw.dDataLength;
|
||||
|
||||
if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
|
||||
if ((g_usbd_msc.cbw.bLUN > 1) || (g_usbd_msc.cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc.cbw.bCBLength < 1) || (g_usbd_msc.cbw.bCBLength > 16)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
} else {
|
||||
USB_LOG_DBG("Decode CB:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_TESTUNITREADY:
|
||||
ret = SCSI_testUnitReady(&buf2send, &len2send);
|
||||
break;
|
||||
@@ -730,13 +751,13 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
|
||||
default:
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
if (usbd_msc_cfg.stage == MSC_READ_CBW) {
|
||||
if (g_usbd_msc.stage == MSC_READ_CBW) {
|
||||
if (len2send) {
|
||||
USB_LOG_DBG("Send info len:%d\r\n", len2send);
|
||||
usbd_msc_send_info(buf2send, len2send);
|
||||
@@ -750,21 +771,26 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (usbd_msc_cfg.stage) {
|
||||
switch (g_usbd_msc.stage) {
|
||||
case MSC_READ_CBW:
|
||||
if (SCSI_CBWDecode(nbytes) == false) {
|
||||
USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
USB_LOG_ERR("Command:0x%02x decode err\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
usbd_msc_bot_abort();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MSC_DATA_OUT:
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_WRITE10:
|
||||
case SCSI_CMD_WRITE12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
g_usbd_msc.nbytes = nbytes;
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_OUT);
|
||||
#else
|
||||
if (SCSI_processWrite(nbytes) == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -777,15 +803,19 @@ void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (usbd_msc_cfg.stage) {
|
||||
switch (g_usbd_msc.stage) {
|
||||
case MSC_DATA_IN:
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_READ10:
|
||||
case SCSI_CMD_READ12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
#else
|
||||
if (SCSI_processRead() == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -798,9 +828,9 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
/*the host has received the CSW*/
|
||||
case MSC_WAIT_CSW:
|
||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||
g_usbd_msc.stage = MSC_READ_CBW;
|
||||
USB_LOG_DBG("Start reading cbw\r\n");
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -808,6 +838,32 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbdev_msc_thread(void *argument)
|
||||
{
|
||||
uintptr_t event;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(g_usbd_msc.usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
USB_LOG_DBG("%d\r\n", event);
|
||||
if (event == MSC_DATA_OUT) {
|
||||
if (SCSI_processWrite(g_usbd_msc.nbytes) == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else if (event == MSC_DATA_IN) {
|
||||
if (SCSI_processRead() == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
|
||||
{
|
||||
intf->class_interface_handler = msc_storage_class_interface_request_handler;
|
||||
@@ -823,19 +879,34 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
|
||||
usbd_add_endpoint(&mass_ep_data[MSD_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(&mass_ep_data[MSD_IN_EP_IDX]);
|
||||
|
||||
memset((uint8_t *)&usbd_msc_cfg, 0, sizeof(struct usbd_msc_cfg_priv));
|
||||
memset((uint8_t *)&g_usbd_msc, 0, sizeof(struct usbd_msc_priv));
|
||||
|
||||
usbd_msc_get_cap(0, &usbd_msc_cfg.scsi_blk_nbr, &usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
|
||||
|
||||
if (usbd_msc_cfg.scsi_blk_size > CONFIG_USBDEV_MSC_BLOCK_SIZE) {
|
||||
if (g_usbd_msc.scsi_blk_size > CONFIG_USBDEV_MSC_BLOCK_SIZE) {
|
||||
USB_LOG_ERR("msc block buffer overflow\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
g_usbd_msc.usbd_msc_mq = usb_osal_mq_create(1);
|
||||
if (g_usbd_msc.usbd_msc_mq == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
g_usbd_msc.usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, NULL);
|
||||
if (g_usbd_msc.usbd_msc_thread == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return intf;
|
||||
}
|
||||
|
||||
void usbd_msc_set_readonly(bool readonly)
|
||||
{
|
||||
usbd_msc_cfg.readonly = readonly;
|
||||
}
|
||||
g_usbd_msc.readonly = readonly;
|
||||
}
|
||||
|
||||
bool usbd_msc_set_popup(void)
|
||||
{
|
||||
return g_usbd_msc.popup;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
|
||||
void usbd_msc_set_readonly(bool readonly);
|
||||
bool usbd_msc_set_popup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -9,33 +9,35 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/sd%c"
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
|
||||
|
||||
static int usbh_msc_devno_alloc(struct usbh_msc *msc_class)
|
||||
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
|
||||
|
||||
static struct usbh_msc *usbh_msc_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 26; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
msc_class->sdchar = 'a' + devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; 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];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_msc_devno_free(struct usbh_msc *msc_class)
|
||||
static void usbh_msc_class_free(struct usbh_msc *msc_class)
|
||||
{
|
||||
int devno = msc_class->sdchar - 'a';
|
||||
|
||||
if (devno >= 0 && devno < 26) {
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
}
|
||||
|
||||
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
|
||||
@@ -273,19 +275,39 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
|
||||
}
|
||||
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
{
|
||||
if (config) {
|
||||
g_msc_modeswitch_config = config;
|
||||
} else {
|
||||
g_msc_modeswitch_config = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
|
||||
memcpy(g_msc_buf, message, 31);
|
||||
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
|
||||
}
|
||||
|
||||
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
struct usbh_msc_modeswitch_config *config;
|
||||
|
||||
struct usbh_msc *msc_class = usb_malloc(sizeof(struct usbh_msc));
|
||||
struct usbh_msc *msc_class = usbh_msc_class_alloc();
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc msc_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
usbh_msc_devno_alloc(msc_class);
|
||||
msc_class->hport = hport;
|
||||
msc_class->intf = intf;
|
||||
|
||||
@@ -307,6 +329,23 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
if (g_msc_modeswitch_config) {
|
||||
uint8_t num = 0;
|
||||
while (1) {
|
||||
config = &g_msc_modeswitch_config[num];
|
||||
if (config) {
|
||||
if ((hport->device_desc.idVendor == config->vid) &&
|
||||
(hport->device_desc.idProduct == config->pid)) {
|
||||
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
|
||||
usbh_msc_modeswitch(msc_class, config->message_content);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
@@ -315,6 +354,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
@@ -349,8 +389,6 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
|
||||
|
||||
if (msc_class) {
|
||||
usbh_msc_devno_free(msc_class);
|
||||
|
||||
if (msc_class->bulkin) {
|
||||
usbh_pipe_free(msc_class->bulkin);
|
||||
}
|
||||
@@ -364,8 +402,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_msc_stop(msc_class);
|
||||
}
|
||||
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
usb_free(msc_class);
|
||||
usbh_msc_class_free(msc_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -22,6 +22,14 @@ struct usbh_msc {
|
||||
uint16_t blocksize; /* Block size of USB mass storage device */
|
||||
};
|
||||
|
||||
struct usbh_msc_modeswitch_config {
|
||||
const char *name;
|
||||
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
|
||||
uint16_t pid; /* Product ID (for vendor/product specific devices) */
|
||||
const uint8_t *message_content;
|
||||
};
|
||||
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
|
||||
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
|
||||
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
|
||||
|
||||
|
||||
@@ -437,9 +437,8 @@ struct mtp_container_response {
|
||||
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
|
||||
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
|
||||
/* Interface */ \
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
@@ -453,13 +452,13 @@ struct mtp_container_response {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
@@ -467,37 +466,6 @@ struct mtp_container_response {
|
||||
0x03, /* bmAttributes */ \
|
||||
0x1c, 0x00, /* wMaxPacketSize */ \
|
||||
0x06 /* bInterval */
|
||||
#else
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x03, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
|
||||
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
|
||||
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x1c, 0x00, /* wMaxPacketSize */ \
|
||||
0x06 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_MTP_H */
|
||||
|
||||
@@ -16,7 +16,7 @@ enum Stage {
|
||||
MTP_WAIT_RESPONSE = 4,
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp_priv {
|
||||
USB_MEM_ALIGNX struct mtp_container_command con_command;
|
||||
USB_MEM_ALIGNX struct mtp_container_data con_data;
|
||||
USB_MEM_ALIGNX struct mtp_container_response con_response;
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_printer.h"
|
||||
|
||||
struct printer_cfg_priv {
|
||||
struct usbd_printer_priv {
|
||||
const uint8_t *device_id;
|
||||
uint8_t device_id_len;
|
||||
uint8_t port_status;
|
||||
} usbd_printer_cfg;
|
||||
} g_usbd_printer;
|
||||
|
||||
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
@@ -20,8 +20,8 @@ static int printer_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case PRINTER_REQUEST_GET_DEVICE_ID:
|
||||
memcpy(*data, usbd_printer_cfg.device_id, usbd_printer_cfg.device_id_len);
|
||||
*len = usbd_printer_cfg.device_id_len;
|
||||
memcpy(*data, g_usbd_printer.device_id, g_usbd_printer.device_id_len);
|
||||
*len = g_usbd_printer.device_id_len;
|
||||
break;
|
||||
case PRINTER_REQUEST_GET_PORT_SATTUS:
|
||||
|
||||
@@ -55,7 +55,7 @@ struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = printer_notify_handler;
|
||||
|
||||
usbd_printer_cfg.device_id = device_id;
|
||||
usbd_printer_cfg.device_id_len = device_id_len;
|
||||
g_usbd_printer.device_id = device_id;
|
||||
g_usbd_printer.device_id_len = device_id_len;
|
||||
return intf;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,34 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/printer"
|
||||
|
||||
static struct usbh_printer g_printer_class[CONFIG_USBHOST_MAX_PRINTER_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_printer *usbh_printer_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_PRINTER_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_printer_class[devno], 0, sizeof(struct usbh_printer));
|
||||
g_printer_class[devno].minor = devno;
|
||||
return &g_printer_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_printer_class_free(struct usbh_printer *printer_class)
|
||||
{
|
||||
int devno = printer_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
}
|
||||
|
||||
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
@@ -56,14 +84,12 @@ static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_printer *printer_class = usb_malloc(sizeof(struct usbh_printer));
|
||||
struct usbh_printer *printer_class = usbh_printer_class_alloc();
|
||||
if (printer_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc printer_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
|
||||
printer_class->hport = hport;
|
||||
printer_class->intf = intf;
|
||||
|
||||
@@ -107,8 +133,7 @@ static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
usb_free(printer_class);
|
||||
usbh_printer_class_free(printer_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -12,6 +12,7 @@ struct usbh_printer {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
};
|
||||
|
||||
@@ -3,43 +3,47 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/xxx"
|
||||
|
||||
static struct usbh_xxx g_xxx_class[CONFIG_USBHOST_MAX_CUSTOM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_xxx *usbh_xxx_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; 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];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
int devno = xxx_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(xxx_class, 0, sizeof(struct usbh_xxx));
|
||||
}
|
||||
|
||||
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_xxx *xxx_class = usb_malloc(sizeof(struct usbh_xxx));
|
||||
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
|
||||
if (xxx_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(xxx_class, 0, sizeof(struct usbh_xxx));
|
||||
|
||||
xxx_class->hport = hport;
|
||||
xxx_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = xxx_class;
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
|
||||
|
||||
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
|
||||
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||
ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
|
||||
ep_cfg.ep_interval = ep_desc->bInterval;
|
||||
ep_cfg.hport = hport;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
|
||||
} else {
|
||||
usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +62,24 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_pipe_free(xxx_class->bulkout);
|
||||
}
|
||||
|
||||
usb_free(xxx_class);
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_xxx_stop(xxx_class);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
hport->config.intf[intf].priv = NULL;
|
||||
usbh_xxx_class_free(xxx_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_xxx_run(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_xxx_stop(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver xxx_class_driver = {
|
||||
.driver_name = "xxx",
|
||||
|
||||
@@ -7,8 +7,9 @@ struct usbh_xxx {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t intin; /* INTR IN endpoint */
|
||||
usbh_pipe_t intout; /* INTR OUT endpoint */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* bulk OUT endpoint */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,8 @@ struct usbh_cdc_custom_air724 {
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_air724_buf[32];
|
||||
|
||||
static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
@@ -30,12 +32,26 @@ static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *c
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int usbh_air724_bulk_in_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_custom_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
/* interface 3 is AT command */
|
||||
if (intf != 3) {
|
||||
USB_LOG_WRN("ignore intf:%d\r\n", intf);
|
||||
return 0;
|
||||
@@ -65,20 +81,22 @@ int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
uint8_t cdc_buffer[32] = { 0x41, 0x54, 0x0d, 0x0a };
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkout, cdc_buffer, 4, 3000);
|
||||
const uint8_t AT[4] = { 0x41, 0x54, 0x0d, 0x0a };
|
||||
|
||||
memcpy(g_air724_buf, AT, 4);
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class, g_air724_buf, 4, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", ret);
|
||||
}
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkin, cdc_buffer, 10, 3000);
|
||||
ret = usbh_air724_bulk_in_transfer(cdc_custom_class, g_air724_buf, 10, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||
for (size_t i = 0; i < ret; i++) {
|
||||
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||
USB_LOG_RAW("0x%02x ", g_air724_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
1763
class/vendor/cp201x/usbh_cp210x.c
vendored
Normal file
99
class/vendor/cp201x/usbh_cp210x.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#ifndef USBH_CP210X_H
|
||||
#define USBH_CP210X_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "usbh_core.h"
|
||||
|
||||
typedef int32_t speed_t;
|
||||
typedef int32_t tcflag_t;
|
||||
|
||||
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
|
||||
|
||||
struct usb_serial_port{
|
||||
uint8_t partnum;
|
||||
uint8_t ctrlpipe_rx;
|
||||
uint8_t ctrlpipe_tx;
|
||||
int32_t max_speed;
|
||||
speed_t use_actual_rate;
|
||||
uint8_t bInterfaceNumber;
|
||||
int has_swapped_line_ctl;
|
||||
};
|
||||
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
|
||||
#define NCCS 19
|
||||
struct termios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has identical termios and termios2 */
|
||||
|
||||
struct termios2 {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has matching termios and ktermios */
|
||||
|
||||
struct ktermios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
|
||||
struct tty_struct{
|
||||
struct usb_serial_port driver_data;
|
||||
struct termios termios;
|
||||
};
|
||||
|
||||
int cp210x_attach(struct usb_serial_port *port);
|
||||
int cp210x_port_probe(struct usb_serial_port *port);
|
||||
void cp210x_break_ctl(struct tty_struct *tty, int break_state);
|
||||
int cp210x_open(struct tty_struct *tty);
|
||||
int cp210x_tiocmget(struct tty_struct *tty);
|
||||
void cp210x_set_termios(struct tty_struct *tty);
|
||||
void cp210x_change_speed(struct tty_struct *tty);
|
||||
void cp210x_dtr_rts(struct usb_serial_port *port, int on);
|
||||
|
||||
struct usbh_cp210x
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf;
|
||||
usbh_pipe_t bulkin;
|
||||
usbh_pipe_t bulkout;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb bulkout_urb;
|
||||
|
||||
struct tty_struct drv_data;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
/* weak defined function */
|
||||
void drv_usbh_cp210x_run(struct usbh_cp210x *p_device);
|
||||
void drv_usbh_cp210x_stop(struct usbh_cp210x *p_device);
|
||||
|
||||
#endif
|
||||
@@ -12,17 +12,13 @@ struct video_entity_info {
|
||||
uint16_t wTerminalType;
|
||||
};
|
||||
|
||||
struct usbd_video_cfg_priv {
|
||||
struct usbd_video_priv {
|
||||
struct video_probe_and_commit_controls probe;
|
||||
struct video_probe_and_commit_controls commit;
|
||||
uint8_t power_mode;
|
||||
uint8_t error_code;
|
||||
struct video_entity_info info[3];
|
||||
} usbd_video_cfg = {
|
||||
.info[0] = { .bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x01, .wTerminalType = VIDEO_ITT_CAMERA },
|
||||
.info[1] = { .bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x03, .wTerminalType = 0x00 },
|
||||
.info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
|
||||
};
|
||||
} g_usbd_video;
|
||||
|
||||
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
@@ -70,7 +66,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
struct video_entity_info *entity_info = &usbd_video_cfg.info[i];
|
||||
struct video_entity_info *entity_info = &g_usbd_video.info[i];
|
||||
if (entity_info->bEntityId == entity_id) {
|
||||
switch (entity_info->bDescriptorSubtype) {
|
||||
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
|
||||
@@ -550,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usbd_video_cfg.error_code = 0x06;
|
||||
g_usbd_video.error_code = 0x06;
|
||||
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
@@ -576,10 +572,10 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_PROBE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_SET_CUR:
|
||||
//memcpy((uint8_t *)&usbd_video_cfg.probe, *data, setup->wLength);
|
||||
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.probe, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
|
||||
@@ -587,7 +583,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_REQUEST_GET_MAX:
|
||||
case VIDEO_REQUEST_GET_RES:
|
||||
case VIDEO_REQUEST_GET_DEF:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.probe, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_LEN:
|
||||
@@ -608,17 +604,17 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_COMMIT_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_SET_CUR:
|
||||
//memcpy((uint8_t *)&usbd_video_cfg.commit, *data, setup->wLength);
|
||||
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.commit, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_MIN:
|
||||
case VIDEO_REQUEST_GET_MAX:
|
||||
case VIDEO_REQUEST_GET_RES:
|
||||
case VIDEO_REQUEST_GET_DEF:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.commit, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
|
||||
@@ -640,7 +636,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
(*data)[0] = usbd_video_cfg.error_code;
|
||||
(*data)[0] = g_usbd_video.error_code;
|
||||
*len = 1;
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_INFO:
|
||||
@@ -684,8 +680,8 @@ static void video_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
usbd_video_cfg.error_code = 0;
|
||||
usbd_video_cfg.power_mode = 0;
|
||||
g_usbd_video.error_code = 0;
|
||||
g_usbd_video.power_mode = 0;
|
||||
break;
|
||||
|
||||
case USBD_EVENT_SET_INTERFACE: {
|
||||
@@ -705,41 +701,41 @@ static void video_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
{
|
||||
usbd_video_cfg.probe.hintUnion.bmHint = 0x01;
|
||||
usbd_video_cfg.probe.hintUnion1.bmHint = 0;
|
||||
usbd_video_cfg.probe.bFormatIndex = 1;
|
||||
usbd_video_cfg.probe.bFrameIndex = 1;
|
||||
usbd_video_cfg.probe.dwFrameInterval = dwFrameInterval;
|
||||
usbd_video_cfg.probe.wKeyFrameRate = 0;
|
||||
usbd_video_cfg.probe.wPFrameRate = 0;
|
||||
usbd_video_cfg.probe.wCompQuality = 0;
|
||||
usbd_video_cfg.probe.wCompWindowSize = 0;
|
||||
usbd_video_cfg.probe.wDelay = 0;
|
||||
usbd_video_cfg.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
usbd_video_cfg.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
usbd_video_cfg.probe.dwClockFrequency = 0;
|
||||
usbd_video_cfg.probe.bmFramingInfo = 0;
|
||||
usbd_video_cfg.probe.bPreferedVersion = 0;
|
||||
usbd_video_cfg.probe.bMinVersion = 0;
|
||||
usbd_video_cfg.probe.bMaxVersion = 0;
|
||||
g_usbd_video.probe.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video.probe.hintUnion1.bmHint = 0;
|
||||
g_usbd_video.probe.bFormatIndex = 1;
|
||||
g_usbd_video.probe.bFrameIndex = 1;
|
||||
g_usbd_video.probe.dwFrameInterval = dwFrameInterval;
|
||||
g_usbd_video.probe.wKeyFrameRate = 0;
|
||||
g_usbd_video.probe.wPFrameRate = 0;
|
||||
g_usbd_video.probe.wCompQuality = 0;
|
||||
g_usbd_video.probe.wCompWindowSize = 0;
|
||||
g_usbd_video.probe.wDelay = 0;
|
||||
g_usbd_video.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
g_usbd_video.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
g_usbd_video.probe.dwClockFrequency = 0;
|
||||
g_usbd_video.probe.bmFramingInfo = 0;
|
||||
g_usbd_video.probe.bPreferedVersion = 0;
|
||||
g_usbd_video.probe.bMinVersion = 0;
|
||||
g_usbd_video.probe.bMaxVersion = 0;
|
||||
|
||||
usbd_video_cfg.commit.hintUnion.bmHint = 0x01;
|
||||
usbd_video_cfg.commit.hintUnion1.bmHint = 0;
|
||||
usbd_video_cfg.commit.bFormatIndex = 1;
|
||||
usbd_video_cfg.commit.bFrameIndex = 1;
|
||||
usbd_video_cfg.commit.dwFrameInterval = dwFrameInterval;
|
||||
usbd_video_cfg.commit.wKeyFrameRate = 0;
|
||||
usbd_video_cfg.commit.wPFrameRate = 0;
|
||||
usbd_video_cfg.commit.wCompQuality = 0;
|
||||
usbd_video_cfg.commit.wCompWindowSize = 0;
|
||||
usbd_video_cfg.commit.wDelay = 0;
|
||||
usbd_video_cfg.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
usbd_video_cfg.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
usbd_video_cfg.commit.dwClockFrequency = 0;
|
||||
usbd_video_cfg.commit.bmFramingInfo = 0;
|
||||
usbd_video_cfg.commit.bPreferedVersion = 0;
|
||||
usbd_video_cfg.commit.bMinVersion = 0;
|
||||
usbd_video_cfg.commit.bMaxVersion = 0;
|
||||
g_usbd_video.commit.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video.commit.hintUnion1.bmHint = 0;
|
||||
g_usbd_video.commit.bFormatIndex = 1;
|
||||
g_usbd_video.commit.bFrameIndex = 1;
|
||||
g_usbd_video.commit.dwFrameInterval = dwFrameInterval;
|
||||
g_usbd_video.commit.wKeyFrameRate = 0;
|
||||
g_usbd_video.commit.wPFrameRate = 0;
|
||||
g_usbd_video.commit.wCompQuality = 0;
|
||||
g_usbd_video.commit.wCompWindowSize = 0;
|
||||
g_usbd_video.commit.wDelay = 0;
|
||||
g_usbd_video.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
g_usbd_video.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
g_usbd_video.commit.dwClockFrequency = 0;
|
||||
g_usbd_video.commit.bmFramingInfo = 0;
|
||||
g_usbd_video.commit.bPreferedVersion = 0;
|
||||
g_usbd_video.commit.bMinVersion = 0;
|
||||
g_usbd_video.commit.bMaxVersion = 0;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
||||
@@ -752,6 +748,16 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = video_notify_handler;
|
||||
|
||||
g_usbd_video.info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[0].bEntityId = 0x01;
|
||||
g_usbd_video.info[0].wTerminalType = VIDEO_ITT_CAMERA;
|
||||
g_usbd_video.info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[1].bEntityId = 0x03;
|
||||
g_usbd_video.info[1].wTerminalType = 0x00;
|
||||
g_usbd_video.info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[2].bEntityId = 0x02;
|
||||
g_usbd_video.info[2].wTerminalType = 0x00;
|
||||
|
||||
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
|
||||
return intf;
|
||||
}
|
||||
@@ -763,18 +769,18 @@ uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8
|
||||
uint32_t picture_pos = 0;
|
||||
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||
|
||||
packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
|
||||
last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
|
||||
packets = (input_len + (g_usbd_video.probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
||||
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2));
|
||||
|
||||
for (size_t i = 0; i < packets; i++) {
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
if (i == (packets - 1)) {
|
||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
} else {
|
||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
|
||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += g_usbd_video.probe.dwMaxPayloadTransferSize - 2;
|
||||
}
|
||||
}
|
||||
uvc_header[1] ^= 1;
|
||||
|
||||
@@ -21,63 +21,77 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
|
||||
|
||||
static const char *format_type[] = { "uncompressed", "mjpeg" };
|
||||
|
||||
static int usbh_video_devno_alloc(struct usbh_video *video_class)
|
||||
static struct usbh_video g_video_class[CONFIG_USBHOST_MAX_VIDEO_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_video *usbh_video_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
video_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; 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];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_video_devno_free(struct usbh_video *video_class)
|
||||
static void usbh_video_class_free(struct usbh_video *video_class)
|
||||
{
|
||||
int devno = video_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
}
|
||||
|
||||
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
int ret;
|
||||
uint8_t retry;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = VIDEO_REQUEST_GET_CUR;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
setup->wIndex = (entity_id << 8) | intf;
|
||||
setup->wLength = len;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
retry = 0;
|
||||
while (1) {
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
if (ret > 0) {
|
||||
break;
|
||||
}
|
||||
retry++;
|
||||
|
||||
if (retry == 3) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
memcpy(buf, g_video_buf, len);
|
||||
|
||||
if (buf) {
|
||||
memcpy(buf, g_video_buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = VIDEO_REQUEST_SET_CUR;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
setup->wIndex = (entity_id << 8) | intf;
|
||||
setup->wLength = len;
|
||||
@@ -85,13 +99,13 @@ int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t ent
|
||||
memcpy(g_video_buf, buf, len);
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
usb_osal_msleep(5);
|
||||
usb_osal_msleep(50);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
|
||||
{
|
||||
return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
@@ -99,7 +113,8 @@ int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t fo
|
||||
video_class->probe.bFormatIndex = formatindex;
|
||||
video_class->probe.bFrameIndex = frameindex;
|
||||
video_class->probe.dwMaxPayloadTransferSize = 0;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
video_class->probe.dwFrameInterval = 333333;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
@@ -107,7 +122,8 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
|
||||
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
|
||||
video_class->commit.bFormatIndex = formatindex;
|
||||
video_class->commit.bFrameIndex = frameindex;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
video_class->commit.dwFrameInterval = 333333;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
}
|
||||
|
||||
int usbh_video_open(struct usbh_video *video_class,
|
||||
@@ -124,6 +140,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
bool found = false;
|
||||
uint8_t formatidx = 0;
|
||||
uint8_t frameidx = 0;
|
||||
uint8_t step;
|
||||
|
||||
if (video_class->is_opened) {
|
||||
return -EMFILE;
|
||||
@@ -151,31 +168,65 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Open video step:
|
||||
* Get CUR request (probe)
|
||||
* Set CUR request (probe)
|
||||
* Get CUR request (probe)
|
||||
* Get MAX request (probe)
|
||||
* Get MIN request (probe)
|
||||
* Get CUR request (probe)
|
||||
* Set CUR request (commit)
|
||||
*
|
||||
*/
|
||||
step = 0;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 1;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 2;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 3;
|
||||
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MAX, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 4;
|
||||
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MIN, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 5;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 6;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 7;
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 8;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
@@ -184,7 +235,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
@@ -202,6 +253,10 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
video_class->is_opened = true;
|
||||
video_class->current_format = format_type;
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
USB_LOG_ERR("Fail to open video in step %u\r\n", step);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_video_close(struct usbh_video *video_class)
|
||||
@@ -292,14 +347,12 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
uint8_t num_of_frames = 0xff;
|
||||
uint8_t *p;
|
||||
|
||||
struct usbh_video *video_class = usb_malloc(sizeof(struct usbh_video));
|
||||
struct usbh_video *video_class = usbh_video_class_alloc();
|
||||
if (video_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc video_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
usbh_video_devno_alloc(video_class);
|
||||
video_class->hport = hport;
|
||||
video_class->ctrl_intf = intf;
|
||||
video_class->data_intf = intf + 1;
|
||||
@@ -401,8 +454,6 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
|
||||
|
||||
if (video_class) {
|
||||
usbh_video_devno_free(video_class);
|
||||
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
}
|
||||
@@ -416,8 +467,7 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_video_stop(video_class);
|
||||
}
|
||||
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
usb_free(video_class);
|
||||
usbh_video_class_free(video_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -433,132 +483,6 @@ static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t i
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stream->bufoffset == 0) && ((iso_packet[i].transfer_buffer[header_len] != 0xff) || (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8))) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) || (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
/** do something here */
|
||||
}
|
||||
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback && (stream->bufoffset == stream->buflen)) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
}
|
||||
#endif
|
||||
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
@@ -567,10 +491,6 @@ __WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
.driver_name = "video_ctrl",
|
||||
.connect = usbh_video_ctrl_connect,
|
||||
|
||||
@@ -25,6 +25,8 @@ struct usbh_video_format {
|
||||
struct usbh_videostreaming {
|
||||
uint32_t bufoffset;
|
||||
uint32_t buflen;
|
||||
uint16_t width;
|
||||
uint16_t heigth;
|
||||
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
|
||||
};
|
||||
|
||||
@@ -52,14 +54,8 @@ struct usbh_video {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_video_inityuyv2rgb_table(void);
|
||||
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len);
|
||||
|
||||
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
|
||||
int usbh_video_open(struct usbh_video *video_class,
|
||||
uint8_t format_type,
|
||||
@@ -70,10 +66,6 @@ int usbh_video_close(struct usbh_video *video_class);
|
||||
|
||||
void usbh_video_list_info(struct usbh_video *video_class);
|
||||
|
||||
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream);
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream);
|
||||
void usbh_videostreaming_output(uint8_t *input, uint32_t input_len);
|
||||
|
||||
void usbh_video_run(struct usbh_video *video_class);
|
||||
void usbh_video_stop(struct usbh_video *video_class);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ static struct usbd_endpoint rndis_ep_data[3];
|
||||
#endif
|
||||
|
||||
/* Device data structure */
|
||||
struct usbd_rndis_cfg_priv {
|
||||
struct usbd_rndis_priv {
|
||||
uint32_t drv_version;
|
||||
uint32_t link_status;
|
||||
uint32_t speed;
|
||||
@@ -38,11 +38,12 @@ struct usbd_rndis_cfg_priv {
|
||||
usb_eth_stat_t eth_state;
|
||||
rndis_state_t init_state;
|
||||
uint8_t mac[6];
|
||||
} usbd_rndis_cfg = { .drv_version = 0x0001,
|
||||
.link_status = NDIS_MEDIA_STATE_DISCONNECTED,
|
||||
.speed = RNDIS_LINK_SPEED,
|
||||
.init_state = rndis_uninitialized,
|
||||
.mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
|
||||
} g_usbd_rndis;
|
||||
|
||||
#if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
|
||||
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
@@ -174,7 +175,7 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp->AfListOffset = 0;
|
||||
resp->AfListSize = 0;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_initialized;
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
return 0;
|
||||
@@ -187,7 +188,7 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageLength = 0;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_uninitialized;
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -241,7 +242,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
break;
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
|
||||
RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
|
||||
infomation_len = 6;
|
||||
break;
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
@@ -253,7 +254,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
@@ -261,7 +262,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
@@ -301,19 +302,19 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
@@ -354,7 +355,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
param->ParameterValueOffset, param->ParameterValueLength);
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
|
||||
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
|
||||
USB_LOG_WRN("PACKET_FILTER!\r\n");
|
||||
resp->Status = RNDIS_STATUS_INVALID_DATA;
|
||||
} else {
|
||||
@@ -362,12 +363,12 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
/* Parameter starts at offset buf_offset of the req_id field */
|
||||
filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
|
||||
|
||||
//usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
|
||||
usbd_rndis_cfg.net_filter = *(uint32_t *)filter;
|
||||
if (usbd_rndis_cfg.net_filter) {
|
||||
usbd_rndis_cfg.init_state = rndis_data_initialized;
|
||||
//g_usbd_rndis.net_filter = param->ParameterNameOffset;
|
||||
g_usbd_rndis.net_filter = *(uint32_t *)filter;
|
||||
if (g_usbd_rndis.net_filter) {
|
||||
g_usbd_rndis.init_state = rndis_data_initialized;
|
||||
} else {
|
||||
usbd_rndis_cfg.init_state = rndis_initialized;
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -393,7 +394,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
|
||||
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
rndis_reset_cmplt_t *resp;
|
||||
|
||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
@@ -402,7 +403,7 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
resp->AddressingReset = 1;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_uninitialized;
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
@@ -429,12 +430,12 @@ static void rndis_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
g_rndis_rx_data_length = 0;
|
||||
g_rndis_tx_data_length = 0;
|
||||
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
break;
|
||||
|
||||
@@ -458,7 +459,7 @@ void rndis_bulk_out(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((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
|
||||
usbd_rndis_data_recv_done();
|
||||
}
|
||||
|
||||
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
@@ -506,7 +507,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -543,7 +544,11 @@ 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])
|
||||
{
|
||||
memcpy(usbd_rndis_cfg.mac, mac, 6);
|
||||
memcpy(g_usbd_rndis.mac, mac, 6);
|
||||
|
||||
g_usbd_rndis.drv_version = 0x0001;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
|
||||
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
|
||||
|
||||
@@ -18,6 +18,8 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep, uint8_t mac[6]);
|
||||
|
||||
void usbd_rndis_data_recv_done(void);
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
struct pbuf *usbd_rndis_eth_rx(void);
|
||||
int usbd_rndis_eth_tx(struct pbuf *p);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
@@ -79,7 +81,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_query_msg_t);
|
||||
setup->wLength = query_len + sizeof(rndis_query_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
@@ -131,7 +133,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_set_msg_t);
|
||||
setup->wLength = info_len + sizeof(rndis_set_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
@@ -232,7 +234,6 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
|
||||
static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint32_t *oid_support_list;
|
||||
@@ -242,11 +243,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
uint8_t tmp_buffer[512];
|
||||
uint8_t data[32];
|
||||
|
||||
struct usbh_rndis *rndis_class = usb_malloc(sizeof(struct usbh_rndis));
|
||||
if (rndis_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc rndis_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
struct usbh_rndis *rndis_class = &g_rndis_class;
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
|
||||
@@ -363,7 +360,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_run(rndis_class);
|
||||
@@ -394,7 +391,6 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
usb_free(rndis_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -13,7 +13,7 @@ struct usbh_rndis {
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Notify endpoint */
|
||||
|
||||
@@ -484,13 +484,10 @@ struct usb_msosv1_comp_id_function_descriptor {
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor {
|
||||
uint8_t *string;
|
||||
uint8_t string_len;
|
||||
const uint8_t *string;
|
||||
uint8_t vendor_code;
|
||||
uint8_t *compat_id;
|
||||
uint16_t compat_id_len;
|
||||
uint8_t *comp_id_property;
|
||||
uint16_t comp_id_property_len;
|
||||
const uint8_t *compat_id;
|
||||
const uint8_t **comp_id_property;
|
||||
};
|
||||
|
||||
/* MS OS 2.0 Header descriptor */
|
||||
|
||||
@@ -59,7 +59,11 @@ struct usbh_urb {
|
||||
uint32_t start_frame;
|
||||
usbh_complete_callback_t complete;
|
||||
void *arg;
|
||||
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
#else
|
||||
struct usbh_iso_frame_packet iso_packet[0];
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2022-2023, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -44,9 +44,9 @@
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||
#ifndef __USED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __USED __attribute__((used))
|
||||
#else
|
||||
#define __USED __root
|
||||
@@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __WEAK
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __WEAK __attribute__((weak))
|
||||
#else
|
||||
#define __WEAK _Pragma("__weak")
|
||||
@@ -62,7 +62,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -71,7 +71,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_STRUCT
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -80,7 +80,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_UNION
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -89,7 +89,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGNED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#elif (__VER__ >= 7080000)
|
||||
/* Needs IAR language extensions */
|
||||
|
||||
458
core/usbd_core.c
@@ -6,9 +6,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
@@ -32,7 +29,7 @@ struct usbd_tx_rx_msg {
|
||||
usbd_endpoint_callback cb;
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
|
||||
/** Setup packet */
|
||||
USB_MEM_ALIGNX struct usb_setup_packet setup;
|
||||
/** Pointer to data buffer */
|
||||
@@ -45,41 +42,28 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
bool zlp_flag;
|
||||
/** Pointer to registered descriptors */
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
struct usb_descriptor *descriptors;
|
||||
const struct usb_descriptor *descriptors;
|
||||
#else
|
||||
const uint8_t *descriptors;
|
||||
#endif
|
||||
struct usb_msosv1_descriptor *msosv1_desc;
|
||||
struct usb_msosv2_descriptor *msosv2_desc;
|
||||
struct usb_bos_descriptor *bos_desc;
|
||||
/* Buffer used for storing standard, class and vendor request data */
|
||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||
|
||||
/** Variable to check whether the usb has been configured */
|
||||
bool configured;
|
||||
/** Currently selected configuration */
|
||||
uint8_t configuration;
|
||||
uint8_t speed;
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
bool test_mode;
|
||||
#endif
|
||||
struct usbd_interface *intf[8];
|
||||
uint8_t intf_offset;
|
||||
} usbd_core_cfg;
|
||||
|
||||
usb_slist_t usbd_intf_head = USB_SLIST_OBJECT_INIT(usbd_intf_head);
|
||||
|
||||
static struct usb_msosv1_descriptor *msosv1_desc;
|
||||
static struct usb_msosv2_descriptor *msosv2_desc;
|
||||
static struct usb_bos_descriptor *bos_desc;
|
||||
|
||||
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
|
||||
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
|
||||
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD)
|
||||
usb_osal_mq_t usbd_tx_mq;
|
||||
usb_osal_thread_t usbd_tx_thread;
|
||||
#endif
|
||||
#if defined(CONFIG_USBDEV_RX_THREAD)
|
||||
usb_osal_mq_t usbd_rx_mq;
|
||||
usb_osal_thread_t usbd_rx_thread;
|
||||
#endif
|
||||
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
|
||||
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
|
||||
} g_usbd_core;
|
||||
|
||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
|
||||
|
||||
@@ -96,7 +80,7 @@ static void usbd_print_setup(struct usb_setup_packet *setup)
|
||||
|
||||
static bool is_device_configured(void)
|
||||
{
|
||||
return (usbd_core_cfg.configuration != 0);
|
||||
return (g_usbd_core.configuration != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,24 +155,24 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
|
||||
switch (type) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_descriptor[0];
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_descriptor[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
usbd_core_cfg.speed = usbd_get_port_speed(0);
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->hs_config_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
g_usbd_core.speed = usbd_get_port_speed(0);
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->hs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->fs_config_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
if (g_usbd_core.descriptors->fs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
@@ -203,20 +187,20 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
(*data)[3] = 0x04;
|
||||
*len = 4;
|
||||
} else if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
if (g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n");
|
||||
*data = usbd_core_cfg.descriptors->msosv1_descriptor->string;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->string_len;
|
||||
*data = g_usbd_core.descriptors->msosv1_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->msosv1_descriptor->string_len;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)usbd_core_cfg.descriptors->string_descriptor[index - 1]);
|
||||
if (g_usbd_core.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)g_usbd_core.descriptors->string_descriptor[index - 1]);
|
||||
|
||||
(*data)[0] = str_len * 2 + 2;
|
||||
(*data)[1] = 0x03;
|
||||
for (uint16_t i = 0; i < str_len; i++) {
|
||||
(*data)[i * 2 + 2] = usbd_core_cfg.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 2] = g_usbd_core.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 3] = 0;
|
||||
}
|
||||
|
||||
@@ -227,28 +211,28 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
}
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
if (usbd_core_cfg.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_quality_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_quality_descriptor[0];
|
||||
if (g_usbd_core.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_quality_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_quality_descriptor[0];
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
if (g_usbd_core.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
@@ -285,25 +269,25 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
|
||||
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
|
||||
|
||||
if (!msosv1_desc) {
|
||||
if (!g_usbd_core.msosv1_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//*data = (uint8_t *)msosv1_desc->string;
|
||||
memcpy(*data, (uint8_t *)msosv1_desc->string, msosv1_desc->string_len);
|
||||
*len = msosv1_desc->string_len;
|
||||
//*data = (uint8_t *)g_usbd_core.msosv1_desc->string;
|
||||
memcpy(*data, (uint8_t *)g_usbd_core.msosv1_desc->string, g_usbd_core.msosv1_desc->string[0]);
|
||||
*len = g_usbd_core.msosv1_desc->string[0];
|
||||
|
||||
return true;
|
||||
} else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) {
|
||||
USB_LOG_INFO("read BOS descriptor string\r\n");
|
||||
|
||||
if (!bos_desc) {
|
||||
if (!g_usbd_core.bos_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//*data = bos_desc->string;
|
||||
memcpy(*data, (uint8_t *)bos_desc->string, bos_desc->string_len);
|
||||
*len = bos_desc->string_len;
|
||||
//*data = g_usbd_core.bos_desc->string;
|
||||
memcpy(*data, (uint8_t *)g_usbd_core.bos_desc->string, g_usbd_core.bos_desc->string_len);
|
||||
*len = g_usbd_core.bos_desc->string_len;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
@@ -319,7 +303,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
return false;
|
||||
}
|
||||
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
|
||||
cur_index = 0U;
|
||||
|
||||
@@ -351,7 +335,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
memcpy(*data, p, *len);
|
||||
} else {
|
||||
/* nothing found */
|
||||
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
|
||||
USB_LOG_ERR("descriptor <type:0x%02x,index:0x%02x> not found!\r\n", type, index);
|
||||
}
|
||||
|
||||
return found;
|
||||
@@ -377,13 +361,13 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
bool found = false;
|
||||
uint8_t *p;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
/* configure endpoints for this configuration/altsetting */
|
||||
while (p[DESC_bLength] != 0U) {
|
||||
@@ -441,13 +425,13 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
bool ret = false;
|
||||
uint8_t *p;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting);
|
||||
|
||||
@@ -526,7 +510,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
}
|
||||
} else if (value == USB_FEATURE_TEST_MODE) {
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
usbd_core_cfg.test_mode = true;
|
||||
g_usbd_core.test_mode = true;
|
||||
usbd_execute_test_mode(setup);
|
||||
#endif
|
||||
}
|
||||
@@ -547,7 +531,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_CONFIGURATION:
|
||||
*data = (uint8_t *)&usbd_core_cfg.configuration;
|
||||
*data = (uint8_t *)&g_usbd_core.configuration;
|
||||
*len = 1;
|
||||
break;
|
||||
|
||||
@@ -557,8 +541,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
if (!usbd_set_configuration(value, 0)) {
|
||||
ret = false;
|
||||
} else {
|
||||
usbd_core_cfg.configuration = value;
|
||||
usbd_core_cfg.configured = true;
|
||||
g_usbd_core.configuration = value;
|
||||
usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
|
||||
usbd_event_handler(USBD_EVENT_CONFIGURED);
|
||||
}
|
||||
@@ -609,13 +592,11 @@ static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
|
||||
USB_LOG_INFO("read hid report descriptor\r\n");
|
||||
usb_slist_t *i;
|
||||
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->intf_num == intf_num) {
|
||||
if (intf && (intf->intf_num == intf_num)) {
|
||||
//*data = (uint8_t *)intf->hid_report_descriptor;
|
||||
memcpy(*data, intf->hid_report_descriptor, intf->hid_report_descriptor_len);
|
||||
*len = intf->hid_report_descriptor_len;
|
||||
@@ -761,22 +742,19 @@ static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t
|
||||
*/
|
||||
static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
|
||||
if (intf && intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
|
||||
return intf->class_interface_handler(setup, data, len);
|
||||
}
|
||||
}
|
||||
} else if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->class_endpoint_handler) {
|
||||
if (intf && intf->class_endpoint_handler) {
|
||||
return intf->class_endpoint_handler(setup, data, len);
|
||||
}
|
||||
}
|
||||
@@ -797,45 +775,56 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **
|
||||
*/
|
||||
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t desclen;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv1_descriptor->vendor_code) {
|
||||
if (g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->msosv1_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->compat_id_len;
|
||||
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
|
||||
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->compat_id;
|
||||
*len = desclen;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property_len;
|
||||
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (usbd_core_cfg.descriptors->msosv2_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv2_descriptor->vendor_code) {
|
||||
} else if (g_usbd_core.descriptors->msosv2_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->msosv2_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv2_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv2_descriptor->compat_id_len;
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv2_descriptor->compat_id;
|
||||
*len = g_usbd_core.descriptors->msosv2_descriptor->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (usbd_core_cfg.descriptors->webusb_url_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->webusb_url_descriptor->vendor_code) {
|
||||
} else if (g_usbd_core.descriptors->webusb_url_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->webusb_url_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET Webusb url Descriptor\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->webusb_url_descriptor->string;
|
||||
*len = usbd_core_cfg.descriptors->webusb_url_descriptor->string_len;
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->webusb_url_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->webusb_url_descriptor->string_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
@@ -844,36 +833,42 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (msosv1_desc) {
|
||||
if (setup->bRequest == msosv1_desc->vendor_code) {
|
||||
if (g_usbd_core.msosv1_desc) {
|
||||
if (setup->bRequest == g_usbd_core.msosv1_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
//*data = (uint8_t *)msosv1_desc->compat_id;
|
||||
memcpy(*data, msosv1_desc->compat_id, msosv1_desc->compat_id_len);
|
||||
*len = msosv1_desc->compat_id_len;
|
||||
|
||||
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
|
||||
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
|
||||
memcpy(*data, g_usbd_core.msosv1_desc->compat_id, desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
//*data = (uint8_t *)msosv1_desc->comp_id_property;
|
||||
memcpy(*data, msosv1_desc->comp_id_property, msosv1_desc->comp_id_property_len);
|
||||
*len = msosv1_desc->comp_id_property_len;
|
||||
|
||||
//*data = (uint8_t *)msosv1_desc->comp_id_property[setup->wValue];
|
||||
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
|
||||
memcpy(*data, g_usbd_core.msosv1_desc->comp_id_property[setup->wValue], desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (msosv2_desc) {
|
||||
if (setup->bRequest == msosv2_desc->vendor_code) {
|
||||
} else if (g_usbd_core.msosv2_desc) {
|
||||
if (setup->bRequest == g_usbd_core.msosv2_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
//*data = (uint8_t *)msosv2_desc->compat_id;
|
||||
memcpy(*data, msosv2_desc->compat_id, msosv2_desc->compat_id_len);
|
||||
*len = msosv2_desc->compat_id_len;
|
||||
memcpy(*data, g_usbd_core.msosv2_desc->compat_id, g_usbd_core.msosv2_desc->compat_id_len);
|
||||
*len = g_usbd_core.msosv2_desc->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
@@ -882,13 +877,10 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
}
|
||||
}
|
||||
#endif
|
||||
usb_slist_t *i;
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
|
||||
if (intf->vendor_handler && !intf->vendor_handler(setup, data, len)) {
|
||||
if (intf && intf->vendor_handler && (intf->vendor_handler(setup, data, len) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -910,11 +902,20 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
|
||||
case USB_REQUEST_STANDARD:
|
||||
if (usbd_standard_request_handler(setup, data, len) < 0) {
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (g_usbd_core.speed == USB_SPEED_FULL) {
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef CONFIG_USB_HS
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
USB_LOG_ERR("standard request error\r\n");
|
||||
usbd_print_setup(setup);
|
||||
@@ -945,18 +946,16 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
|
||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (arg) {
|
||||
struct usb_interface_descriptor *desc = (struct usb_interface_descriptor *)arg;
|
||||
if (intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
|
||||
if (intf && intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
|
||||
intf->notify_handler(event, arg);
|
||||
}
|
||||
} else {
|
||||
if (intf->notify_handler) {
|
||||
if (intf && intf->notify_handler) {
|
||||
intf->notify_handler(event, arg);
|
||||
}
|
||||
}
|
||||
@@ -986,11 +985,10 @@ void usbd_event_suspend_handler(void)
|
||||
void usbd_event_reset_handler(void)
|
||||
{
|
||||
usbd_set_address(0);
|
||||
usbd_core_cfg.configured = 0;
|
||||
usbd_core_cfg.configuration = 0;
|
||||
g_usbd_core.configuration = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
usbd_core_cfg.test_mode = false;
|
||||
g_usbd_core.test_mode = false;
|
||||
#endif
|
||||
struct usbd_endpoint_cfg ep0_cfg;
|
||||
|
||||
@@ -1008,7 +1006,7 @@ void usbd_event_reset_handler(void)
|
||||
|
||||
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
memcpy(setup, psetup, 8);
|
||||
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
|
||||
@@ -1022,65 +1020,65 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
}
|
||||
}
|
||||
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
usbd_core_cfg.ep0_data_buf_residue = setup->wLength;
|
||||
usbd_core_cfg.ep0_data_buf_len = setup->wLength;
|
||||
usbd_core_cfg.zlp_flag = false;
|
||||
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
|
||||
g_usbd_core.ep0_data_buf_residue = setup->wLength;
|
||||
g_usbd_core.ep0_data_buf_len = setup->wLength;
|
||||
g_usbd_core.zlp_flag = false;
|
||||
|
||||
/* handle class request when all the data is received */
|
||||
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, setup->wLength);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ask installed handler to process request */
|
||||
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
|
||||
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
|
||||
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
/* send status in test mode, so do not execute downward, just return */
|
||||
if (usbd_core_cfg.test_mode) {
|
||||
usbd_core_cfg.test_mode = false;
|
||||
if (g_usbd_core.test_mode) {
|
||||
g_usbd_core.test_mode = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* Send smallest of requested and offered length */
|
||||
usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, setup->wLength);
|
||||
if (usbd_core_cfg.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
|
||||
g_usbd_core.ep0_data_buf_residue = MIN(g_usbd_core.ep0_data_buf_len, setup->wLength);
|
||||
if (g_usbd_core.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
|
||||
USB_LOG_ERR("Request buffer too small\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send data or status to host */
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
/*
|
||||
* Set ZLP flag when host asks for a bigger length and the data size is
|
||||
* multiplier of USB_CTRL_EP_MPS, to indicate the transfer done after zlp
|
||||
* sent.
|
||||
*/
|
||||
if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
|
||||
usbd_core_cfg.zlp_flag = true;
|
||||
if ((setup->wLength > g_usbd_core.ep0_data_buf_len) && (!(g_usbd_core.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
|
||||
g_usbd_core.zlp_flag = true;
|
||||
USB_LOG_DBG("EP0 Set zlp\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
usbd_core_cfg.ep0_data_buf += nbytes;
|
||||
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
|
||||
g_usbd_core.ep0_data_buf += nbytes;
|
||||
g_usbd_core.ep0_data_buf_residue -= nbytes;
|
||||
|
||||
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
|
||||
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
|
||||
|
||||
if (usbd_core_cfg.ep0_data_buf_residue != 0) {
|
||||
if (g_usbd_core.ep0_data_buf_residue != 0) {
|
||||
/* Start sending the remain data */
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
} else {
|
||||
if (usbd_core_cfg.zlp_flag == true) {
|
||||
usbd_core_cfg.zlp_flag = false;
|
||||
if (g_usbd_core.zlp_flag == true) {
|
||||
g_usbd_core.zlp_flag = false;
|
||||
/* Send zlp to host */
|
||||
USB_LOG_DBG("EP0 Send zlp\r\n");
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
|
||||
@@ -1100,18 +1098,18 @@ void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
if (nbytes > 0) {
|
||||
usbd_core_cfg.ep0_data_buf += nbytes;
|
||||
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
|
||||
g_usbd_core.ep0_data_buf += nbytes;
|
||||
g_usbd_core.ep0_data_buf_residue -= nbytes;
|
||||
|
||||
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
|
||||
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
|
||||
|
||||
if (usbd_core_cfg.ep0_data_buf_residue == 0) {
|
||||
if (g_usbd_core.ep0_data_buf_residue == 0) {
|
||||
/* Received all, send data to handler */
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
|
||||
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
|
||||
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
|
||||
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
|
||||
return;
|
||||
}
|
||||
@@ -1120,7 +1118,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
|
||||
} else {
|
||||
/* Start reading the remain data */
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
}
|
||||
} else {
|
||||
/* Read out status completely, do nothing */
|
||||
@@ -1130,166 +1128,95 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_TX_THREAD
|
||||
if (tx_msg[ep & 0x7f].cb) {
|
||||
tx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
if (g_usbd_core.tx_msg[ep & 0x7f].cb) {
|
||||
g_usbd_core.tx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
tx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_tx_mq, (uintptr_t)&tx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_RX_THREAD
|
||||
if (rx_msg[ep & 0x7f].cb) {
|
||||
rx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
rx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_rx_mq, (uintptr_t)&rx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_THREAD
|
||||
static void usbdev_tx_thread(void *argument)
|
||||
{
|
||||
struct usbd_tx_rx_msg *msg;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usbd_tx_mq, (uintptr_t *)&msg, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg->cb) {
|
||||
msg->cb(msg->ep, msg->nbytes);
|
||||
}
|
||||
if (g_usbd_core.rx_msg[ep & 0x7f].cb) {
|
||||
g_usbd_core.rx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_RX_THREAD
|
||||
static void usbdev_rx_thread(void *argument)
|
||||
{
|
||||
struct usbd_tx_rx_msg *msg;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usbd_rx_mq, (uintptr_t *)&msg, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg->cb) {
|
||||
msg->cb(msg->ep, msg->nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
void usbd_desc_register(struct usb_descriptor *desc)
|
||||
{
|
||||
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
|
||||
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
|
||||
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
g_usbd_core.descriptors = desc;
|
||||
g_usbd_core.intf_offset = 0;
|
||||
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
g_usbd_core.tx_msg[0].ep = 0x80;
|
||||
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
g_usbd_core.rx_msg[0].ep = 0x00;
|
||||
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc)
|
||||
{
|
||||
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
|
||||
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
|
||||
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
g_usbd_core.descriptors = desc;
|
||||
g_usbd_core.intf_offset = 0;
|
||||
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
g_usbd_core.tx_msg[0].ep = 0x80;
|
||||
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
g_usbd_core.rx_msg[0].ep = 0x00;
|
||||
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
|
||||
/* Register MS OS Descriptors version 1 */
|
||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc)
|
||||
{
|
||||
msosv1_desc = desc;
|
||||
g_usbd_core.msosv1_desc = desc;
|
||||
}
|
||||
|
||||
/* Register MS OS Descriptors version 2 */
|
||||
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc)
|
||||
{
|
||||
msosv2_desc = desc;
|
||||
g_usbd_core.msosv2_desc = desc;
|
||||
}
|
||||
|
||||
void usbd_bos_desc_register(struct usb_bos_descriptor *desc)
|
||||
{
|
||||
bos_desc = desc;
|
||||
g_usbd_core.bos_desc = desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(struct usbd_interface *intf)
|
||||
{
|
||||
intf->intf_num = usbd_core_cfg.intf_offset;
|
||||
usb_slist_add_tail(&usbd_intf_head, &intf->list);
|
||||
usbd_core_cfg.intf_offset++;
|
||||
intf->intf_num = g_usbd_core.intf_offset;
|
||||
g_usbd_core.intf[g_usbd_core.intf_offset] = intf;
|
||||
g_usbd_core.intf_offset++;
|
||||
}
|
||||
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep)
|
||||
{
|
||||
if (ep->ep_addr & 0x80) {
|
||||
tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
} else {
|
||||
rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_device_is_configured(void)
|
||||
{
|
||||
return usbd_core_cfg.configured;
|
||||
return g_usbd_core.configuration;
|
||||
}
|
||||
|
||||
int usbd_initialize(void)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_TX_THREAD
|
||||
usbd_tx_mq = usb_osal_mq_create(16);
|
||||
if (usbd_tx_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
usbd_tx_thread = usb_osal_thread_create("usbd_tx", CONFIG_USBDEV_TX_STACKSIZE, CONFIG_USBDEV_TX_PRIO, usbdev_tx_thread, NULL);
|
||||
if (usbd_tx_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_USBDEV_RX_THREAD
|
||||
usbd_rx_mq = usb_osal_mq_create(16);
|
||||
if (usbd_rx_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
usbd_rx_thread = usb_osal_thread_create("usbd_rx", CONFIG_USBDEV_RX_STACKSIZE, CONFIG_USBDEV_RX_PRIO, usbdev_rx_thread, NULL);
|
||||
if (usbd_rx_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return usb_dc_init();
|
||||
}
|
||||
|
||||
int usbd_deinitialize(void)
|
||||
{
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
usb_slist_init(&usbd_intf_head);
|
||||
g_usbd_core.intf_offset = 0;
|
||||
usb_dc_deinit();
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1307,7 +1234,6 @@ __WEAK void usbd_event_handler(uint8_t event)
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
usbd_configure_done_callback();
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
@@ -46,15 +46,12 @@ typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **da
|
||||
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
|
||||
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
||||
|
||||
extern usb_slist_t usbd_intf_head;
|
||||
|
||||
struct usbd_endpoint {
|
||||
uint8_t ep_addr;
|
||||
usbd_endpoint_callback ep_cb;
|
||||
};
|
||||
|
||||
struct usbd_interface {
|
||||
usb_slist_t list;
|
||||
usbd_request_handler class_interface_handler;
|
||||
usbd_request_handler class_endpoint_handler;
|
||||
usbd_request_handler vendor_handler;
|
||||
@@ -91,7 +88,6 @@ void usbd_add_interface(struct usbd_interface *intf);
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep);
|
||||
|
||||
bool usb_device_is_configured(void);
|
||||
void usbd_configure_done_callback(void);
|
||||
int usbd_initialize(void);
|
||||
int usbd_deinitialize(void);
|
||||
|
||||
|
||||
136
core/usbh_core.c
@@ -13,8 +13,8 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
|
||||
#define USB_DEV_ADDR_MAX 0x7f
|
||||
#define USB_DEV_ADDR_MARK_OFFSET 5
|
||||
@@ -270,23 +270,6 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
||||
void usbh_print_string(char *lead, uint8_t *str)
|
||||
{
|
||||
uint8_t string[64 + 1] = { 0 };
|
||||
|
||||
int len, i = 2, j = 0;
|
||||
|
||||
len = str[0];
|
||||
while (i < len) {
|
||||
string[j] = str[i];
|
||||
i += 2;
|
||||
j++;
|
||||
}
|
||||
USB_LOG_RAW("%s%s\r\n", lead, string);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_print_hubport_info(struct usbh_hubport *hport)
|
||||
{
|
||||
USB_LOG_RAW("Device Descriptor:\r\n");
|
||||
@@ -408,6 +391,54 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
|
||||
return usbh_pipe_alloc(pipe, &ep_cfg);
|
||||
}
|
||||
|
||||
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
|
||||
{
|
||||
struct usb_setup_packet *setup = hport->setup;
|
||||
int ret;
|
||||
uint8_t *src;
|
||||
uint8_t *dst;
|
||||
uint16_t len;
|
||||
uint16_t i = 2;
|
||||
uint16_t j = 0;
|
||||
|
||||
/* Get Manufacturer string */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
|
||||
setup->wIndex = 0x0409;
|
||||
setup->wLength = 255;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
src = ep0_request_buffer;
|
||||
dst = output;
|
||||
len = src[0];
|
||||
|
||||
while (i < len) {
|
||||
dst[j] = src[i];
|
||||
i += 2;
|
||||
j++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting)
|
||||
{
|
||||
struct usb_setup_packet *setup = hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = intf;
|
||||
setup->wIndex = altsetting;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_enumerate(struct usbh_hubport *hport)
|
||||
{
|
||||
struct usb_interface_descriptor *intf_desc;
|
||||
@@ -553,50 +584,37 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
}
|
||||
memcpy(hport->raw_config_desc, ep0_request_buffer, wTotalLength);
|
||||
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
||||
/* Get Manufacturer string */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_MFC_INDEX);
|
||||
setup->wIndex = 0x0409;
|
||||
setup->wLength = 255;
|
||||
uint8_t string_buffer[128];
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
/* Get Manufacturer string */
|
||||
memset(string_buffer, 0, 128);
|
||||
ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
usbh_print_string("Manufacturer: ", ep0_request_buffer);
|
||||
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
|
||||
|
||||
/* Get Product string */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_PRODUCT_INDEX);
|
||||
setup->wIndex = 0x0409;
|
||||
setup->wLength = 255;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
memset(string_buffer, 0, 128);
|
||||
ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
usbh_print_string("Product: ", ep0_request_buffer);
|
||||
USB_LOG_INFO("Product: %s\r\n", string_buffer);
|
||||
|
||||
/* Get SerialNumber string */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_SERIAL_INDEX);
|
||||
setup->wIndex = 0x0409;
|
||||
setup->wLength = 255;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
memset(string_buffer, 0, 128);
|
||||
ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
usbh_print_string("SerialNumber: ", ep0_request_buffer);
|
||||
USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
|
||||
#endif
|
||||
/* Select device configuration 1 */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
@@ -611,6 +629,19 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_MSOS_ENABLE
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0x0004;
|
||||
setup->wLength = 16;
|
||||
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0 && (ret != -EPERM)) {
|
||||
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
|
||||
/*search supported class driver*/
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
@@ -639,25 +670,6 @@ errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
usb_slist_t *hub_list;
|
||||
usb_slist_for_each(hub_list, &hub_class_head)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
if (hport->dev_addr == dev_addr) {
|
||||
return &hub->child[port];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *usbh_find_class_instance(const char *devname)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
@@ -152,6 +152,7 @@ struct usbh_hubport {
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
usb_osal_thread_t thread;
|
||||
};
|
||||
|
||||
struct usbh_hub {
|
||||
@@ -168,6 +169,16 @@ struct usbh_hub {
|
||||
struct usbh_hubport *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Activates an endpoint for a USB host pipe on a specific hub port.
|
||||
*
|
||||
* This function is responsible for activating the specified endpoint
|
||||
* described by the given endpoint descriptor on the USB host pipe.
|
||||
* @param pipe Pointer to the USB host pipe structure.
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param ep_desc Pointer to the USB endpoint descriptor.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
|
||||
|
||||
/**
|
||||
@@ -182,8 +193,35 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
|
||||
*/
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a USB string descriptor from a specific hub port.
|
||||
*
|
||||
* This function is responsible for retrieving the USB string descriptor
|
||||
* with the specified index from the USB device connected to the given hub port.
|
||||
* The retrieved descriptor is stored in the output buffer provided.
|
||||
*
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param index Index of the string descriptor to retrieve.
|
||||
* @param output Pointer to the buffer where the retrieved descriptor will be stored.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief Sets the alternate setting for a USB interface on a specific hub port.
|
||||
*
|
||||
* This function is responsible for setting the alternate setting of the
|
||||
* specified USB interface on the USB device connected to the given hub port.
|
||||
* The interface and alternate setting are identified by the respective parameters.
|
||||
*
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param intf Interface number to set the alternate setting for.
|
||||
* @param altsetting Alternate setting value to set for the interface.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
|
||||
|
||||
int usbh_initialize(void);
|
||||
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#define AUDIO_IN_EP 0x81
|
||||
|
||||
#define AUDIO_IN_FU_ID 0x02
|
||||
|
||||
/* AUDIO Class Config */
|
||||
#define AUDIO_FREQ 16000U
|
||||
|
||||
@@ -61,13 +63,13 @@
|
||||
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \
|
||||
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v1_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
|
||||
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
|
||||
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, INPUT_CTRL),
|
||||
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
|
||||
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL),
|
||||
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID),
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
@@ -143,19 +145,40 @@ const uint8_t audio_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
}
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
tx_flag = 1;
|
||||
USB_LOG_RAW("OPEN\r\n");
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
USB_LOG_RAW("CLOSE\r\n");
|
||||
@@ -176,14 +199,18 @@ static struct usbd_endpoint audio_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
void audio_v1_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_v1_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 1));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 1));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#define AUDIO_IN_EP 0x81
|
||||
#define AUDIO_OUT_EP 0x02
|
||||
|
||||
#define AUDIO_IN_FU_ID 0x02
|
||||
#define AUDIO_OUT_FU_ID 0x05
|
||||
|
||||
/* AUDIO Class Config */
|
||||
#define AUDIO_SPEAKER_FREQ 16000U
|
||||
#define AUDIO_SPEAKER_FRAME_SIZE_BYTE 2u
|
||||
@@ -49,7 +52,7 @@
|
||||
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v1_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
|
||||
@@ -59,9 +62,9 @@ const uint8_t audio_descriptor[] = {
|
||||
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
|
||||
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
|
||||
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,\
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
|
||||
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,\
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
|
||||
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
@@ -137,24 +140,51 @@ const uint8_t audio_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
volatile bool rx_flag = 0;
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
printf("OPEN1\r\n");
|
||||
} else {
|
||||
tx_flag = 1;
|
||||
printf("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
@@ -166,16 +196,10 @@ void usbd_audio_close(uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -198,32 +222,36 @@ struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void audio_init()
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2));
|
||||
usbd_desc_register(audio_v1_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v1_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||
while (ep_tx_busy_flag) {
|
||||
if (tx_flag == false) {
|
||||
break;
|
||||
}
|
||||
if (tx_flag) {
|
||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||
while (ep_tx_busy_flag) {
|
||||
if (tx_flag == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#define AUDIO_IN_EP 0x81
|
||||
|
||||
#define AUDIO_IN_CLOCK_ID 0x01
|
||||
#define AUDIO_IN_FU_ID 0x03
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -50,7 +53,6 @@
|
||||
|
||||
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||
|
||||
|
||||
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
|
||||
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||
@@ -65,7 +67,7 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
|
||||
@@ -157,29 +159,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
tx_flag = 1;
|
||||
USB_LOG_RAW("OPEN\r\n");
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
USB_LOG_RAW("CLOSE\r\n");
|
||||
tx_flag = 0;
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_IN_EP) {
|
||||
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
}
|
||||
|
||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
}
|
||||
@@ -192,23 +215,27 @@ static struct usbd_endpoint audio_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_IN_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (tx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#define AUDIO_OUT_EP 0x02
|
||||
#define AUDIO_IN_EP 0x81
|
||||
|
||||
#define AUDIO_OUT_CLOCK_ID 0x01
|
||||
#define AUDIO_OUT_FU_ID 0x03
|
||||
#define AUDIO_IN_CLOCK_ID 0x05
|
||||
#define AUDIO_IN_FU_ID 0x07
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -49,36 +54,34 @@
|
||||
#define INPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
|
||||
#define OUT_CHANNEL_NUM 2
|
||||
|
||||
#if OUT_CHANNEL_NUM == 1
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000000
|
||||
#elif OUT_CHANNEL_NUM == 2
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000003
|
||||
#elif OUT_CHANNEL_NUM == 3
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000007
|
||||
#elif OUT_CHANNEL_NUM == 4
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||
#elif OUT_CHANNEL_NUM == 5
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||
#elif OUT_CHANNEL_NUM == 6
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||
#elif OUT_CHANNEL_NUM == 7
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||
#elif OUT_CHANNEL_NUM == 8
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
|
||||
/* AudioFreq * DataSize (2 bytes) * NumChannels */
|
||||
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
|
||||
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||
@@ -106,7 +109,7 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
uint8_t audio_descriptor[] = {
|
||||
uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
|
||||
@@ -220,23 +223,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
|
||||
AUDIO_SAMPLE_FREQ_4B(0x00)
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
volatile bool rx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
USB_LOG_RAW("OPEN1\r\n");
|
||||
} else {
|
||||
tx_flag = 1;
|
||||
USB_LOG_RAW("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
@@ -248,36 +278,34 @@ void usbd_audio_close(uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
|
||||
} else if (entity_id == 0x05) {
|
||||
} else if (ep == AUDIO_IN_EP) {
|
||||
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
uint16_t packet_size = 0;
|
||||
if (entity_id == 1) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
|
||||
} else if (entity_id == 5) {
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
|
||||
} else if (ep == AUDIO_IN_EP) {
|
||||
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -298,27 +326,37 @@ struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void audio_init()
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_IN_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2));
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
usbd_audio_add_entity(0x05, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x07, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (rx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#define AUDIO_OUT_EP 0x01
|
||||
|
||||
#define AUDIO_OUT_CLOCK_ID 0x01
|
||||
#define AUDIO_OUT_FU_ID 0x03
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -23,28 +26,28 @@
|
||||
#define OUT_CHANNEL_NUM 2
|
||||
|
||||
#if OUT_CHANNEL_NUM == 1
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000000
|
||||
#elif OUT_CHANNEL_NUM == 2
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000003
|
||||
#elif OUT_CHANNEL_NUM == 3
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000007
|
||||
#elif OUT_CHANNEL_NUM == 4
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||
#elif OUT_CHANNEL_NUM == 5
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||
#elif OUT_CHANNEL_NUM == 6
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||
#elif OUT_CHANNEL_NUM == 7
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||
#elif OUT_CHANNEL_NUM == 8
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
@@ -64,13 +67,13 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
|
||||
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
|
||||
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
|
||||
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
|
||||
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
|
||||
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
|
||||
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
|
||||
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
|
||||
///////////////////////////////////////
|
||||
@@ -166,36 +169,60 @@ static const uint8_t default_sampling_freq_table[] = {
|
||||
AUDIO_SAMPLE_FREQ_4B(0x00),
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
|
||||
volatile bool rx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
USB_LOG_RAW("OPEN\r\n");
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
USB_LOG_RAW("CLOSE\r\n");
|
||||
rx_flag = 0;
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
static struct usbd_endpoint audio_out_ep = {
|
||||
@@ -206,23 +233,27 @@ static struct usbd_endpoint audio_out_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (rx_flag) {
|
||||
}
|
||||
if (rx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,23 @@
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN + 25)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t cdc_acm_hid_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
@@ -136,35 +148,6 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!< hid mouse report descriptor */
|
||||
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
@@ -255,10 +238,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
@@ -360,3 +364,32 @@ void cdc_acm_data_send_with_dtr_test(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,24 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -109,10 +121,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
@@ -26,14 +26,20 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -119,13 +125,34 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
@@ -14,11 +14,17 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -104,10 +110,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
@@ -144,8 +171,8 @@ struct usbd_endpoint cdc_in_ep = {
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
};
|
||||
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
static struct usbd_interface intf0;
|
||||
static struct usbd_interface intf1;
|
||||
|
||||
void cdc_acm_init(void)
|
||||
{
|
||||
|
||||
274
demo/cdc_ecm_template.c
Normal file
@@ -0,0 +1,274 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc_ecm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
#define CDC_OUT_EP 0x02
|
||||
#define CDC_INT_EP 0x83
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ECM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#define CDC_ECM_ETH_STATISTICS_BITMAP 0x00000000
|
||||
|
||||
/* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
|
||||
#define CDC_ECM_MAC_STRING_INDEX 4
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_ecm_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ECM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, CDC_ECM_ETH_STATISTICS_BITMAP, CONFIG_CDC_ECM_ETH_MAX_SEGSZE, 0, 0, CDC_ECM_MAC_STRING_INDEX),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x2E, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'C', 0x00, /* wcChar10 */
|
||||
'D', 0x00, /* wcChar11 */
|
||||
'C', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'E', 0x00, /* wcChar14 */
|
||||
'C', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
' ', 0x00, /* wcChar17 */
|
||||
'D', 0x00, /* wcChar18 */
|
||||
'E', 0x00, /* wcChar19 */
|
||||
'M', 0x00, /* wcChar20 */
|
||||
'O', 0x00, /* wcChar21 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
///////////////////////////////////////
|
||||
/// string4 descriptor
|
||||
///////////////////////////////////////
|
||||
0x1A, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'a', 0x00, /* wcChar0 */
|
||||
'a', 0x00, /* wcChar1 */
|
||||
'b', 0x00, /* wcChar2 */
|
||||
'b', 0x00, /* wcChar3 */
|
||||
'c', 0x00, /* wcChar4 */
|
||||
'c', 0x00, /* wcChar5 */
|
||||
'd', 0x00, /* wcChar6 */
|
||||
'd', 0x00, /* wcChar7 */
|
||||
'e', 0x00, /* wcChar8 */
|
||||
'e', 0x00, /* wcChar9 */
|
||||
'f', 0x00, /* wcChar10 */
|
||||
'f', 0x00, /* wcChar11 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x02,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
|
||||
/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
|
||||
#define IP_ADDR0 (uint8_t)192
|
||||
#define IP_ADDR1 (uint8_t)168
|
||||
#define IP_ADDR2 (uint8_t)123
|
||||
#define IP_ADDR3 (uint8_t)100
|
||||
|
||||
/*NETMASK*/
|
||||
#define NETMASK_ADDR0 (uint8_t)255
|
||||
#define NETMASK_ADDR1 (uint8_t)255
|
||||
#define NETMASK_ADDR2 (uint8_t)255
|
||||
#define NETMASK_ADDR3 (uint8_t)0
|
||||
|
||||
/*Gateway Address*/
|
||||
#define GW_ADDR0 (uint8_t)192
|
||||
#define GW_ADDR1 (uint8_t)168
|
||||
#define GW_ADDR2 (uint8_t)123
|
||||
#define GW_ADDR3 (uint8_t)1
|
||||
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
|
||||
const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
|
||||
static struct netif cdc_ecm_netif; //network interface
|
||||
|
||||
/* Network interface name */
|
||||
#define IFNAME0 'E'
|
||||
#define IFNAME1 'X'
|
||||
|
||||
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
static int ret;
|
||||
|
||||
ret = usbd_cdc_ecm_eth_tx(p);
|
||||
if (ret == 0)
|
||||
return ERR_OK;
|
||||
else
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
err_t cdc_ecm_if_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
netif->state = NULL;
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = linkoutput_fn;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t cdc_ecm_if_input(struct netif *netif)
|
||||
{
|
||||
static err_t err;
|
||||
static struct pbuf *p;
|
||||
|
||||
p = usbd_cdc_ecm_eth_rx();
|
||||
if (p != NULL) {
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
return ERR_BUF;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void cdc_ecm_lwip_init(void)
|
||||
{
|
||||
struct netif *netif = &cdc_ecm_netif;
|
||||
|
||||
lwip_init();
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, mac, 6);
|
||||
|
||||
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, cdc_ecm_if_init, netif_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
// while (dhserv_init(&dhcp_config)) {}
|
||||
|
||||
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
}
|
||||
|
||||
void usbd_cdc_ecm_data_recv_done(void)
|
||||
{
|
||||
}
|
||||
|
||||
void cdc_ecm_input_poll(void)
|
||||
{
|
||||
cdc_ecm_if_input(&cdc_ecm_netif);
|
||||
}
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
/* ecm only supports in linux, and you should input the following command
|
||||
*
|
||||
* sudo ifconfig enxaabbccddeeff up
|
||||
* sudo dhcpclient enxaabbccddeeff
|
||||
*/
|
||||
void cdc_ecm_init(void)
|
||||
{
|
||||
cdc_ecm_lwip_init();
|
||||
|
||||
usbd_desc_register(cdc_ecm_descriptor);
|
||||
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
||||
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
||||
usbd_initialize();
|
||||
}
|
||||
@@ -14,11 +14,17 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_RNDIS_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -95,20 +101,36 @@ static const uint8_t cdc_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
|
||||
#define IP_ADDR0 (uint8_t)192
|
||||
#define IP_ADDR1 (uint8_t)168
|
||||
#define IP_ADDR2 (uint8_t)123
|
||||
#define IP_ADDR3 (uint8_t)100
|
||||
|
||||
/*NETMASK*/
|
||||
#define NETMASK_ADDR0 (uint8_t)255
|
||||
#define NETMASK_ADDR1 (uint8_t)255
|
||||
#define NETMASK_ADDR2 (uint8_t)255
|
||||
#define NETMASK_ADDR3 (uint8_t)0
|
||||
|
||||
/*Gateway Address*/
|
||||
#define GW_ADDR0 (uint8_t)192
|
||||
#define GW_ADDR1 (uint8_t)168
|
||||
#define GW_ADDR2 (uint8_t)123
|
||||
#define GW_ADDR3 (uint8_t)1
|
||||
|
||||
#ifdef RT_USING_LWIP
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <netif/ethernetif.h>
|
||||
|
||||
const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
|
||||
const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
|
||||
struct eth_device rndis_dev;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
eth_device_linkchange(&rndis_dev, RT_TRUE);
|
||||
}
|
||||
|
||||
uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
|
||||
static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
switch (cmd) {
|
||||
@@ -139,7 +161,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(uint8_t *data, uint32_t len)
|
||||
void usbd_rndis_data_recv_done(void)
|
||||
{
|
||||
eth_device_ready(&rndis_dev);
|
||||
}
|
||||
@@ -155,12 +177,120 @@ void rt_usbd_rndis_init(void)
|
||||
eth_device_linkchange(&rndis_dev, RT_FALSE);
|
||||
}
|
||||
#else
|
||||
void usbd_configure_done_callback(void)
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
|
||||
const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
|
||||
static struct netif rndis_netif; //network interface
|
||||
|
||||
/* Network interface name */
|
||||
#define IFNAME0 'E'
|
||||
#define IFNAME1 'X'
|
||||
|
||||
err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
static int ret;
|
||||
|
||||
ret = usbd_rndis_eth_tx(p);
|
||||
if (ret == 0)
|
||||
return ERR_OK;
|
||||
else
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
err_t rndisif_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
netif->state = NULL;
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = linkoutput_fn;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t rndisif_input(struct netif *netif)
|
||||
{
|
||||
static err_t err;
|
||||
static struct pbuf *p;
|
||||
|
||||
p = usbd_rndis_eth_rx();
|
||||
if (p != NULL) {
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
return ERR_BUF;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void rndis_lwip_init(void)
|
||||
{
|
||||
struct netif *netif = &rndis_netif;
|
||||
|
||||
lwip_init();
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, mac, 6);
|
||||
|
||||
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, rndisif_init, netif_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
// while (dhserv_init(&dhcp_config)) {}
|
||||
|
||||
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||
}
|
||||
|
||||
void usbd_rndis_data_recv_done(void)
|
||||
{
|
||||
}
|
||||
|
||||
void rndis_input_poll(void)
|
||||
{
|
||||
rndisif_input(&rndis_netif);
|
||||
}
|
||||
#endif /* RT_USING_LWIP */
|
||||
|
||||
void usbd_event_handler(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:
|
||||
#ifdef RT_USING_LWIP
|
||||
eth_device_linkchange(&rndis_dev, RT_TRUE);
|
||||
#endif
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
@@ -168,6 +298,8 @@ void cdc_rndis_init(void)
|
||||
{
|
||||
#ifdef RT_USING_LWIP
|
||||
rt_usbd_rndis_init();
|
||||
#else
|
||||
rndis_lwip_init();
|
||||
#endif
|
||||
usbd_desc_register(cdc_descriptor);
|
||||
usbd_add_interface(usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
|
||||
#define DAP_IN_EP 0x81
|
||||
#define DAP_OUT_EP 0x02
|
||||
|
||||
#define CDC_IN_EP 0x83
|
||||
#define CDC_OUT_EP 0x04
|
||||
#define CDC_INT_EP 0x85
|
||||
|
||||
#define USBD_VID 0xd6e7
|
||||
#define USBD_PID 0x3507
|
||||
#define USBD_MAX_POWER 500
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define CMSIS_DAP_INTERFACE_SIZE (9 + 7 + 7)
|
||||
#define USB_CONFIG_SIZE (9 + CMSIS_DAP_INTERFACE_SIZE + CDC_ACM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#define WCID_VENDOR_CODE 0x01
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
///////////////////////////////////////
|
||||
0x12, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
/* MSFT100 */
|
||||
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
|
||||
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
|
||||
WCID_VENDOR_CODE, /* bVendorCode */
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x28, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x01, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x00, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
|
||||
.string_len = 18,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
|
||||
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
|
||||
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
|
||||
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
|
||||
};
|
||||
|
||||
const uint8_t daplink_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
/* Configuration 0 */
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
|
||||
/* Endpoint IN 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x00),
|
||||
/* String 0 (LANGID) */
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
/* String 1 (Manufacturer) */
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
/* String 2 (Product) */
|
||||
0x28, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'C', 0x00, // wcChar0
|
||||
'h', 0x00, // wcChar1
|
||||
'e', 0x00, // wcChar2
|
||||
'r', 0x00, // wcChar3
|
||||
'r', 0x00, // wcChar4
|
||||
'y', 0x00, // wcChar5
|
||||
'U', 0x00, // wcChar6
|
||||
'S', 0x00, // wcChar7
|
||||
'B', 0x00, // wcChar8
|
||||
' ', 0x00, // wcChar9
|
||||
'C', 0x00, // wcChar10
|
||||
'M', 0x00, // wcChar11
|
||||
'S', 0x00, // wcChar12
|
||||
'I', 0x00, // wcChar13
|
||||
'S', 0x00, // wcChar14
|
||||
'-', 0x00, // wcChar15
|
||||
'D', 0x00, // wcChar16
|
||||
'A', 0x00, // wcChar17
|
||||
'P', 0x00, // wcChar18
|
||||
/* String 3 (Serial Number) */
|
||||
0x1A, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'0', 0, // wcChar0
|
||||
'1', 0, // wcChar1
|
||||
'2', 0, // wcChar2
|
||||
'3', 0, // wcChar3
|
||||
'4', 0, // wcChar4
|
||||
'5', 0, // wcChar5
|
||||
'A', 0, // wcChar6
|
||||
'B', 0, // wcChar7
|
||||
'C', 0, // wcChar8
|
||||
'D', 0, // wcChar9
|
||||
'E', 0, // wcChar10
|
||||
'F', 0, // wcChar11
|
||||
#ifdef CONFIG_USB_HS
|
||||
/* Device Qualifier */
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x10,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
/* End */
|
||||
0x00
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_read_buffer[CDC_MAX_MPS];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Request[DAP_PACKET_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Response[DAP_PACKET_SIZE];
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
|
||||
usbd_ep_start_read(DAP_OUT_EP, USB_Request, DAP_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
/* setup next out ep read transfer */
|
||||
if (1) {
|
||||
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_dap_recv_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
uint32_t actual_len;
|
||||
if (USB_Request[0] == ID_DAP_TransferAbort) {
|
||||
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
|
||||
DAP_TransferAbort = 1;
|
||||
return;
|
||||
}
|
||||
actual_len = DAP_ProcessCommand(USB_Request, USB_Response);
|
||||
|
||||
usbd_ep_start_write(DAP_IN_EP, USB_Response, actual_len & 0xffff);
|
||||
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void usb_dap_send_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(DAP_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint cdc_out_ep = {
|
||||
.ep_addr = CDC_OUT_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_out
|
||||
};
|
||||
|
||||
static struct usbd_endpoint cdc_in_ep = {
|
||||
.ep_addr = CDC_IN_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
};
|
||||
|
||||
static struct usbd_endpoint dap_out_ep = {
|
||||
.ep_addr = DAP_OUT_EP,
|
||||
.ep_cb = usb_dap_recv_callback
|
||||
};
|
||||
static struct usbd_endpoint dap_in_ep = {
|
||||
.ep_addr = DAP_IN_EP,
|
||||
.ep_cb = usb_dap_send_callback
|
||||
};
|
||||
|
||||
struct usbd_interface dap_interface;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void daplink_init(void)
|
||||
{
|
||||
usbd_desc_register(daplink_descriptor);
|
||||
usbd_msosv1_desc_register(&msosv1_desc);
|
||||
|
||||
/*!< winusb */
|
||||
usbd_add_interface(&dap_interface);
|
||||
usbd_add_endpoint(&dap_out_ep);
|
||||
usbd_add_endpoint(&dap_in_ep);
|
||||
|
||||
/*!< cdc acm */
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
|
||||
usbd_add_endpoint(&cdc_out_ep);
|
||||
usbd_add_endpoint(&cdc_in_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
@@ -137,9 +137,29 @@ const uint8_t dfu_flash_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/*!< hidraw in endpoint */
|
||||
#define HIDRAW_IN_EP 0x81
|
||||
#define HIDRAW_IN_SIZE 64
|
||||
#define HIDRAW_IN_EP_SIZE 64
|
||||
#define HIDRAW_IN_INTERVAL 10
|
||||
|
||||
/*!< hidraw out endpoint */
|
||||
@@ -20,7 +20,7 @@
|
||||
#define USB_HID_CONFIG_DESC_SIZ (9 + 9 + 9 + 7 + 7)
|
||||
|
||||
/*!< custom hid report descriptor size */
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 34
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 38
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t hid_descriptor[] = {
|
||||
@@ -51,7 +51,7 @@ static const uint8_t hid_descriptor[] = {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
WBVAL(HIDRAW_IN_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
WBVAL(HIDRAW_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||
/******************** Descriptor of Custom out endpoint ********************/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
@@ -61,13 +61,13 @@ static const uint8_t hid_descriptor[] = {
|
||||
WBVAL(HIDRAW_OUT_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 73 */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string0 descriptor
|
||||
*/
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string1 descriptor
|
||||
*/
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
@@ -79,9 +79,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string2 descriptor
|
||||
*/
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
@@ -102,9 +102,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string3 descriptor
|
||||
*/
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
@@ -118,9 +118,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* device qualifier descriptor
|
||||
*/
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
@@ -138,38 +138,62 @@ static const uint8_t hid_descriptor[] = {
|
||||
/*!< custom hid report descriptor */
|
||||
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||
/* USER CODE BEGIN 0 */
|
||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Defined Page 1) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0xa1, 0x01, /* COLLECTION (Application) */
|
||||
0x85, 0x02, /* REPORT ID (0x02) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */
|
||||
0x95, 0x40 - 1, /* REPORT_COUNT (63) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x81, 0x02, /* INPUT (Data,Var,Abs) */
|
||||
/* <___________________________________________________> */
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
0x85, 0x01, /* REPORT ID (0x01) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */
|
||||
0x95, 0x40 - 1, /* REPORT_COUNT (63) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
||||
/* USER CODE END 0 */
|
||||
0xC0 /* END_COLLECTION */
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[HIDRAW_OUT_EP_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t send_buffer[HIDRAW_IN_EP_SIZE];
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t custom_state = HID_STATE_IDLE;
|
||||
static volatile uint8_t custom_state;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_hid_custom_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -182,6 +206,8 @@ static void usbd_hid_custom_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
|
||||
read_buffer[0] = 0x02; /* IN: report id */
|
||||
usbd_ep_start_write(HIDRAW_IN_EP, read_buffer, nbytes);
|
||||
}
|
||||
|
||||
static struct usbd_endpoint custom_in_ep = {
|
||||
@@ -194,9 +220,16 @@ static struct usbd_endpoint custom_out_ep = {
|
||||
.ep_addr = HIDRAW_OUT_EP
|
||||
};
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief hid custom init
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_custom_keyboard_init(void)
|
||||
void hid_custom_init(void)
|
||||
{
|
||||
usbd_desc_register(hid_descriptor);
|
||||
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||
@@ -205,16 +238,3 @@ void hid_custom_keyboard_init(void)
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void hid_custom_test(void)
|
||||
{
|
||||
uint8_t sendbuffer[64] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int ret = usbd_ep_start_write(HIDRAW_IN_EP, sendbuffer, 8);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
custom_state = HID_STATE_BUSY;
|
||||
while (custom_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
||||
@@ -172,9 +172,29 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
@@ -204,11 +224,14 @@ void hid_keyboard_init(void)
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
|
||||
|
||||
void hid_keyboard_test(void)
|
||||
{
|
||||
uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
|
||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int ret = usbd_ep_start_write(HID_INT_EP, sendbuffer, 8);
|
||||
memcpy(write_buffer, sendbuffer, 8);
|
||||
int ret = usbd_ep_start_write(HID_INT_EP, write_buffer, 8);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ struct hid_mouse {
|
||||
};
|
||||
|
||||
/*!< mouse report */
|
||||
static struct hid_mouse mouse_cfg;
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
@@ -194,9 +194,29 @@ static struct hid_mouse mouse_cfg;
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
@@ -236,15 +256,20 @@ void hid_mouse_init(void)
|
||||
*/
|
||||
void hid_mouse_test(void)
|
||||
{
|
||||
/*!< move mouse pointer */
|
||||
mouse_cfg.x += 10;
|
||||
mouse_cfg.y = 0;
|
||||
int counter = 0;
|
||||
while (counter < 1000) {
|
||||
/*!< move mouse pointer */
|
||||
mouse_cfg.x += 40;
|
||||
mouse_cfg.y += 0;
|
||||
|
||||
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
hid_state = HID_STATE_BUSY;
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
hid_state = HID_STATE_BUSY;
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usb_midi.h"
|
||||
|
||||
#define MIDI_OUT_EP 0x02
|
||||
#define MIDI_IN_EP 0x81
|
||||
|
||||
#define USBD_VID 0x0d28
|
||||
#define USBD_PID 0x0404
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 9 + 9 + 7 + MIDI_SIZEOF_JACK_DESC + 9 + 5 + 9 + 5)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MIDI_EP_MPS 512
|
||||
#else
|
||||
#define MIDI_EP_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t midi_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
@@ -48,11 +64,11 @@ const uint8_t midi_descriptor[] = {
|
||||
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
|
||||
MIDI_JACK_DESCRIPTOR_INIT(0x01),
|
||||
// OUT endpoint descriptor
|
||||
0x09, 0x05, 0x02, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||
0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
|
||||
0x05, 0x25, 0x01, 0x01, 0x01,
|
||||
|
||||
// IN endpoint descriptor
|
||||
0x09, 0x05, 0x81, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||
0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
|
||||
0x05, 0x25, 0x01, 0x01, 0x03,
|
||||
|
||||
///////////////////////////////////////
|
||||
@@ -130,6 +146,31 @@ const uint8_t midi_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_midi_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x02
|
||||
|
||||
/*!< endpoint address */
|
||||
/*!< hidraw in endpoint */
|
||||
#define HIDRAW_IN_EP 0x83
|
||||
#define HIDRAW_IN_SIZE 64
|
||||
#define HIDRAW_IN_INTERVAL 10
|
||||
|
||||
/*!< hidraw out endpoint */
|
||||
#define HIDRAW_OUT_EP 0x04
|
||||
#define HIDRAW_OUT_EP_SIZE 64
|
||||
#define HIDRAW_OUT_EP_INTERVAL 10
|
||||
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFc
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< custom hid report descriptor size */
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 34
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN + 9+ 9 + 7 + 7)
|
||||
|
||||
const uint8_t hid_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
/************** Descriptor of Custom interface *****************/
|
||||
/* 41 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Custom HID ********************/
|
||||
/* 50 */
|
||||
0x09, /* bLength: HID Descriptor size */
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||
0x11, /* bcdHID: HID Class Spec release number */
|
||||
0x01,
|
||||
0x00, /* bCountryCode: Hardware target country */
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||
0x22, /* bDescriptorType */
|
||||
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Custom in endpoint ********************/
|
||||
/* 59 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HIDRAW_IN_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||
/******************** Descriptor of Custom out endpoint ********************/
|
||||
/* 66 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HIDRAW_OUT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'M', 0x00, /* wcChar10 */
|
||||
'S', 0x00, /* wcChar11 */
|
||||
'C', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!< custom hid report descriptor */
|
||||
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||
/* USER CODE BEGIN 0 */
|
||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
/* <___________________________________________________> */
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
/* USER CODE END 0 */
|
||||
0xC0 /* END_COLLECTION */
|
||||
};
|
||||
|
||||
/*!< class */
|
||||
static usbd_class_t hid_class;
|
||||
|
||||
/*!< interface */
|
||||
static usbd_interface_t hid_intf_2;
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
uint8_t custom_state = HID_STATE_IDLE;
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
static void usbd_hid_custom_in_callback(uint8_t ep)
|
||||
{
|
||||
/*!< endpoint call back */
|
||||
/*!< transfer successfully */
|
||||
if (custom_state == HID_STATE_BUSY) {
|
||||
/*!< update the state */
|
||||
custom_state = HID_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_hid_custom_out_callback(uint8_t ep)
|
||||
{
|
||||
/*!< read the data from host send */
|
||||
uint8_t custom_data[HIDRAW_OUT_EP_SIZE];
|
||||
usbd_ep_read(HIDRAW_OUT_EP, custom_data, HIDRAW_OUT_EP_SIZE, NULL);
|
||||
|
||||
/*!< you can use the data do some thing you like */
|
||||
}
|
||||
|
||||
/*!< endpoint call back */
|
||||
static struct usbd_interface custom_in_ep = {
|
||||
.ep_cb = usbd_hid_custom_in_callback,
|
||||
.ep_addr = HIDRAW_IN_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface custom_out_ep = {
|
||||
.ep_cb = usbd_hid_custom_out_callback,
|
||||
.ep_addr = HIDRAW_OUT_EP
|
||||
};
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief msc ram init
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
void hid_msc_descriptor_init(void)
|
||||
{
|
||||
usbd_desc_register(hid_msc_descriptor);
|
||||
|
||||
usbd_msc_class_init(MSC_OUT_EP, MSC_IN_EP);
|
||||
/*!< add interface */
|
||||
/*!< add interface the ! second interface */
|
||||
usbd_hid_add_interface(&hid_class, &hid_intf_2);
|
||||
/*!< interface1 add endpoint ! the first endpoint */
|
||||
usbd_interface_add_endpoint(&hid_intf_2, &custom_in_ep);
|
||||
/*!< interface1 add endpoint ! the second endpoint */
|
||||
usbd_interface_add_endpoint(&hid_intf_2, &custom_out_ep);
|
||||
|
||||
/*!< register report descriptor interface 1 */
|
||||
usbd_hid_report_descriptor_register(1, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief device send report to host
|
||||
* @pre none
|
||||
* @param[in] ep endpoint address
|
||||
* @param[in] data points to the data buffer waiting to be sent
|
||||
* @param[in] len length of data to be sent
|
||||
* @retval none
|
||||
*/
|
||||
void hid_custom_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||
{
|
||||
if (usb_device_is_configured()) {
|
||||
if (custom_state == HID_STATE_IDLE) {
|
||||
/*!< updata the state */
|
||||
custom_state = HID_STATE_BUSY;
|
||||
/*!< write buffer */
|
||||
usbd_ep_write(ep, data, len, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief hid custom test
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
void hid_custom_test(void)
|
||||
{
|
||||
/*!< keyboard test */
|
||||
uint8_t sendbuffer1[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
|
||||
/*!< custom test */
|
||||
uint8_t sendbuffer2[64] = { 6 };
|
||||
hid_custom_send_report(HIDRAW_IN_EP, sendbuffer2, HIDRAW_IN_SIZE);
|
||||
//HAL_Delay(1000);
|
||||
}
|
||||
@@ -11,10 +11,16 @@
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t msc_ram_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -89,9 +95,29 @@ const uint8_t msc_ram_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
@@ -111,14 +137,14 @@ void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
if (sector < BLOCK_COUNT)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
if (sector < BLOCK_COUNT)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
167
demo/msc_storage_template.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
|
||||
#ifdef __RT_THREAD_H__
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
|
||||
const uint8_t msc_storage_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_1_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'M', 0x00, /* wcChar10 */
|
||||
'S', 0x00, /* wcChar11 */
|
||||
'C', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
/* assume the block device is 512M */
|
||||
#define BLOCK_DEV_NAME "sd0"
|
||||
#define BLOCK_SIZE 512U
|
||||
#define BLOCK_COUNT 0x1024U * 0x1024U
|
||||
static rt_device_t blk_dev = RT_NULL;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = BLOCK_COUNT;
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msc_storage_init(void)
|
||||
{
|
||||
rt_err_t res;
|
||||
|
||||
blk_dev = rt_device_find(BLOCK_DEV_NAME);
|
||||
RT_ASSERT(blk_dev);
|
||||
|
||||
res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
|
||||
RT_ASSERT(res == RT_EOK);
|
||||
|
||||
usbd_desc_register(msc_storage_descriptor);
|
||||
usbd_add_interface(usbd_msc_init_intf(&intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
#endif
|
||||
@@ -61,10 +61,16 @@ struct usb_msosv1_descriptor msosv1_desc = {
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + MTP_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MTP_MAX_MPS 512
|
||||
#else
|
||||
#define MTP_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t mtp_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0201, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MTP_DESCRIPTOR_INIT(0x00, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, 2),
|
||||
MTP_DESCRIPTOR_INIT(0x00, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, MTP_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -145,8 +151,29 @@ const uint8_t bos_descriptor[] = {
|
||||
0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
@@ -101,10 +101,31 @@ static const uint8_t printer_descriptor[] = {
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[PRINTER_OUT_EP_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[PRINTER_IN_EP_SIZE];
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_printer_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
193
demo/usb_host.c
@@ -11,6 +11,7 @@
|
||||
#define TEST_USBH_MSC_FATFS 0
|
||||
#define TEST_USBH_AUDIO 0
|
||||
#define TEST_USBH_VIDEO 0
|
||||
#define TEST_USBH_CDC_ECM 0
|
||||
|
||||
#if TEST_USBH_CDC_ACM
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
|
||||
@@ -254,6 +255,192 @@ find_class:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stream->bufoffset == 0) && ((iso_packet[i].transfer_buffer[header_len] != 0xff) || (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8))) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) || (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
/** do something here */
|
||||
}
|
||||
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback && (stream->bufoffset == stream->buflen)) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ECM
|
||||
#include "usbh_cdc_ecm.h"
|
||||
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#if LWIP_DHCP
|
||||
#include "lwip/dhcp.h"
|
||||
#endif
|
||||
|
||||
struct netif g_cdc_ecm_netif;
|
||||
|
||||
static err_t usbh_cdc_ecm_if_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
netif->state = NULL;
|
||||
netif->name[0] = 'E';
|
||||
netif->name[1] = 'X';
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = usbh_cdc_ecm_linkoutput;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, cdc_ecm_class->mac, 6);
|
||||
|
||||
IP4_ADDR(&cdc_ecm_class->ipaddr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&cdc_ecm_class->netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&cdc_ecm_class->gateway, 0, 0, 0, 0);
|
||||
|
||||
netif = netif_add(netif, &cdc_ecm_class->ipaddr, &cdc_ecm_class->netmask, &cdc_ecm_class->gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
#if LWIP_DHCP
|
||||
dhcp_stop(netif);
|
||||
dhcp_cleanup(netif);
|
||||
#endif
|
||||
netif_set_down(netif);
|
||||
netif_remove(netif);
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
}
|
||||
@@ -313,4 +500,10 @@ void usbh_class_test(void)
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_video", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_video_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_CDC_ECM
|
||||
/* Initialize the LwIP stack */
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
usbh_cdc_ecm_lwip_thread_init(&g_cdc_ecm_netif);
|
||||
#endif
|
||||
}
|
||||
@@ -141,9 +141,29 @@ const uint8_t video_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, so do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
|
||||
#define DOUBLE_WINUSB 0
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
@@ -16,6 +18,7 @@ __ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
#if DOUBLE_WINUSB == 0
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
@@ -37,61 +40,144 @@ __ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
#else
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[64] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
0x40, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x02, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
0x00, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x01, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
#endif
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties [142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
#define WINUSB_IF1_WCID_PROPERTIES_SIZE (142)
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF1_WCIDProperties [142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
WINUSB_IF1_WCIDProperties,
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
|
||||
.string_len = 18,
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
|
||||
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
|
||||
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
|
||||
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
#if DOUBLE_WINUSB == 0
|
||||
.comp_id_property = &WINUSB_IF0_WCIDProperties,
|
||||
#else
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0x0d28
|
||||
#define USBD_PID 0x0404
|
||||
#define USBD_VID 0xefff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#if DOUBLE_WINUSB == 0
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
|
||||
#define INTF_NUM 1
|
||||
#else
|
||||
#define WINUSB_IN_EP2 0x83
|
||||
#define WINUSB_OUT_EP2 0x04
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + 9 + 7 + 7)
|
||||
#define INTF_NUM 2
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define WINUSB_EP_MPS 512
|
||||
@@ -100,11 +186,16 @@ struct usb_msosv1_descriptor msosv1_desc = {
|
||||
#endif
|
||||
|
||||
const uint8_t winusb_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xff, 0xff, 0xff, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0x01, 0x00, 0x02),
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x04),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
#if DOUBLE_WINUSB == 1
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x01, 0x00, 0x02, 0xff, 0xff, 0x00, 0x05),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP2, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP2, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
#endif
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -164,6 +255,62 @@ const uint8_t winusb_descriptor[] = {
|
||||
'0', 0x00, /* wcChar7 */
|
||||
'0', 0x00, /* wcChar8 */
|
||||
'0', 0x00, /* wcChar9 */
|
||||
///////////////////////////////////////
|
||||
/// string4 descriptor
|
||||
///////////////////////////////////////
|
||||
0x30, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'W', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'N', 0x00, /* wcChar12 */
|
||||
'U', 0x00, /* wcChar13 */
|
||||
'S', 0x00, /* wcChar14 */
|
||||
'B', 0x00, /* wcChar15 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'D', 0x00, /* wcChar17 */
|
||||
'E', 0x00, /* wcChar18 */
|
||||
'M', 0x00, /* wcChar19 */
|
||||
'O', 0x00, /* wcChar20 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'1', 0x00, /* wcChar21 */
|
||||
///////////////////////////////////////
|
||||
/// string5 descriptor
|
||||
///////////////////////////////////////
|
||||
0x30, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'W', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'N', 0x00, /* wcChar12 */
|
||||
'U', 0x00, /* wcChar13 */
|
||||
'S', 0x00, /* wcChar14 */
|
||||
'B', 0x00, /* wcChar15 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'D', 0x00, /* wcChar17 */
|
||||
'E', 0x00, /* wcChar18 */
|
||||
'M', 0x00, /* wcChar19 */
|
||||
'O', 0x00, /* wcChar20 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'2', 0x00, /* wcChar21 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
@@ -187,10 +334,34 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
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:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
#if DOUBLE_WINUSB == 1
|
||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
||||
#endif
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
|
||||
@@ -200,41 +371,86 @@ void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
|
||||
// printf("%02x ", read_buffer[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
usbd_ep_start_write(WINUSB_IN_EP, read_buffer, nbytes);
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_winusb_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
||||
usbd_ep_start_write(WINUSB_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_endpoint winusb_out_ep = {
|
||||
struct usbd_endpoint winusb_out_ep1 = {
|
||||
.ep_addr = WINUSB_OUT_EP,
|
||||
.ep_cb = usbd_winusb_out
|
||||
};
|
||||
|
||||
struct usbd_endpoint winusb_in_ep = {
|
||||
struct usbd_endpoint winusb_in_ep1 = {
|
||||
.ep_addr = WINUSB_IN_EP,
|
||||
.ep_cb = usbd_winusb_in
|
||||
};
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
#if DOUBLE_WINUSB == 1
|
||||
|
||||
void usbd_winusb_out2(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");
|
||||
usbd_ep_start_write(WINUSB_IN_EP2, read_buffer, nbytes);
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_winusb_in2(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
|
||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(WINUSB_IN_EP2, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_endpoint winusb_out_ep2 = {
|
||||
.ep_addr = WINUSB_OUT_EP2,
|
||||
.ep_cb = usbd_winusb_out2
|
||||
};
|
||||
|
||||
struct usbd_endpoint winusb_in_ep2 = {
|
||||
.ep_addr = WINUSB_IN_EP2,
|
||||
.ep_cb = usbd_winusb_in2
|
||||
};
|
||||
|
||||
struct usbd_interface intf1;
|
||||
|
||||
#endif
|
||||
|
||||
void winusb_init(void)
|
||||
{
|
||||
usbd_desc_register(winusb_descriptor);
|
||||
usbd_msosv1_desc_register(&msosv1_desc);
|
||||
usbd_add_interface(&intf0);
|
||||
usbd_add_endpoint(&winusb_out_ep);
|
||||
usbd_add_endpoint(&winusb_in_ep);
|
||||
|
||||
usbd_add_endpoint(&winusb_out_ep1);
|
||||
usbd_add_endpoint(&winusb_in_ep1);
|
||||
#if DOUBLE_WINUSB == 1
|
||||
usbd_add_interface(&intf1);
|
||||
usbd_add_endpoint(&winusb_out_ep2);
|
||||
usbd_add_endpoint(&winusb_in_ep2);
|
||||
#endif
|
||||
usbd_initialize();
|
||||
}
|
||||
1
docs/assets/CherryUSB.svg
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,48 +0,0 @@
|
||||
其他
|
||||
=========================
|
||||
|
||||
usb_malloc
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_malloc`` 用来申请内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *usb_malloc(size_t size);
|
||||
|
||||
- **size** 要申请的内存大小
|
||||
- **return** 申请的内存地址
|
||||
|
||||
usb_free
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_free`` 用来释放申请的内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_free(void *ptr);
|
||||
|
||||
- **ptr** 要释放的内存地址
|
||||
|
||||
usb_iomalloc
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_iomalloc`` 用来申请内存,并按照 `CONFIG_DCACHE_LINE_SIZE` 对齐,一般使用到 dcache 和 dma 需要对齐操作的时候使用。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *usb_iomalloc(size_t size);
|
||||
|
||||
- **size** 要申请的内存大小
|
||||
- **return** 申请的内存地址
|
||||
|
||||
usb_iofree
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_iofree`` 用来释放申请的内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_iofree(void *ptr);
|
||||
|
||||
- **ptr** 要释放的内存地址
|
||||
@@ -4,8 +4,152 @@ USB CONFIG 宏
|
||||
通用 CONFIG 宏
|
||||
---------------------
|
||||
|
||||
CONFIG_USB_PRINTF
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
USB log 功能,默认重定向到 printf,需要注意,USB log 会在中断中使用,因此重定向的 api 不允许阻塞。举例,如果使用的是 rt-thread,请更换成 rt-kprintf
|
||||
|
||||
CONFIG_USB_DBG_LEVEL
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制 log 的打印级别
|
||||
|
||||
CONFIG_USB_PRINTF_COLOR_ENABLE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制 log 颜色打印,默认开启
|
||||
|
||||
CONFIG_USB_ALIGN_SIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
USB buffer 的对齐大小,默认是 4。IP 在 dma 模式下可能对输入的 buffer有对齐要求,一般是4,如果是其他对齐方式,请修改此值。
|
||||
|
||||
USB_NOCACHE_RAM_SECTION
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
如果芯片没有 cache 功能,此宏无效。如果有,则 USB 的输入输出 buffer 必须放在 nocache ram 中,保证数据一致性。
|
||||
|
||||
设备相关 CONFIG 宏
|
||||
---------------------
|
||||
|
||||
CONFIG_USBDEV_REQUEST_BUFFER_LEN
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制传输接收和发送的 buffer 最大长度,默认是 256。
|
||||
|
||||
CONFIG_USBDEV_SETUP_LOG_PRINT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
使能或者关闭 setup 包的 dump 信息,默认关闭。
|
||||
|
||||
CONFIG_USBDEV_DESC_CHECK
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
暂时没有实现
|
||||
|
||||
CONFIG_USBDEV_TEST_MODE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
使能或者关闭 usb test mode
|
||||
|
||||
CONFIG_USBDEV_MSC_BLOCK_SIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
msc 临时缓存的大小,缓存越大,msc 的速度越高,默认等于 1个内存介质的扇区大小(例如 sd卡 512,flash 4K),更改时需要是内存介质扇区的倍数。
|
||||
|
||||
虽然名字叫 block size,但是跟内存介质的 block size不是一个意思。
|
||||
|
||||
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CONFIG_USBDEV_MSC_PRODUCT_STRING
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CONFIG_USBDEV_MSC_VERSION_STRING
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CONFIG_USBDEV_MSC_THREAD
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
使能或者关闭 msc 线程,默认关闭。usbd_msc_sector_read 和 usbd_msc_sector_write 默认是在中断中执行,所以如果开启了 os 建议开启此宏,那么,
|
||||
usbd_msc_sector_read 和 usbd_msc_sector_write 就会在线程中执行。
|
||||
|
||||
CONFIG_USBDEV_MSC_PRIO
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
MSC 读写线程的优先级,默认是 4,数值越小,优先级越高
|
||||
|
||||
CONFIG_USBDEV_MSC_STACKSIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
MSC 读写线程的堆栈大小,默认 2K 字节
|
||||
|
||||
CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
rndis 控制传输最大接收和发送的长度,根据 RNDIS options list 决定最小长度,默认要大于等于 156
|
||||
|
||||
CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
rndis 以太网帧的最大长度,默认 1536
|
||||
|
||||
CONFIG_USBDEV_RNDIS_VENDOR_ID
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CONFIG_USBDEV_RNDIS_VENDOR_DESC
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
rndis 与 lwip 接口的对接
|
||||
|
||||
主机相关 CONFIG 宏
|
||||
---------------------
|
||||
|
||||
以下参数决定了支持的最大外部hub数量,接口数,每个接口的端点数和 altsetting 数量,更改此值会影响 ram 的大小,建议根据实际情况更改。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
以下参数决定了支持的 class 数目,更改此值会影响 ram 的大小,建议根据实际情况更改。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
CONFIG_USBHOST_PSC_PRIO
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
主机插拔线程的优先级,默认是 4,数值越小,优先级越高
|
||||
|
||||
CONFIG_USBHOST_PSC_STACKSIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
主机插拔线程的堆栈大小,默认 2K 字节
|
||||
|
||||
CONFIG_USBHOST_REQUEST_BUFFER_LEN
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制传输能够接收或者发送的最大长度
|
||||
|
||||
CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制传输发送或者接收的超时时间,默认 1s
|
||||
|
||||
CONFIG_USBHOST_MSC_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
MSC 读写传输的超时时间,默认 5s
|
||||
@@ -103,7 +103,7 @@ usbd_bos_desc_register
|
||||
usbd_add_interface
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_add_interface`` 添加一个接口驱动。
|
||||
``usbd_add_interface`` 添加一个接口驱动。 **添加顺序必须按照描述符顺序**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
@@ -122,37 +122,24 @@ usbd_add_endpoint
|
||||
|
||||
- **ep** 端点句柄
|
||||
|
||||
usb_device_is_configured
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_device_is_configured`` 用来检查 USB 设备是否被配置(枚举)。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
bool usb_device_is_configured(void);
|
||||
|
||||
- **return** 配置状态, 0 表示未配置, 1 表示配置成功
|
||||
|
||||
usbd_configure_done_callback
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_configure_done_callback`` 在执行 set_configuration 命令后触发,表示配置完成,用户需要实现该函数, **此函数一般用作启动第一次数据接收**,如果没有使用到 out 端点,则函数为空即可。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
bool usbd_configure_done_callback(void);
|
||||
|
||||
.. warning:: msc 端点不需要在该函数中手动启动,协议栈会自动启动第一次接收
|
||||
|
||||
usbd_initialize
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。
|
||||
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。 **如果使用 os,必须放在线程中执行**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbd_initialize(void);
|
||||
|
||||
usbd_event_handler
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_event_handler`` 是协议栈中中断或者协议栈一些状态的回调函数。大部分 IP 仅支持 USBD_EVENT_RESET 和 USBD_EVENT_CONFIGURED
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_event_handler(uint8_t event);
|
||||
|
||||
CDC ACM
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -82,11 +82,13 @@ hubport 结构体
|
||||
const char *iManufacturer;
|
||||
const char *iProduct;
|
||||
const char *iSerialNumber;
|
||||
#if 0
|
||||
uint8_t* raw_config_desc;
|
||||
#endif
|
||||
USB_MEM_ALIGNX struct usb_setup_packet setup;
|
||||
uint8_t *raw_config_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usbh_hub *parent;
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
usb_osal_thread_t thread;
|
||||
};
|
||||
|
||||
hub 结构体
|
||||
@@ -101,12 +103,11 @@ hub 结构体
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
USB_MEM_ALIGNX uint8_t int_buffer[1];
|
||||
uint8_t *int_buffer;
|
||||
struct usbh_urb intin_urb;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
usb_slist_t hub_event_list;
|
||||
};
|
||||
|
||||
usbh_initialize
|
||||
|
||||
@@ -153,19 +153,19 @@ usbh_roothub_control
|
||||
- **buf** 接收缓冲区
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_ep0_pipe_reconfigure
|
||||
usbh_ep_pipe_reconfigure
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_ep0_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。
|
||||
``usbh_ep_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
- **pipe** pipe 句柄
|
||||
- **dev_addr** 端点所在设备地址
|
||||
- **ep_mps** 端点最大包长
|
||||
- **speed** 端点所在设备的速度
|
||||
- **mult** 端点一次传输个数
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_pipe_alloc
|
||||
|
||||
@@ -6,8 +6,8 @@ project = 'CherryUSB'
|
||||
copyright = '2022, sakumisu'
|
||||
author = 'sakumisu'
|
||||
|
||||
release = '0.9'
|
||||
version = '0.9.0'
|
||||
release = '0.10.0'
|
||||
version = '0.10.0'
|
||||
|
||||
# -- General configuration
|
||||
|
||||
|
||||
@@ -8,23 +8,41 @@ CherryUSB 使用指南
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的 USB 主从协议栈。同时 CherryUSB 具有以下优点:
|
||||
|
||||
- 代码精简,并且内存占用极小,而且还可进一步的裁剪
|
||||
- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律
|
||||
- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类
|
||||
- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程
|
||||
- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。
|
||||
- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制
|
||||
- 能够达到 USB 硬件理论带宽
|
||||
**易于学习 USB**
|
||||
|
||||
从机协议栈整体执行流程:
|
||||
为了方便用户学习 USB 基本知识、枚举、驱动加载、IP 驱动,因此,编写的代码具备以下优点:
|
||||
|
||||
- 代码精简,逻辑简单,无复杂 C 语言语法
|
||||
- 树状化编程,代码层层递进
|
||||
- Class 驱动和 porting 驱动模板化、精简化
|
||||
- API 分类清晰(从机:初始化、注册类、命令回调类、数据收发类;主机:初始化、查找类、数据收发类)
|
||||
|
||||
**易于使用 USB**
|
||||
|
||||
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma,因此,设计的数据收发类接口具备以下优点:
|
||||
|
||||
- 等价于使用 uart tx dma/uart rx dma
|
||||
- 收发长度没有限制,用户不需要关心 USB 分包过程(porting 驱动做分包过程)
|
||||
|
||||
**易于发挥 USB 性能**
|
||||
|
||||
考虑到 USB 性能问题,尽量达到 USB 硬件理论带宽,因此,设计的数据收发类接口具备以下优点:
|
||||
|
||||
- Porting 驱动直接对接寄存器,无抽象层封装
|
||||
- Memory zero copy
|
||||
- IP 如果带 DMA 则使用 DMA 模式(DMA 带硬件分包功能)
|
||||
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
|
||||
- 分包功能在中断中处理
|
||||
|
||||
**从机协议栈整体执行流程**
|
||||
|
||||
.. figure:: usbdev.svg
|
||||
|
||||
主机协议栈整体执行流程:
|
||||
**主机协议栈整体执行流程**
|
||||
|
||||
.. figure:: usbhost.svg
|
||||
|
||||
其他相关链接:
|
||||
**其他相关链接**
|
||||
|
||||
- **CherryUSB 大纲** https://www.bilibili.com/video/BV1st4y1H7K2
|
||||
- **从机协议栈视频教程** https://www.bilibili.com/video/BV1Ef4y1t73d
|
||||
@@ -35,10 +53,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
|
||||
:maxdepth: 1
|
||||
:caption: 快速上手
|
||||
|
||||
quick_start/bl702
|
||||
quick_start/stm32
|
||||
quick_start/hpm
|
||||
quick_start/es32
|
||||
quick_start/index
|
||||
quick_start/rt-thread/rtthread
|
||||
quick_start/other_chip
|
||||
|
||||
@@ -59,7 +74,6 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
|
||||
api/api_device
|
||||
api/api_host
|
||||
api/api_port
|
||||
api/api_common
|
||||
api/api_config
|
||||
|
||||
.. toctree::
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
基于 BL 系列开发指南
|
||||
=========================
|
||||
|
||||
BL 系列 USB 的开发主要使用 bl_mcu_sdk,参考 `bl_mcu_sdk <https://github.com/bouffalolab/bl_mcu_sdk>`_。
|
||||
|
||||
USB 的相关应用位于 `examples/usbdev` 和 `examples/usbhost` 目录下,环境搭建完成后,即可编译使用。
|
||||
@@ -1,84 +0,0 @@
|
||||
基于 ES32F369 开发指南
|
||||
=========================
|
||||
|
||||
ES32F3xx 系列单片机中 USB 外设使用标准的 musb ip,并且拥有 usb device 和 usb host 功能。本章主要介绍如何在东软载波的 ES32F369x 开发板中使用 CherryUSB。
|
||||
|
||||
在使用之前需要从 essemi 官网下载 `keil 芯片支持包 <http://www.essemi.com/index/product/detail?id=796>`_ 并安装,
|
||||
|
||||
|
||||
工程样例试用
|
||||
-----------------------
|
||||
|
||||
在 CherryUSB demo 目录下已经有主机跟从机的样例,在有板子的情况下,可以先跑工程样例,试用一下。
|
||||
|
||||
- 进入 MDK-ARM 目录下,双击 `example.uvprojx` 打开工程,选择好调试器后,编译烧录即可。
|
||||
- 如果是从机,默认提供的是 cdc acm 的示例,代码烧录以后,将 usb 线插到 板子的丝印为 USB-OTG 口,并接上电脑,按下复位键,电脑便会枚举出一个串口。打开串口,勾选 DTR 可以接收数据,在发送缓冲区填入数据并发送,调试器的串口便可以打印出接收的长度和数据。
|
||||
- 如果是主机,则需要一个 usb 母口转接线,并接入相关 usb 设备,就可以进行测试了。比如接上鼠标、U盘、4G 网卡等等。
|
||||
|
||||
USB Device 移植要点
|
||||
-----------------------
|
||||
|
||||
针对自定义的工程移植,需要按照以下步骤:
|
||||
|
||||
- 准备好可以进行调试打印的工程,并且实现 `printf`、 `malloc` 、 `free` 函数(也可以直接勾选 Use microlib 来使用)。
|
||||
- 拷贝 CherryUSB 源码到工程里
|
||||
- 添加 CherryUSB 源码和头文件路径,其中 `usbd_core.c` 和 `usb_dc_musb.c` 为必须添加项。
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径。所以根目录下的文件仅作为参考,不要添加根目录下的头文件。
|
||||
|
||||
.. figure:: img/es322.png
|
||||
.. figure:: img/es323.png
|
||||
|
||||
- 实现 `usb_dc_low_level_init` 函数,该函数主要负责 USB 时钟、引脚、中断的初始化。例如
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_dc_low_level_init(void)
|
||||
{
|
||||
ald_pmu_perh_power_config(PMU_POWER_USB, ENABLE);
|
||||
ald_cmu_perh_clock_config(CMU_PERH_USB, ENABLE);
|
||||
ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE);
|
||||
ald_cmu_usb_clock_config(CMU_USB_CLOCK_SEL_HOSC, CMU_USB_DIV_1);
|
||||
ald_rmu_reset_periperal(RMU_PERH_USB);
|
||||
ald_mcu_irq_config(USB_INT_IRQn, 2, 2, ENABLE);
|
||||
ald_mcu_irq_config(USB_DMA_IRQn, 2, 2, ENABLE);
|
||||
usb_pin_init();
|
||||
}
|
||||
|
||||
- 描述符的注册、class的注册、接口的注册、端点中断的注册。不会的参考 demo 下的 template 。
|
||||
- 调用 `usbd_initialize` 初始化 usb 硬件。
|
||||
- 正常使用。
|
||||
|
||||
|
||||
USB Host 移植要点
|
||||
-----------------------
|
||||
|
||||
针对自定义的工程移植,需要以下步骤:
|
||||
|
||||
- 准备好可以进行调试打印的带 FreeRTOS 或者 RT-Thread 的工程,并且实现 `printf`、 `malloc` 、 `free` 函数(也可以直接勾选 Use microlib 来使用)。
|
||||
- 拷贝 CherryUSB 源码到工程里
|
||||
- 添加 CherryUSB 源码和头文件路径,其中 `usbh_core.c` 和 `usb_hc_musb.c` 、 osal 下的文件为必须添加项,根据不同的 os 添加对应的文件。
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h` ,并添加相应的目录头文件路径。所以根目录下的文件仅作为参考,不要添加根目录下的头文件。
|
||||
|
||||
.. figure:: img/es324.png
|
||||
.. figure:: img/es325.png
|
||||
|
||||
- 由于是作为主机,推荐添加所有的 class,功能全面。当然如果只用一个 class ,就添加一个。
|
||||
- 实现 `usb_hc_low_level_init` 函数,该函数主要负责 USB 时钟、引脚、中断的初始化。例如
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_hc_low_level_init(void)
|
||||
{
|
||||
ald_pmu_perh_power_config(PMU_POWER_USB, ENABLE);
|
||||
ald_cmu_perh_clock_config(CMU_PERH_USB, ENABLE);
|
||||
ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE);
|
||||
ald_cmu_usb_clock_config(CMU_USB_CLOCK_SEL_HOSC, CMU_USB_DIV_1);
|
||||
ald_rmu_reset_periperal(RMU_PERH_USB);
|
||||
ald_mcu_irq_config(USB_INT_IRQn, 2, 2, ENABLE);
|
||||
ald_mcu_irq_config(USB_DMA_IRQn, 2, 2, ENABLE);
|
||||
usb_pin_init();
|
||||
}
|
||||
|
||||
- 调用 `usbh_initialize` 初始化 usb 硬件。
|
||||
- 此时编译会报错,因为协议栈中为每个 class 都添加了测试 demo,文件在 `usb_host.c` 中,如果不想要,可以直接删除。
|
||||
- 正常使用。
|
||||
@@ -1,6 +0,0 @@
|
||||
基于 HPM 系列开发指南
|
||||
=========================
|
||||
|
||||
HPM 系列 USB 的开发主要使用 hpm_sdk ,参考 `hpm sdk <https://github.com/hpmicro/hpm_sdk>`_。
|
||||
|
||||
USB 的相关应用位于 `samples/cherryusb` 目录下,环境搭建完成后,即可编译使用。
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
BIN
docs/source/quick_start/img/keil.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
@@ -1,13 +1,41 @@
|
||||
基于 STM32F1/F4/H7 开发指南
|
||||
=============================
|
||||
基于现有 demo 快速验证
|
||||
=========================
|
||||
|
||||
本节是基于 STM32 三个系列芯片的使用,涵盖 F1/F4/H7,其余芯片基本类似,不再赘述,具体区别有:
|
||||
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
|
||||
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
|
||||
|
||||
|
||||
基于 bouffalolab 系列芯片
|
||||
---------------------------
|
||||
|
||||
仓库参考:https://github.com/CherryUSB/cherryusb_bouffalolab
|
||||
|
||||
- BL702 是一个 USB2.0 全速芯片,共 8 个端点(包含端点0)。仅支持从机。
|
||||
- BL616/BL808 是一个 USB2.0 并且内置高速 PHY 芯片,共 5个端点(包含端点0)。支持主从机。
|
||||
- USB 的相关应用位于 `examples/usbdev` 和 `examples/usbhost` 目录下,根据官方环境搭建完成后,即可编译使用。
|
||||
|
||||
|
||||
基于 ST 系列芯片
|
||||
---------------------------
|
||||
|
||||
仓库参考:https://github.com/CherryUSB/cherryusb_stm32
|
||||
|
||||
默认提供以下 demo 工程:
|
||||
|
||||
- F103 使用 fsdev ip
|
||||
- F429 主从使用 hs port,并且均用 dma 模式
|
||||
- H7 设备使用 fs port,主机使用 hs port,并且主机带 cache 支持
|
||||
|
||||
默认删除 Drivers ,所以需要使用 stm32cubemx 生成一下 Drivers 目录下的文件,demo 底下提供了 **stm32xxx.ioc** 文件,双击打开,点击 **Generate Code** 即可。
|
||||
|
||||
.. caution:: 生成完以后,请使用 git reset 功能将被覆盖的 `main.c` 和 `stm32xxx_it.c` 文件撤回,禁止被 cubemx 覆盖。
|
||||
|
||||
涵盖 F1/F4/H7,其余芯片基本类似,不再赘述,具体区别有:
|
||||
|
||||
- usb ip 区别:F1使用 fsdev,F4/H7使用 dwc2
|
||||
- dwc2 ip 区别: fs port(引脚是 PA11/PA12) 和 hs port(引脚是 PB14/PB15), 其中 hs port 默认全速,可以接外部PHY 形成高速主机,并且带 dma 功能
|
||||
- F4 与 H7 cache 区别、USB BASE 区别
|
||||
|
||||
|
||||
如果是 STM32F7/STM32H7 这种带 cache 功能,需要将 usb 使用到的 ram 定位到 no cache ram 区域。举例如下
|
||||
|
||||
.. code-block:: C
|
||||
@@ -36,22 +64,10 @@
|
||||
|
||||
.. caution :: 如果使用 STM32F7 或者 STM32H7, 请在 CFLAG 中添加 STM32F7 或者 STM32H7 宏定义,否则无法枚举
|
||||
|
||||
工程样例试用
|
||||
-----------------------
|
||||
|
||||
默认提供以下 demo 工程:
|
||||
|
||||
- F103 使用 fsdev ip
|
||||
- F429 主从使用 hs port,并且均用 dma 模式
|
||||
- H7 设备使用 fs port,主机使用 hs port,并且主机带 cache 支持
|
||||
|
||||
|
||||
默认删除 Drivers ,所以需要使用 stm32cubemx 生成一下 Drivers 目录下的文件,demo 底下提供了 **stm32xxx.ioc** 文件,双击打开,点击 **Generate Code** 即可。
|
||||
|
||||
.. caution:: 生成完以后,请使用 git reset 功能将被覆盖的 `main.c` 和 `stm32xxx_it.c` 文件撤回,禁止被 cubemx 覆盖。
|
||||
.. figure:: img/keil.png
|
||||
|
||||
USB Device 移植要点
|
||||
-----------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- 使用 **stm32cubemx** 创建工程,配置基本的 RCC、UART (作为log使用)
|
||||
|
||||
@@ -104,7 +120,7 @@ USB Device 移植要点
|
||||
.. figure:: img/stm32_15.png
|
||||
|
||||
USB Host 移植要点
|
||||
-----------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
前面 7 步与 Device 一样。需要注意,host 驱动只支持带 dma 的 hs port (引脚是 PB14/PB15),所以 fs port (引脚是 PA11/PA12)不做支持(没有 dma 你玩什么主机)。
|
||||
|
||||
@@ -129,4 +145,12 @@ USB Host 移植要点
|
||||
|
||||
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
|
||||
|
||||
.. figure:: img/stm32_21.png
|
||||
.. figure:: img/stm32_21.png
|
||||
|
||||
基于 HPMicro 系列芯片
|
||||
---------------------------
|
||||
|
||||
仓库参考:https://github.com/CherryUSB/cherryusb_hpmicro
|
||||
|
||||
- HPM 系列芯片均 USB 2.0 并且内置高速 PHY,支持主从机
|
||||
- USB 的相关应用位于 `samples/cherryusb` ,根据官方环境搭建完成后,即可编译使用。
|
||||
@@ -9,13 +9,19 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
|
||||
|
||||
typedef void *usb_osal_thread_t;
|
||||
typedef void *usb_osal_sem_t;
|
||||
typedef void *usb_osal_mutex_t;
|
||||
typedef void *usb_osal_mq_t;
|
||||
typedef void (*usb_thread_entry_t)(void *argument);
|
||||
|
||||
/*
|
||||
* Task with smaller priority value indicates higher task priority
|
||||
*/
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread);
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem);
|
||||
|
||||