Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7df43ba6a2 | ||
|
|
e58a78c070 | ||
|
|
1492b8cca9 | ||
|
|
67a3bbe02e | ||
|
|
65b2de960b | ||
|
|
019c9cff6e | ||
|
|
2662a3497d | ||
|
|
7f7add7cec | ||
|
|
fa2900d4cd | ||
|
|
d30d08ca3a | ||
|
|
02685793aa | ||
|
|
8cd31e6be0 | ||
|
|
56c2b34131 | ||
|
|
f68a86ea89 | ||
|
|
8a831cdaa5 | ||
|
|
44e9c1cf4f | ||
|
|
e201439722 | ||
|
|
01f9025b6b | ||
|
|
bb709437aa | ||
|
|
7b936db889 | ||
|
|
6db1ef3a40 | ||
|
|
8f991699cb | ||
|
|
29d45ef5c7 | ||
|
|
a1ed27523c | ||
|
|
ce2a438c99 | ||
|
|
297852ce16 | ||
|
|
b1e95f0ca3 | ||
|
|
14f1f597f1 | ||
|
|
48730e20be | ||
|
|
11e389f922 | ||
|
|
82cd79989c | ||
|
|
fe18d36fe0 | ||
|
|
d414fd21d8 | ||
|
|
c8a11be013 | ||
|
|
fb6a463cc1 | ||
|
|
7e3795c191 | ||
|
|
22d60b4300 | ||
|
|
85e73197f9 | ||
|
|
c90f273e24 | ||
|
|
b14976dd56 | ||
|
|
9cd88c0ca3 | ||
|
|
3440e0cc1d | ||
|
|
849ea98853 | ||
|
|
b5f0c043e7 | ||
|
|
84299ce80b | ||
|
|
8e0c5b4e7e | ||
|
|
8ae4453ca4 | ||
|
|
86c7e435a3 | ||
|
|
074f30a7b4 | ||
|
|
50e1cd3471 | ||
|
|
b7d02b7125 | ||
|
|
5b32482c3e | ||
|
|
18eed18413 | ||
|
|
98c6ac25ec | ||
|
|
af1484882d | ||
|
|
e3c9fdbb86 | ||
|
|
03db11f4af | ||
|
|
d6bd89f274 | ||
|
|
9ea2121c7c | ||
|
|
bbcb433564 | ||
|
|
7989708bfe | ||
|
|
07fa211f40 | ||
|
|
73eb69bfa2 | ||
|
|
a08097c90e | ||
|
|
5bbe2a97f2 | ||
|
|
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
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()
|
||||
84
README.md
84
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
|
||||
|
||||
@@ -70,7 +70,7 @@ CherryUSB Device Stack has the following functions:
|
||||
- Support USB2.0 full and high speed, USB3.0 super speed
|
||||
- Support endpoint irq callback register by users, let users do whatever they wants in endpoint irq callback.
|
||||
- Support Composite Device
|
||||
- Support Communication Device Class (CDC)
|
||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB VIDEO CLASS (UVC1.0、UVC1.5)
|
||||
@@ -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
|
||||
|
||||
@@ -102,38 +103,51 @@ CherryUSB Host Stack has the following functions:
|
||||
- Support blocking transfers and asynchronous transfers
|
||||
- Support Composite Device
|
||||
- Multi-level HUB support, expandable up to 7 levels
|
||||
- Support Communication Device Class (CDC)
|
||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support Vendor class
|
||||
- Support USB modeswitch
|
||||
|
||||
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
|
||||
|
||||
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 |
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
|
||||
```
|
||||
#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_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#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
|
||||
```
|
||||
|
||||
## 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,19 @@ 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|
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|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 |
|
||||
|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 |
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
84
README_zh.md
84
README_zh.md
@@ -4,7 +4,7 @@
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
||||
|
||||

|
||||

|
||||
|
||||
## 为什么选择
|
||||
|
||||
@@ -68,7 +68,7 @@ CherryUSB Device 协议栈当前实现以下功能:
|
||||
- 支持 USB2.0 全速和高速设备,USB3.0 超速设备
|
||||
- 支持端点中断注册功能,porting 给用户自己处理中断里的数据
|
||||
- 支持复合设备
|
||||
- 支持 Communication Device Class (CDC)
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- 支持 Human Interface Device (HID)
|
||||
- 支持 Mass Storage Class (MSC)
|
||||
- 支持 USB VIDEO CLASS (UVC1.0、UVC1.5)
|
||||
@@ -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 协议栈简介
|
||||
|
||||
@@ -100,38 +101,51 @@ CherryUSB Host 协议栈当前实现以下功能:
|
||||
- 支持阻塞式传输和异步传输
|
||||
- 支持复合设备
|
||||
- 支持多级 HUB,最高可拓展到 7 级
|
||||
- 支持 Communication Device Class (CDC)
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- 支持 Human Interface Device (HID)
|
||||
- 支持 Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 USB modeswitch
|
||||
|
||||
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||
|
||||
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 |
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|
||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||
|
||||
```
|
||||
#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_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#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
|
||||
```
|
||||
|
||||
## 文档教程
|
||||
|
||||
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
|
||||
@@ -146,23 +160,19 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
|
||||
|
||||
## 示例仓库
|
||||
|
||||
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|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 |
|
||||
|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 |
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
40
SConscript
40
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']):
|
||||
@@ -58,14 +62,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_FS']):
|
||||
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=FS_PORT']
|
||||
elif GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_HS']):
|
||||
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=HS_PORT']
|
||||
if GetDepend(['SOC_SERIES_STM32F7']):
|
||||
CPPDEFINES += ['STM32F7']
|
||||
elif GetDepend(['SOC_SERIES_STM32H7']):
|
||||
CPPDEFINES += ['STM32H7']
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_STM32']):
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
@@ -81,6 +79,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,9 +101,13 @@ 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')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
|
||||
src += Glob('class/cdc/usbh_cdc_ecm.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_STM32']):
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
@@ -111,8 +119,24 @@ 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('RT_USING_DFS'):
|
||||
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
|
||||
|
||||
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
|
||||
|
||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
|
||||
5
VERSION
Normal file
5
VERSION
Normal file
@@ -0,0 +1,5 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
PATCHLEVEL = 99
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
@@ -6,7 +6,8 @@
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x000900
|
||||
#define CHERRYUSB_VERSION 0x010000
|
||||
#define CHERRYUSB_VERSION_STR "v1.0.0"
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
@@ -44,27 +45,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 +61,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
|
||||
@@ -112,14 +94,20 @@
|
||||
#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_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_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
|
||||
#define CONFIG_USBHOST_PSC_PRIO 4
|
||||
#define CONFIG_USBHOST_PSC_PRIO 0
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
|
||||
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
|
||||
@@ -127,6 +115,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
|
||||
|
||||
@@ -140,13 +131,15 @@
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
//#define USBD_IRQHandler USBD_IRQHandler
|
||||
//#define USB_BASE (0x40080000UL)
|
||||
//#define USB_NUM_BIDIR_ENDPOINTS 4
|
||||
#define USBD_IRQHandler USBD_IRQHandler
|
||||
#define USBD_BASE (0)
|
||||
#define CONFIG_USBDEV_EP_NUM 4
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
|
||||
#define CONFIG_USBHOST_PIPE_NUM 10
|
||||
// #define USBH_IRQHandler USBH_IRQHandler
|
||||
// #define USBH_BASE (0)
|
||||
// #define CONFIG_USBHOST_PIPE_NUM 10
|
||||
|
||||
/* ================ EHCI Configuration ================ */
|
||||
|
||||
@@ -154,7 +147,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)
|
||||
@@ -57,7 +62,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
|
||||
uint8_t altsetting = 1;
|
||||
|
||||
if (audio_class->is_opened) {
|
||||
return -EMFILE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->module_num; i++) {
|
||||
@@ -74,7 +79,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
|
||||
freq_found:
|
||||
|
||||
@@ -84,7 +89,7 @@ freq_found:
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -98,7 +103,7 @@ freq_found:
|
||||
setup->wLength = 3;
|
||||
|
||||
memcpy(g_audio_buf, &samp_freq, 3);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -107,10 +112,10 @@ freq_found:
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
audio_class->isoin_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&audio_class->isoin, audio_class->hport, ep_desc);
|
||||
USBH_EP_INIT(audio_class->isoin, ep_desc);
|
||||
} else {
|
||||
audio_class->isoout_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&audio_class->isoout, audio_class->hport, ep_desc);
|
||||
USBH_EP_INIT(audio_class->isoout, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
|
||||
@@ -133,7 +138,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Close audio module :%s\r\n", name);
|
||||
@@ -142,12 +147,10 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
if (audio_class->isoin) {
|
||||
usbh_pipe_free(audio_class->isoin);
|
||||
audio_class->isoin = NULL;
|
||||
}
|
||||
} else {
|
||||
if (audio_class->isoout) {
|
||||
usbh_pipe_free(audio_class->isoout);
|
||||
audio_class->isoout = NULL;
|
||||
}
|
||||
}
|
||||
@@ -158,7 +161,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -179,7 +182,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -191,7 +194,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
|
||||
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
|
||||
|
||||
memcpy(g_audio_buf, &volume_hex, 2);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -211,7 +214,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -221,7 +224,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
|
||||
setup->wLength = 1;
|
||||
|
||||
memcpy(g_audio_buf, &mute, 1);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -269,14 +272,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;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -383,7 +384,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
|
||||
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
audio_class->module_num = input_offset;
|
||||
@@ -412,14 +413,10 @@ 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);
|
||||
}
|
||||
|
||||
if (audio_class->isoout) {
|
||||
usbh_pipe_free(audio_class->isoout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
@@ -427,8 +424,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;
|
||||
|
||||
@@ -40,11 +40,11 @@ struct usbh_audio_module {
|
||||
|
||||
struct usbh_audio {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t isoin; /* ISO IN endpoint */
|
||||
usbh_pipe_t isoout; /* ISO OUT endpoint */
|
||||
uint16_t isoin_mps;
|
||||
uint16_t isoout_mps;
|
||||
bool is_opened;
|
||||
|
||||
@@ -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
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
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
|
||||
|
||||
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
|
||||
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
|
||||
volatile uint32_t g_cdc_ecm_tx_data_length = 0;
|
||||
|
||||
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 -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
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
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)
|
||||
@@ -48,7 +50,7 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
|
||||
memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
@@ -62,7 +64,7 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
setup->wIndex = cdc_acm_class->ctrl_intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -83,7 +85,7 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
|
||||
cdc_acm_class->dtr = dtr;
|
||||
cdc_acm_class->rts = rts;
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@@ -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;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -124,15 +124,15 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&cdc_acm_class->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
|
||||
#endif
|
||||
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_acm_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_acm_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,28 +151,57 @@ 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);
|
||||
usbh_kill_urb(&cdc_acm_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (cdc_acm_class->bulkout) {
|
||||
usbh_pipe_free(cdc_acm_class->bulkout);
|
||||
usbh_kill_urb(&cdc_acm_class->bulkout_urb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
if (cdc_acm_class->intin) {
|
||||
usbh_kill_urb(&cdc_acm_class->intin_urb);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
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;
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_acm_class->bulkout_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
struct usbh_cdc_acm {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb intin_urb;
|
||||
|
||||
struct cdc_line_coding linecoding;
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
@@ -17,11 +23,6 @@ struct usbh_cdc_acm {
|
||||
bool dtr;
|
||||
bool rts;
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -32,6 +33,9 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
|
||||
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
|
||||
|
||||
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class);
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class);
|
||||
|
||||
|
||||
334
class/cdc/usbh_cdc_ecm.c
Normal file
334
class/cdc/usbh_cdc_ecm.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static 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, 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->hport, 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) {
|
||||
if (g_cdc_ecm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
|
||||
cdc_ecm_class->connect_status = true;
|
||||
} else {
|
||||
cdc_ecm_class->connect_status = false;
|
||||
}
|
||||
} 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;
|
||||
|
||||
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
|
||||
|
||||
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, 12);
|
||||
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_EP_INIT(cdc_ecm_class->intin, 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_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkout, 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_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkout, 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_kill_urb(&cdc_ecm_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->bulkout) {
|
||||
usbh_kill_urb(&cdc_ecm_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->intin) {
|
||||
usbh_kill_urb(&cdc_ecm_class->intin_urb);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
g_cdc_ecm_class.connect_status = false;
|
||||
if (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_cdc_ecm_class.connect_status == false) {
|
||||
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), 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 % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
|
||||
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 {
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete cdc ecm rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
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 == false) {
|
||||
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.hport, 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;
|
||||
}
|
||||
|
||||
__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
|
||||
};
|
||||
51
class/cdc/usbh_cdc_ecm.h
Normal file
51
class/cdc/usbh_cdc_ecm.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
|
||||
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
|
||||
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
|
||||
uint8_t mac[6];
|
||||
bool connect_status;
|
||||
uint16_t max_segment_size;
|
||||
uint32_t speed[2];
|
||||
|
||||
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_rx_thread(void *argument);
|
||||
|
||||
#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)
|
||||
@@ -48,7 +49,7 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 128;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -66,7 +67,7 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hid_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
@@ -80,7 +81,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -98,7 +99,7 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hid_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@@ -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;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usbh_hid_devno_alloc(hid_class);
|
||||
hid_class->hport = hport;
|
||||
hid_class->intf = intf;
|
||||
|
||||
@@ -138,9 +137,9 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&hid_class->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(hid_class->intin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&hid_class->intout, hport, ep_desc);
|
||||
USBH_EP_INIT(hid_class->intout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,14 +158,12 @@ 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);
|
||||
usbh_kill_urb(&hid_class->intin_urb);
|
||||
}
|
||||
|
||||
if (hid_class->intout) {
|
||||
usbh_pipe_free(hid_class->intout);
|
||||
usbh_kill_urb(&hid_class->intout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
@@ -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;
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
|
||||
struct usbh_hid {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||
|
||||
uint8_t report_desc[128];
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t intin; /* INTR IN endpoint */
|
||||
usbh_pipe_t intout; /* INTR OUT endpoint */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -3,20 +3,17 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/hub%d"
|
||||
#define DEV_FORMAT "/dev/hub%d"
|
||||
|
||||
#define HUB_DEBOUNCE_TIMEOUT 1500
|
||||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 100
|
||||
#define DELAY_TIME_AFTER_RESET 200
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static uint32_t g_devinuse = 0;
|
||||
#endif
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
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,13 +25,8 @@ 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_free_devaddr(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
|
||||
|
||||
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
@@ -46,26 +38,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
|
||||
|
||||
@@ -102,14 +100,14 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
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;
|
||||
@@ -123,7 +121,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -131,6 +129,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)
|
||||
{
|
||||
@@ -145,7 +144,7 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 4;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -165,7 +164,7 @@ static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t fea
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
@@ -180,7 +179,7 @@ static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t f
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
@@ -195,7 +194,7 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
@@ -240,7 +239,7 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -258,7 +257,7 @@ static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feat
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -294,6 +293,27 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
|
||||
}
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_free_devaddr(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_kill_urb(&child->ep0_urb);
|
||||
usb_osal_mutex_delete(child->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
@@ -309,21 +329,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);
|
||||
return -ENOMEM;
|
||||
struct usbh_hub *hub = usbh_hub_class_alloc();
|
||||
if (hub == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hub_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -341,7 +355,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&hub->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(hub->intin, ep_desc);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -381,7 +395,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
hub->int_buffer = g_hub_intbuf[hub->index - 1];
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
return 0;
|
||||
}
|
||||
@@ -394,47 +408,37 @@ 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);
|
||||
usbh_kill_urb(&hub->intin_urb);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
child = &hub->child[port];
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_hubport_release(child);
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
static void usbh_hubport_enumerate_thread(void *argument)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
struct usbh_hubport *child = (struct usbh_hubport *)argument;
|
||||
|
||||
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)
|
||||
@@ -453,9 +457,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)))) {
|
||||
@@ -594,17 +599,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
child->connected = true;
|
||||
child->port = port + 1;
|
||||
child->speed = speed;
|
||||
child->mutex = usb_osal_mutex_create();
|
||||
|
||||
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 */
|
||||
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 +624,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 +637,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;
|
||||
}
|
||||
@@ -648,6 +647,8 @@ static void usbh_hub_thread(void *argument)
|
||||
|
||||
static void usbh_roothub_register(void)
|
||||
{
|
||||
usb_slist_init(&hub_class_head);
|
||||
|
||||
memset(&roothub, 0, sizeof(struct usbh_hub));
|
||||
|
||||
roothub.connected = true;
|
||||
@@ -659,11 +660,6 @@ static void usbh_roothub_register(void)
|
||||
usbh_hub_register(&roothub);
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
|
||||
}
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint8_t port)
|
||||
{
|
||||
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
|
||||
@@ -686,6 +682,36 @@ int usbh_hub_initialize(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hub_deinitialize(void)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
struct usbh_hubport *hport;
|
||||
size_t flags;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
usb_slist_for_each(i, &hub_class_head)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
|
||||
usbh_hubport_release(hport);
|
||||
}
|
||||
}
|
||||
|
||||
usb_hc_deinit();
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
usb_osal_mq_delete(hub_mq);
|
||||
usb_osal_thread_delete(hub_thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
const struct usbh_class_driver hub_class_driver = {
|
||||
.driver_name = "hub",
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#ifndef USBH_HUB_H
|
||||
#define USBH_HUB_H
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_hub.h"
|
||||
|
||||
#define USBH_HUB_MAX_PORTS 4
|
||||
@@ -14,12 +13,20 @@
|
||||
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
||||
|
||||
extern usb_slist_t hub_class_head;
|
||||
extern struct usbh_hub roothub;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint8_t port);
|
||||
|
||||
int usbh_hub_initialize(void);
|
||||
int usbh_hub_deinitialize(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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)
|
||||
@@ -48,7 +50,7 @@ static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
|
||||
setup->wIndex = msc_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
return usbh_control_transfer(msc_class->hport->ep0, setup, buffer);
|
||||
return usbh_control_transfer(msc_class->hport, setup, buffer);
|
||||
}
|
||||
|
||||
static void usbh_msc_cbw_dump(struct CBW *cbw)
|
||||
@@ -85,9 +87,8 @@ static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &msc_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
@@ -99,9 +100,8 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &msc_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
@@ -109,7 +109,7 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
|
||||
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
|
||||
{
|
||||
int nbytes;
|
||||
|
||||
@@ -155,12 +155,12 @@ int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct C
|
||||
/* check csw status */
|
||||
if (csw->dSignature != MSC_CSW_Signature) {
|
||||
USB_LOG_ERR("csw signature error\r\n");
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (csw->bStatus != 0) {
|
||||
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
__err_exit:
|
||||
return nbytes < 0 ? (int)nbytes : 0;
|
||||
@@ -234,6 +234,132 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
|
||||
}
|
||||
|
||||
static inline 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 = usbh_msc_class_alloc();
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc msc_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
msc_class->hport = hport;
|
||||
msc_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(msc_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(msc_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_msc_modeswitch_config) {
|
||||
uint8_t num = 0;
|
||||
while (1) {
|
||||
config = &g_msc_modeswitch_config[num];
|
||||
if (config && config->name) {
|
||||
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;
|
||||
}
|
||||
num++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_msc_run(msc_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
|
||||
|
||||
if (msc_class) {
|
||||
if (msc_class->bulkin) {
|
||||
usbh_kill_urb(&msc_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (msc_class->bulkout) {
|
||||
usbh_kill_urb(&msc_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_msc_stop(msc_class);
|
||||
}
|
||||
|
||||
usbh_msc_class_free(msc_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
@@ -273,102 +399,13 @@ 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);
|
||||
}
|
||||
|
||||
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_msc *msc_class = usb_malloc(sizeof(struct usbh_msc));
|
||||
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;
|
||||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&msc_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
if (config) {
|
||||
g_msc_modeswitch_config = config;
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -ERANGE;
|
||||
g_msc_modeswitch_config = NULL;
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_msc_run(msc_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (msc_class->bulkout) {
|
||||
usbh_pipe_free(msc_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_msc_stop(msc_class);
|
||||
}
|
||||
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
usb_free(msc_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
|
||||
@@ -11,17 +11,25 @@
|
||||
|
||||
struct usbh_msc {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
|
||||
uint8_t intf; /* Data interface number */
|
||||
uint8_t sdchar;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
|
||||
uint16_t blocksize; /* Block size of USB mass storage device */
|
||||
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
|
||||
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);
|
||||
|
||||
|
||||
@@ -1,503 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MTP_H
|
||||
#define USB_MTP_H
|
||||
|
||||
#define USB_MTP_CLASS 0x06
|
||||
|
||||
#define USB_MTP_SUB_CLASS 0x01U
|
||||
#define USB_MTP_PROTOCOL 0x01U
|
||||
|
||||
/* MTP class requests */
|
||||
#define MTP_REQUEST_CANCEL 0x64U
|
||||
#define MTP_REQUEST_GET_EXT_EVENT_DATA 0x65U
|
||||
#define MTP_REQUEST_RESET 0x66U
|
||||
#define MTP_REQUEST_GET_DEVICE_STATUS 0x67U
|
||||
|
||||
/* Container Types */
|
||||
#define MTP_CONTAINER_TYPE_UNDEFINED 0U
|
||||
#define MTP_CONTAINER_TYPE_COMMAND 1U
|
||||
#define MTP_CONTAINER_TYPE_DATA 2U
|
||||
#define MTP_CONTAINER_TYPE_RESPONSE 3U
|
||||
#define MTP_CONTAINER_TYPE_EVENT 4U
|
||||
|
||||
/*
|
||||
* MTP Class specification Revision 1.1
|
||||
* Appendix D. Operations
|
||||
*/
|
||||
|
||||
/* Operations code */
|
||||
#define MTP_OP_GET_DEVICE_INFO 0x1001U
|
||||
#define MTP_OP_OPEN_SESSION 0x1002U
|
||||
#define MTP_OP_CLOSE_SESSION 0x1003U
|
||||
#define MTP_OP_GET_STORAGE_IDS 0x1004U
|
||||
#define MTP_OP_GET_STORAGE_INFO 0x1005U
|
||||
#define MTP_OP_GET_NUM_OBJECTS 0x1006U
|
||||
#define MTP_OP_GET_OBJECT_HANDLES 0x1007U
|
||||
#define MTP_OP_GET_OBJECT_INFO 0x1008U
|
||||
#define MTP_OP_GET_OBJECT 0x1009U
|
||||
#define MTP_OP_GET_THUMB 0x100AU
|
||||
#define MTP_OP_DELETE_OBJECT 0x100BU
|
||||
#define MTP_OP_SEND_OBJECT_INFO 0x100CU
|
||||
#define MTP_OP_SEND_OBJECT 0x100DU
|
||||
#define MTP_OP_FORMAT_STORE 0x100FU
|
||||
#define MTP_OP_RESET_DEVICE 0x1010U
|
||||
#define MTP_OP_GET_DEVICE_PROP_DESC 0x1014U
|
||||
#define MTP_OP_GET_DEVICE_PROP_VALUE 0x1015U
|
||||
#define MTP_OP_SET_DEVICE_PROP_VALUE 0x1016U
|
||||
#define MTP_OP_RESET_DEVICE_PROP_VALUE 0x1017U
|
||||
#define MTP_OP_TERMINATE_OPEN_CAPTURE 0x1018U
|
||||
#define MTP_OP_MOVE_OBJECT 0x1019U
|
||||
#define MTP_OP_COPY_OBJECT 0x101AU
|
||||
#define MTP_OP_GET_PARTIAL_OBJECT 0x101BU
|
||||
#define MTP_OP_INITIATE_OPEN_CAPTURE 0x101CU
|
||||
#define MTP_OP_GET_OBJECT_PROPS_SUPPORTED 0x9801U
|
||||
#define MTP_OP_GET_OBJECT_PROP_DESC 0x9802U
|
||||
#define MTP_OP_GET_OBJECT_PROP_VALUE 0x9803U
|
||||
#define MTP_OP_SET_OBJECT_PROP_VALUE 0x9804U
|
||||
#define MTP_OP_GET_OBJECT_PROPLIST 0x9805U
|
||||
#define MTP_OP_GET_OBJECT_PROP_REFERENCES 0x9810U
|
||||
#define MTP_OP_GETSERVICEIDS 0x9301U
|
||||
#define MTP_OP_GETSERVICEINFO 0x9302U
|
||||
#define MTP_OP_GETSERVICECAPABILITIES 0x9303U
|
||||
#define MTP_OP_GETSERVICEPROPDESC 0x9304U
|
||||
|
||||
/* MTP response code */
|
||||
#define MTP_RESPONSE_OK 0x2001U
|
||||
#define MTP_RESPONSE_GENERAL_ERROR 0x2002U
|
||||
#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006U
|
||||
#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007U
|
||||
#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008U
|
||||
#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009U
|
||||
#define MTP_RESPONSE_DEVICEPROP_NOT_SUPPORTED 0x200AU
|
||||
#define MTP_RESPONSE_STORE_FULL 0x200CU
|
||||
#define MTP_RESPONSE_ACCESS_DENIED 0x200FU
|
||||
#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013U
|
||||
#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_NOT_SUPPORTED 0x2014U
|
||||
#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015U
|
||||
#define MTP_RESPONSE_DEVICE_BUSY 0x2019U
|
||||
#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201AU
|
||||
#define MTP_RESPONSE_INVALID_PARAMETER 0x201DU
|
||||
#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201EU
|
||||
#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201FU
|
||||
#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801U
|
||||
#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807U
|
||||
#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80AU
|
||||
|
||||
/* MTP Object format codes */
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED 0x3000U
|
||||
#define MTP_OBJ_FORMAT_ASSOCIATION 0x3001U
|
||||
#define MTP_OBJ_FORMAT_SCRIPT 0x3002U
|
||||
#define MTP_OBJ_FORMAT_EXECUTABLE 0x3003U
|
||||
#define MTP_OBJ_FORMAT_TEXT 0x3004U
|
||||
#define MTP_OBJ_FORMAT_HTML 0x3005U
|
||||
#define MTP_OBJ_FORMAT_DPOF 0x3006U
|
||||
#define MTP_OBJ_FORMAT_AIFF 0x3007U
|
||||
#define MTP_OBJ_FORMAT_WAV 0x3008U
|
||||
#define MTP_OBJ_FORMAT_MP3 0x3009U
|
||||
#define MTP_OBJ_FORMAT_AVI 0x300AU
|
||||
#define MTP_OBJ_FORMAT_MPEG 0x300BU
|
||||
#define MTP_OBJ_FORMAT_ASF 0x300CU
|
||||
#define MTP_OBJ_FORMAT_DEFINED 0x3800U
|
||||
#define MTP_OBJ_FORMAT_EXIF_JPEG 0x3801U
|
||||
#define MTP_OBJ_FORMAT_TIFF_EP 0x3802U
|
||||
#define MTP_OBJ_FORMAT_FLASHPIX 0x3803U
|
||||
#define MTP_OBJ_FORMAT_BMP 0x3804U
|
||||
#define MTP_OBJ_FORMAT_CIFF 0x3805U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED0 0x3806U
|
||||
#define MTP_OBJ_FORMAT_GIF 0x3807U
|
||||
#define MTP_OBJ_FORMAT_JFIF 0x3808U
|
||||
#define MTP_OBJ_FORMAT_CD 0x3809U
|
||||
#define MTP_OBJ_FORMAT_PICT 0x380AU
|
||||
#define MTP_OBJ_FORMAT_PNG 0x380BU
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED1 0x380CU
|
||||
#define MTP_OBJ_FORMAT_TIFF 0x380DU
|
||||
#define MTP_OBJ_FORMAT_TIFF_IT 0x380EU
|
||||
#define MTP_OBJ_FORMAT_JP2 0x380FU
|
||||
#define MTP_OBJ_FORMAT_JPX 0x3810U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_FIRMWARE 0xB802U
|
||||
#define MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_AUDIO 0xB900U
|
||||
#define MTP_OBJ_FORMAT_WMA 0xB901U
|
||||
#define MTP_OBJ_FORMAT_OGG 0xB902U
|
||||
#define MTP_OBJ_FORMAT_AAC 0xB903U
|
||||
#define MTP_OBJ_FORMAT_AUDIBLE 0xB904U
|
||||
#define MTP_OBJ_FORMAT_FLAC 0xB906U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_VIDEO 0xB980U
|
||||
#define MTP_OBJ_FORMAT_WMV 0xB981U
|
||||
#define MTP_OBJ_FORMAT_MP4_CONTAINER 0xB982U
|
||||
#define MTP_OBJ_FORMAT_MP2 0xB983U
|
||||
#define MTP_OBJ_FORMAT_3GP_CONTAINER 0xB984U
|
||||
|
||||
/* MTP event codes*/
|
||||
#define MTP_EVENT_UNDEFINED 0x4000U
|
||||
#define MTP_EVENT_CANCELTRANSACTION 0x4001U
|
||||
#define MTP_EVENT_OBJECTADDED 0x4002U
|
||||
#define MTP_EVENT_OBJECTREMOVED 0x4003U
|
||||
#define MTP_EVENT_STOREADDED 0x4004U
|
||||
#define MTP_EVENT_STOREREMOVED 0x4005U
|
||||
#define MTP_EVENT_DEVICEPROPCHANGED 0x4006U
|
||||
#define MTP_EVENT_OBJECTINFOCHANGED 0x4007U
|
||||
#define MTP_EVENT_DEVICEINFOCHANGED 0x4008U
|
||||
#define MTP_EVENT_REQUESTOBJECTTRANSFER 0x4009U
|
||||
#define MTP_EVENT_STOREFULL 0x400AU
|
||||
#define MTP_EVENT_DEVICERESET 0x400BU
|
||||
#define MTP_EVENT_STORAGEINFOCHANGED 0x400CU
|
||||
#define MTP_EVENT_CAPTURECOMPLETE 0x400DU
|
||||
#define MTP_EVENT_UNREPORTEDSTATUS 0x400EU
|
||||
#define MTP_EVENT_OBJECTPROPCHANGED 0xC801U
|
||||
#define MTP_EVENT_OBJECTPROPDESCCHANGED 0xC802U
|
||||
#define MTP_EVENT_OBJECTREFERENCESCHANGED 0xC803U
|
||||
|
||||
/* MTP device properties code*/
|
||||
#define MTP_DEV_PROP_UNDEFINED 0x5000U
|
||||
#define MTP_DEV_PROP_BATTERY_LEVEL 0x5001U
|
||||
#define MTP_DEV_PROP_FUNCTIONAL_MODE 0x5002U
|
||||
#define MTP_DEV_PROP_IMAGE_SIZE 0x5003U
|
||||
#define MTP_DEV_PROP_COMPRESSION_SETTING 0x5004U
|
||||
#define MTP_DEV_PROP_WHITE_BALANCE 0x5005U
|
||||
#define MTP_DEV_PROP_RGB_GAIN 0x5006U
|
||||
#define MTP_DEV_PROP_F_NUMBER 0x5007U
|
||||
#define MTP_DEV_PROP_FOCAL_LENGTH 0x5008U
|
||||
#define MTP_DEV_PROP_FOCUS_DISTANCE 0x5009U
|
||||
#define MTP_DEV_PROP_FOCUS_MODE 0x500AU
|
||||
#define MTP_DEV_PROP_EXPOSURE_METERING_MODE 0x500BU
|
||||
#define MTP_DEV_PROP_FLASH_MODE 0x500CU
|
||||
#define MTP_DEV_PROP_EXPOSURE_TIME 0x500DU
|
||||
#define MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE 0x500EU
|
||||
#define MTP_DEV_PROP_EXPOSURE_INDEX 0x500FU
|
||||
#define MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION 0x5010U
|
||||
#define MTP_DEV_PROP_DATETIME 0x5011U
|
||||
#define MTP_DEV_PROP_CAPTURE_DELAY 0x5012U
|
||||
#define MTP_DEV_PROP_STILL_CAPTURE_MODE 0x5013U
|
||||
#define MTP_DEV_PROP_CONTRAST 0x5014U
|
||||
#define MTP_DEV_PROP_SHARPNESS 0x5015U
|
||||
#define MTP_DEV_PROP_DIGITAL_ZOOM 0x5016U
|
||||
#define MTP_DEV_PROP_EFFECT_MODE 0x5017U
|
||||
#define MTP_DEV_PROP_BURST_NUMBER 0x5018U
|
||||
#define MTP_DEV_PROP_BURST_INTERVAL 0x5019U
|
||||
#define MTP_DEV_PROP_TIMELAPSE_NUMBER 0x501AU
|
||||
#define MTP_DEV_PROP_TIMELAPSE_INTERVAL 0x501BU
|
||||
#define MTP_DEV_PROP_FOCUS_METERING_MODE 0x501CU
|
||||
#define MTP_DEV_PROP_UPLOAD_URL 0x501DU
|
||||
#define MTP_DEV_PROP_ARTIST 0x501EU
|
||||
#define MTP_DEV_PROP_COPYRIGHT_INFO 0x501FU
|
||||
#define MTP_DEV_PROP_SYNCHRONIZATION_PARTNER 0xD401U
|
||||
#define MTP_DEV_PROP_DEVICE_FRIENDLY_NAME 0xD402U
|
||||
#define MTP_DEV_PROP_VOLUME 0xD403U
|
||||
#define MTP_DEV_PROP_SUPPORTEDFORMATSORDERED 0xD404U
|
||||
#define MTP_DEV_PROP_DEVICEICON 0xD405U
|
||||
#define MTP_DEV_PROP_PLAYBACK_RATE 0xD410U
|
||||
#define MTP_DEV_PROP_PLAYBACK_OBJECT 0xD411U
|
||||
#define MTP_DEV_PROP_PLAYBACK_CONTAINER 0xD412U
|
||||
#define MTP_DEV_PROP_SESSION_INITIATOR_VERSION_INFO 0xD406U
|
||||
#define MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE 0xD407U
|
||||
|
||||
/*
|
||||
* MTP Class specification Revision 1.1
|
||||
* Appendix B. Object Properties
|
||||
*/
|
||||
|
||||
/* MTP OBJECT PROPERTIES supported*/
|
||||
#define MTP_OB_PROP_STORAGE_ID 0xDC01U
|
||||
#define MTP_OB_PROP_OBJECT_FORMAT 0xDC02U
|
||||
#define MTP_OB_PROP_PROTECTION_STATUS 0xDC03U
|
||||
#define MTP_OB_PROP_OBJECT_SIZE 0xDC04U
|
||||
#define MTP_OB_PROP_ASSOC_TYPE 0xDC05U
|
||||
#define MTP_OB_PROP_ASSOC_DESC 0xDC06U
|
||||
#define MTP_OB_PROP_OBJ_FILE_NAME 0xDC07U
|
||||
#define MTP_OB_PROP_DATE_CREATED 0xDC08U
|
||||
#define MTP_OB_PROP_DATE_MODIFIED 0xDC09U
|
||||
#define MTP_OB_PROP_KEYWORDS 0xDC0AU
|
||||
#define MTP_OB_PROP_PARENT_OBJECT 0xDC0BU
|
||||
#define MTP_OB_PROP_ALLOWED_FOLD_CONTENTS 0xDC0CU
|
||||
#define MTP_OB_PROP_HIDDEN 0xDC0DU
|
||||
#define MTP_OB_PROP_SYSTEM_OBJECT 0xDC0EU
|
||||
#define MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN 0xDC41U
|
||||
#define MTP_OB_PROP_SYNCID 0xDC42U
|
||||
#define MTP_OB_PROP_PROPERTY_BAG 0xDC43U
|
||||
#define MTP_OB_PROP_NAME 0xDC44U
|
||||
#define MTP_OB_PROP_CREATED_BY 0xDC45U
|
||||
#define MTP_OB_PROP_ARTIST 0xDC46U
|
||||
#define MTP_OB_PROP_DATE_AUTHORED 0xDC47U
|
||||
#define MTP_OB_PROP_DESCRIPTION 0xDC48U
|
||||
#define MTP_OB_PROP_URL_REFERENCE 0xDC49U
|
||||
#define MTP_OB_PROP_LANGUAGELOCALE 0xDC4AU
|
||||
#define MTP_OB_PROP_COPYRIGHT_INFORMATION 0xDC4BU
|
||||
#define MTP_OB_PROP_SOURCE 0xDC4CU
|
||||
#define MTP_OB_PROP_ORIGIN_LOCATION 0xDC4DU
|
||||
#define MTP_OB_PROP_DATE_ADDED 0xDC4EU
|
||||
#define MTP_OB_PROP_NON_CONSUMABLE 0xDC4FU
|
||||
#define MTP_OB_PROP_CORRUPTUNPLAYABLE 0xDC50U
|
||||
#define MTP_OB_PROP_PRODUCERSERIALNUMBER 0xDC51U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_SIZE 0xDC82U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DURATION 0xDC85U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DATA 0xDC86U
|
||||
#define MTP_OB_PROP_WIDTH 0xDC87U
|
||||
#define MTP_OB_PROP_HEIGHT 0xDC88U
|
||||
#define MTP_OB_PROP_DURATION 0xDC89U
|
||||
#define MTP_OB_PROP_RATING 0xDC8AU
|
||||
#define MTP_OB_PROP_TRACK 0xDC8BU
|
||||
#define MTP_OB_PROP_GENRE 0xDC8CU
|
||||
#define MTP_OB_PROP_CREDITS 0xDC8DU
|
||||
#define MTP_OB_PROP_LYRICS 0xDC8EU
|
||||
#define MTP_OB_PROP_SUBSCRIPTION_CONTENT_ID 0xDC8FU
|
||||
#define MTP_OB_PROP_PRODUCED_BY 0xDC90U
|
||||
#define MTP_OB_PROP_USE_COUNT 0xDC91U
|
||||
#define MTP_OB_PROP_SKIP_COUNT 0xDC92U
|
||||
#define MTP_OB_PROP_LAST_ACCESSED 0xDC93U
|
||||
#define MTP_OB_PROP_PARENTAL_RATING 0xDC94U
|
||||
#define MTP_OB_PROP_META_GENRE 0xDC95U
|
||||
#define MTP_OB_PROP_COMPOSER 0xDC96U
|
||||
#define MTP_OB_PROP_EFFECTIVE_RATING 0xDC97U
|
||||
#define MTP_OB_PROP_SUBTITLE 0xDC98U
|
||||
#define MTP_OB_PROP_ORIGINAL_RELEASE_DATE 0xDC99U
|
||||
#define MTP_OB_PROP_ALBUM_NAME 0xDC9AU
|
||||
#define MTP_OB_PROP_ALBUM_ARTIST 0xDC9BU
|
||||
#define MTP_OB_PROP_MOOD 0xDC9CU
|
||||
#define MTP_OB_PROP_DRM_STATUS 0xDC9DU
|
||||
#define MTP_OB_PROP_SUB_DESCRIPTION 0xDC9EU
|
||||
#define MTP_OB_PROP_IS_CROPPED 0xDCD1U
|
||||
#define MTP_OB_PROP_IS_COLOUR_CORRECTED 0xDCD2U
|
||||
#define MTP_OB_PROP_IMAGE_BIT_DEPTH 0xDCD3U
|
||||
#define MTP_OB_PROP_FNUMBER 0xDCD4U
|
||||
#define MTP_OB_PROP_EXPOSURE_TIME 0xDCD5U
|
||||
#define MTP_OB_PROP_EXPOSURE_INDEX 0xDCD6U
|
||||
#define MTP_OB_PROP_TOTAL_BITRATE 0xDE91U
|
||||
#define MTP_OB_PROP_BITRATE_TYPE 0xDE92U
|
||||
#define MTP_OB_PROP_SAMPLE_RATE 0xDE93U
|
||||
#define MTP_OB_PROP_NUMBER_OF_CHANNELS 0xDE94U
|
||||
#define MTP_OB_PROP_AUDIO_BITDEPTH 0xDE95U
|
||||
#define MTP_OB_PROP_SCAN_TYPE 0xDE97U
|
||||
#define MTP_OB_PROP_AUDIO_WAVE_CODEC 0xDE99U
|
||||
#define MTP_OB_PROP_AUDIO_BITRATE 0xDE9AU
|
||||
#define MTP_OB_PROP_VIDEO_FOURCC_CODEC 0xDE9BU
|
||||
#define MTP_OB_PROP_VIDEO_BITRATE 0xDE9CU
|
||||
#define MTP_OB_PROP_FRAMES_PER_THOUSAND_SECONDS 0xDE9DU
|
||||
#define MTP_OB_PROP_KEYFRAME_DISTANCE 0xDE9EU
|
||||
#define MTP_OB_PROP_BUFFER_SIZE 0xDE9FU
|
||||
#define MTP_OB_PROP_ENCODING_QUALITY 0xDEA0U
|
||||
#define MTP_OB_PROP_ENCODING_PROFILE 0xDEA1U
|
||||
#define MTP_OB_PROP_DISPLAY_NAME 0xDCE0U
|
||||
#define MTP_OB_PROP_BODY_TEXT 0xDCE1U
|
||||
#define MTP_OB_PROP_SUBJECT 0xDCE2U
|
||||
#define MTP_OB_PROP_PRIORITY 0xDCE3U
|
||||
#define MTP_OB_PROP_GIVEN_NAME 0xDD00U
|
||||
#define MTP_OB_PROP_MIDDLE_NAMES 0xDD01U
|
||||
#define MTP_OB_PROP_FAMILY_NAME 0xDD02U
|
||||
#define MTP_OB_PROP_PREFIX 0xDD03U
|
||||
#define MTP_OB_PROP_SUFFIX 0xDD04U
|
||||
#define MTP_OB_PROP_PHONETIC_GIVEN_NAME 0xDD05U
|
||||
#define MTP_OB_PROP_PHONETIC_FAMILY_NAME 0xDD06U
|
||||
#define MTP_OB_PROP_EMAIL_PRIMARY 0xDD07U
|
||||
#define MTP_OB_PROP_EMAIL_PERSONAL_1 0xDD08U
|
||||
#define MTP_OB_PROP_EMAIL_PERSONAL_2 0xDD09U
|
||||
#define MTP_OB_PROP_EMAIL_BUSINESS_1 0xDD0AU
|
||||
#define MTP_OB_PROP_EMAIL_BUSINESS_2 0xDD0BU
|
||||
#define MTP_OB_PROP_EMAIL_OTHERS 0xDD0CU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PRIMARY 0xDD0DU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL 0xDD0EU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL_2 0xDD0FU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS 0xDD10U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS_2 0xDD11U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE 0xDD12U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE_2 0xDD13U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_PRIMARY 0xDD14U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_PERSONAL 0xDD15U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_BUSINESS 0xDD16U
|
||||
#define MTP_OB_PROP_PAGER_NUMBER 0xDD17U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_OTHERS 0xDD18U
|
||||
#define MTP_OB_PROP_PRIMARY_WEB_ADDRESS 0xDD19U
|
||||
#define MTP_OB_PROP_PERSONAL_WEB_ADDRESS 0xDD1AU
|
||||
#define MTP_OB_PROP_BUSINESS_WEB_ADDRESS 0xDD1BU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS 0xDD1CU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_2 0xDD1DU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_3 0xDD1EU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1FU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2AU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2BU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2CU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_FULL 0xDD2DU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2EU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2FU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_CITY 0xDD30U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_REGION 0xDD31U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33U
|
||||
#define MTP_OB_PROP_ORGANIZATION_NAME 0xDD34U
|
||||
#define MTP_OB_PROP_PHONETIC_ORGANIZATION_NAME 0xDD35U
|
||||
#define MTP_OB_PROP_ROLE 0xDD36U
|
||||
#define MTP_OB_PROP_BIRTHDATE 0xDD37U
|
||||
#define MTP_OB_PROP_MESSAGE_TO 0xDD40U
|
||||
#define MTP_OB_PROP_MESSAGE_CC 0xDD41U
|
||||
#define MTP_OB_PROP_MESSAGE_BCC 0xDD42U
|
||||
#define MTP_OB_PROP_MESSAGE_READ 0xDD43U
|
||||
#define MTP_OB_PROP_MESSAGE_RECEIVED_TIME 0xDD44U
|
||||
#define MTP_OB_PROP_MESSAGE_SENDER 0xDD45U
|
||||
#define MTP_OB_PROP_ACT_BEGIN_TIME 0xDD50U
|
||||
#define MTP_OB_PROP_ACT_END_TIME 0xDD51U
|
||||
#define MTP_OB_PROP_ACT_LOCATION 0xDD52U
|
||||
#define MTP_OB_PROP_ACT_REQUIRED_ATTENDEES 0xDD54U
|
||||
#define MTP_OB_PROP_ACT_OPTIONAL_ATTENDEES 0xDD55U
|
||||
#define MTP_OB_PROP_ACT_RESOURCES 0xDD56U
|
||||
#define MTP_OB_PROP_ACT_ACCEPTED 0xDD57U
|
||||
#define MTP_OB_PROP_OWNER 0xDD5DU
|
||||
#define MTP_OB_PROP_EDITOR 0xDD5EU
|
||||
#define MTP_OB_PROP_WEBMASTER 0xDD5FU
|
||||
#define MTP_OB_PROP_URL_SOURCE 0xDD60U
|
||||
#define MTP_OB_PROP_URL_DESTINATION 0xDD61U
|
||||
#define MTP_OB_PROP_TIME_BOOKMARK 0xDD62U
|
||||
#define MTP_OB_PROP_OBJECT_BOOKMARK 0xDD63U
|
||||
#define MTP_OB_PROP_BYTE_BOOKMARK 0xDD64U
|
||||
#define MTP_OB_PROP_LAST_BUILD_DATE 0xDD70U
|
||||
#define MTP_OB_PROP_TIME_TO_LIVE 0xDD71U
|
||||
#define MTP_OB_PROP_MEDIA_GUID 0xDD72U
|
||||
|
||||
/* MTP storage type */
|
||||
#define MTP_STORAGE_UNDEFINED 0U
|
||||
#define MTP_STORAGE_FIXED_ROM 0x0001U
|
||||
#define MTP_STORAGE_REMOVABLE_ROM 0x0002U
|
||||
#define MTP_STORAGE_FIXED_RAM 0x0003U
|
||||
#define MTP_STORAGE_REMOVABLE_RAM 0x0004U
|
||||
|
||||
/* MTP file system type */
|
||||
#define MTP_FILESYSTEM_UNDEFINED 0U
|
||||
#define MTP_FILESYSTEM_GENERIC_FLAT 0x0001U
|
||||
#define MTP_FILESYSTEM_GENERIC_HIERARCH 0x0002U
|
||||
#define MTP_FILESYSTEM_DCF 0x0003U
|
||||
|
||||
/* MTP access capability */
|
||||
#define MTP_ACCESS_CAP_RW 0U /* read write */
|
||||
#define MTP_ACCESS_CAP_RO_WITHOUT_DEL 0x0001U
|
||||
#define MTP_ACCESS_CAP_RO_WITH_DEL 0x0002U
|
||||
|
||||
/* MTP standard data types supported */
|
||||
#define MTP_DATATYPE_INT8 0x0001U
|
||||
#define MTP_DATATYPE_UINT8 0x0002U
|
||||
#define MTP_DATATYPE_INT16 0x0003U
|
||||
#define MTP_DATATYPE_UINT16 0x0004U
|
||||
#define MTP_DATATYPE_INT32 0x0005U
|
||||
#define MTP_DATATYPE_UINT32 0x0006U
|
||||
#define MTP_DATATYPE_INT64 0x0007U
|
||||
#define MTP_DATATYPE_UINT64 0x0008U
|
||||
#define MTP_DATATYPE_UINT128 0x000AU
|
||||
#define MTP_DATATYPE_STR 0xFFFFU
|
||||
|
||||
/* MTP reading only or reading/writing */
|
||||
#define MTP_PROP_GET 0x00U
|
||||
#define MTP_PROP_GET_SET 0x01U
|
||||
|
||||
#define MTP_SESSION_CLOSED 0x00
|
||||
#define MTP_SESSION_OPENED 0x01
|
||||
|
||||
struct mtp_container_command {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
uint32_t param4;
|
||||
uint32_t param5;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_container_data {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
uint8_t data[512];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_container_response {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
} __PACKED;
|
||||
|
||||
/*Length of template descriptor: 23 bytes*/
|
||||
#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 */ \
|
||||
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 */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
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 */
|
||||
@@ -1,566 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_mtp.h"
|
||||
#include "usbd_mtp_config.h"
|
||||
|
||||
/* MTP Stage */
|
||||
enum Stage {
|
||||
MTP_READ_COMMAND = 0,
|
||||
MTP_DATA_OUT = 1,
|
||||
MTP_DATA_IN = 2,
|
||||
MTP_SEND_RESPONSE = 3,
|
||||
MTP_WAIT_RESPONSE = 4,
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp {
|
||||
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;
|
||||
enum Stage stage;
|
||||
uint8_t session_state;
|
||||
uint32_t response_code;
|
||||
} g_usbd_mtp;
|
||||
|
||||
/* Max USB packet size */
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MTP_BULK_EP_MPS 64
|
||||
#else
|
||||
#define MTP_BULK_EP_MPS 512
|
||||
#endif
|
||||
|
||||
#define MTP_OUT_EP_IDX 0
|
||||
#define MTP_IN_EP_IDX 1
|
||||
#define MTP_INT_EP_IDX 2
|
||||
|
||||
/* Describe EndPoints configuration */
|
||||
static struct usbd_endpoint mtp_ep_data[3];
|
||||
|
||||
static int mtp_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("MTP Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case MTP_REQUEST_CANCEL:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_GET_EXT_EVENT_DATA:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_RESET:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_GET_DEVICE_STATUS:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled MTP Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbd_mtp_send_response(uint32_t code)
|
||||
{
|
||||
USB_LOG_DBG("Send response\r\n");
|
||||
|
||||
g_usbd_mtp.stage = MTP_WAIT_RESPONSE;
|
||||
|
||||
g_usbd_mtp.con_response.conlen = 12;
|
||||
g_usbd_mtp.con_response.contype = MTP_CONTAINER_TYPE_RESPONSE;
|
||||
g_usbd_mtp.con_response.code = code;
|
||||
g_usbd_mtp.con_response.trans_id = g_usbd_mtp.con_command.trans_id;
|
||||
|
||||
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_response, 12);
|
||||
}
|
||||
|
||||
static void usbd_mtp_send_info(uint8_t *data, uint32_t len)
|
||||
{
|
||||
USB_LOG_DBG("Send info\r\n");
|
||||
|
||||
g_usbd_mtp.stage = MTP_SEND_RESPONSE;
|
||||
|
||||
g_usbd_mtp.con_data.conlen = 12 + len;
|
||||
g_usbd_mtp.con_data.contype = MTP_CONTAINER_TYPE_DATA;
|
||||
g_usbd_mtp.con_data.code = MTP_RESPONSE_OK;
|
||||
g_usbd_mtp.con_data.trans_id = g_usbd_mtp.con_command.trans_id;
|
||||
|
||||
memcpy(g_usbd_mtp.con_data.data, data, len);
|
||||
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_data, 12 + len);
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_device_info(void)
|
||||
{
|
||||
struct mtp_device_info device_info;
|
||||
uint16_t i;
|
||||
|
||||
device_info.StandardVersion = 100;
|
||||
device_info.VendorExtensionID = 0x06;
|
||||
device_info.VendorExtensionVersion = 100;
|
||||
device_info.VendorExtensionDesc_len = (uint8_t)CONFIG_MTP_VEND_EXT_DESC_LEN;
|
||||
|
||||
for (i = 0; i < CONFIG_MTP_VEND_EXT_DESC_LEN; i++) {
|
||||
device_info.VendorExtensionDesc[i] = VendExtDesc[i];
|
||||
}
|
||||
|
||||
/* device supports one mode , standard mode */
|
||||
device_info.FunctionalMode = 0x0000;
|
||||
|
||||
/* All supported operation */
|
||||
device_info.OperationsSupported_len = CONFIG_MTP_SUPP_OP_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OP_LEN; i++) {
|
||||
device_info.OperationsSupported[i] = SuppOP[i];
|
||||
}
|
||||
|
||||
/* event that are currently generated by the device*/
|
||||
device_info.EventsSupported_len = CONFIG_MTP_SUPP_EVENTS_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_EVENTS_LEN; i++) {
|
||||
device_info.EventsSupported[i] = SuppEvents[i];
|
||||
}
|
||||
|
||||
device_info.DevicePropertiesSupported_len = CONFIG_MTP_SUPP_DEVICE_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_DEVICE_PROP_LEN; i++) {
|
||||
device_info.DevicePropertiesSupported[i] = DevicePropSupp[i];
|
||||
}
|
||||
|
||||
device_info.CaptureFormats_len = CONFIG_MTP_SUPP_CAPT_FORMAT_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_CAPT_FORMAT_LEN; i++) {
|
||||
device_info.CaptureFormats[i] = SuppCaptFormat[i];
|
||||
}
|
||||
|
||||
device_info.ImageFormats_len = CONFIG_MTP_SUPP_IMG_FORMAT_LEN; /* number of image formats that are supported by the device*/
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_IMG_FORMAT_LEN; i++) {
|
||||
device_info.ImageFormats[i] = SuppImgFormat[i];
|
||||
}
|
||||
|
||||
device_info.Manufacturer_len = (uint8_t)CONFIG_MTP_MANUF_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_MANUF_LEN; i++) {
|
||||
device_info.Manufacturer[i] = Manuf[i];
|
||||
}
|
||||
|
||||
device_info.Model_len = (uint8_t)CONFIG_MTP_MODEL_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_MODEL_LEN; i++) {
|
||||
device_info.Model[i] = Model[i];
|
||||
}
|
||||
|
||||
device_info.DeviceVersion_len = (uint8_t)CONFIG_MTP_DEVICE_VERSION_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_DEVICE_VERSION_LEN; i++) {
|
||||
device_info.DeviceVersion[i] = DeviceVers[i];
|
||||
}
|
||||
|
||||
device_info.SerialNumber_len = (uint8_t)CONFIG_MTP_SERIAL_NBR_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_SERIAL_NBR_LEN; i++) {
|
||||
device_info.SerialNumber[i] = SerialNbr[i];
|
||||
}
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&device_info, sizeof(struct mtp_device_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_open_session(void)
|
||||
{
|
||||
usbd_mtp_send_response(MTP_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_storage_ids(void)
|
||||
{
|
||||
struct mtp_storage_id storage_id;
|
||||
|
||||
storage_id.StorageIDS_len = CONFIG_MTP_STORAGE_ID_LEN;
|
||||
storage_id.StorageIDS[0] = MTP_STORAGE_ID;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&storage_id, sizeof(struct mtp_storage_id));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_storage_info(void)
|
||||
{
|
||||
struct mtp_storage_info storage_info;
|
||||
|
||||
storage_info.StorageType = MTP_STORAGE_REMOVABLE_RAM;
|
||||
storage_info.FilesystemType = MTP_FILESYSTEM_GENERIC_FLAT;
|
||||
storage_info.AccessCapability = MTP_ACCESS_CAP_RW;
|
||||
storage_info.MaxCapability = 0x0080DFA81A000000; // todo
|
||||
storage_info.FreeSpaceInBytes = 0x00007EEB0D000000; // todo
|
||||
storage_info.FreeSpaceInObjects = 0xFFFFFFFFU; /* not used */
|
||||
storage_info.StorageDescription = 0U;
|
||||
storage_info.VolumeLabel = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&storage_info, sizeof(struct mtp_storage_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_handles(void)
|
||||
{
|
||||
struct mtp_object_handle object_handle;
|
||||
|
||||
// todo
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&object_handle, sizeof(struct mtp_object_handle));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_info(void)
|
||||
{
|
||||
struct mtp_object_info object_info;
|
||||
|
||||
object_info.Storage_id = MTP_STORAGE_ID;
|
||||
object_info.ObjectFormat = 0; // todo
|
||||
object_info.ObjectCompressedSize = 0; //todo
|
||||
object_info.ProtectionStatus = 0U;
|
||||
object_info.ThumbFormat = MTP_OBJ_FORMAT_UNDEFINED;
|
||||
object_info.ThumbCompressedSize = 0U;
|
||||
object_info.ThumbPixWidth = 0U; /* not supported or not an image */
|
||||
object_info.ThumbPixHeight = 0U;
|
||||
object_info.ImagePixWidth = 0U;
|
||||
object_info.ImagePixHeight = 0U;
|
||||
object_info.ImageBitDepth = 0U;
|
||||
object_info.ParentObject = 0; // todo
|
||||
object_info.AssociationType = 0U;
|
||||
object_info.AssociationDesc = 0U;
|
||||
object_info.SequenceNumber = 0U;
|
||||
|
||||
/* we have to get this value before object_info.Filename */
|
||||
object_info.Filename_len = sizeof(DefaultFileName);
|
||||
memcpy(object_info.Filename, DefaultFileName, (uint32_t)object_info.Filename_len + 1U);
|
||||
|
||||
object_info.CaptureDate = 0U;
|
||||
object_info.ModificationDate = 0U;
|
||||
object_info.Keywords = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&object_info, sizeof(struct mtp_object_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_prop_desc(void)
|
||||
{
|
||||
struct mtp_object_prop_desc object_prop_desc;
|
||||
|
||||
uint16_t undef_format = MTP_OBJ_FORMAT_UNDEFINED;
|
||||
uint32_t storageid = MTP_STORAGE_ID;
|
||||
|
||||
switch (g_usbd_mtp.con_command.param1) /* switch obj prop code */
|
||||
{
|
||||
case MTP_OB_PROP_OBJECT_FORMAT:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = (uint8_t *)&undef_format;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_STORAGE_ID:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT32;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = (uint8_t *)&storageid;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJ_FILE_NAME:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PARENT_OBJECT:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_SIZE:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT64;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_NAME:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = NULL;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT128;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PROTECTION_STATUS:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET_SET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// todo
|
||||
usbd_mtp_send_info((uint8_t *)&object_prop_desc, sizeof(struct mtp_object_prop_desc));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_props_supported(void)
|
||||
{
|
||||
struct mtp_object_props_support object_props_support;
|
||||
uint32_t i;
|
||||
|
||||
object_props_support.ObjectPropCode_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
|
||||
object_props_support.ObjectPropCode[i] = ObjectPropCode[i];
|
||||
}
|
||||
usbd_mtp_send_info((uint8_t *)&object_props_support, sizeof(struct mtp_object_props_support));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_prop_list(void)
|
||||
{
|
||||
struct mtp_object_prop_list object_prop_list;
|
||||
|
||||
uint16_t filename[255];
|
||||
uint32_t storageid = MTP_STORAGE_ID;
|
||||
uint32_t default_val = 0U;
|
||||
uint32_t i;
|
||||
uint16_t format;
|
||||
uint64_t objsize;
|
||||
uint32_t parent_proval;
|
||||
|
||||
object_prop_list.Properties_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
|
||||
object_prop_list.Properties[i].ObjectHandle = g_usbd_mtp.con_command.param1;
|
||||
|
||||
switch (ObjectPropCode[i]) {
|
||||
case MTP_OB_PROP_STORAGE_ID:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_STORAGE_ID;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&storageid;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_FORMAT:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_FORMAT;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&format;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJ_FILE_NAME:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJ_FILE_NAME;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
|
||||
object_prop_list.Properties[i].propval = NULL;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PARENT_OBJECT:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PARENT_OBJECT;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&parent_proval;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_SIZE:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_SIZE;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT64;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&objsize;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_NAME:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_NAME;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
|
||||
object_prop_list.Properties[i].propval = NULL;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT128;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&g_usbd_mtp.con_command.param1;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PROTECTION_STATUS:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PROTECTION_STATUS;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&default_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// todo
|
||||
usbd_mtp_send_info((uint8_t *)&object_prop_list, sizeof(struct mtp_object_prop_list));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_device_prop_desc(void)
|
||||
{
|
||||
struct mtp_device_prop_desc device_prop_desc;
|
||||
uint32_t i;
|
||||
|
||||
device_prop_desc.DevicePropertyCode = MTP_DEV_PROP_DEVICE_FRIENDLY_NAME;
|
||||
device_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
device_prop_desc.GetSet = MTP_PROP_GET_SET;
|
||||
device_prop_desc.DefaultValue_len = CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN;
|
||||
|
||||
for (i = 0U; i < (sizeof(DevicePropDefVal) / 2U); i++) {
|
||||
device_prop_desc.DefaultValue[i] = DevicePropDefVal[i];
|
||||
}
|
||||
|
||||
device_prop_desc.CurrentValue_len = CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN;
|
||||
|
||||
for (i = 0U; i < (sizeof(DevicePropCurDefVal) / 2U); i++) {
|
||||
device_prop_desc.CurrentValue[i] = DevicePropCurDefVal[i];
|
||||
}
|
||||
|
||||
device_prop_desc.FormFlag = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&device_prop_desc, sizeof(struct mtp_device_prop_desc));
|
||||
}
|
||||
|
||||
static int usbd_mtp_decode_command(struct mtp_container_command *command)
|
||||
{
|
||||
printf("code:%04x\r\n", command->code);
|
||||
switch (command->code) {
|
||||
case MTP_OP_GET_DEVICE_INFO:
|
||||
usbd_mtp_get_device_info();
|
||||
break;
|
||||
case MTP_OP_OPEN_SESSION:
|
||||
usbd_mtp_open_session();
|
||||
break;
|
||||
case MTP_OP_CLOSE_SESSION:
|
||||
break;
|
||||
case MTP_OP_GET_STORAGE_IDS:
|
||||
usbd_mtp_get_storage_ids();
|
||||
break;
|
||||
case MTP_OP_GET_STORAGE_INFO:
|
||||
usbd_mtp_get_storage_info();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_HANDLES:
|
||||
usbd_mtp_get_object_handles();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_INFO:
|
||||
usbd_mtp_get_object_info();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_REFERENCES:
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROPS_SUPPORTED:
|
||||
usbd_mtp_get_object_props_supported();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_DESC:
|
||||
usbd_mtp_get_object_prop_desc();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROPLIST:
|
||||
usbd_mtp_get_object_prop_list();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_VALUE:
|
||||
break;
|
||||
case MTP_OP_GET_DEVICE_PROP_DESC:
|
||||
usbd_mtp_get_device_prop_desc();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT:
|
||||
break;
|
||||
case MTP_OP_SEND_OBJECT_INFO:
|
||||
break;
|
||||
case MTP_OP_SEND_OBJECT:
|
||||
break;
|
||||
case MTP_OP_DELETE_OBJECT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbd_mtp_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (g_usbd_mtp.stage) {
|
||||
case MTP_READ_COMMAND:
|
||||
usbd_mtp_decode_command(&g_usbd_mtp.con_command);
|
||||
break;
|
||||
case MTP_DATA_OUT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_mtp_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
printf("send:%d\r\n", nbytes);
|
||||
switch (g_usbd_mtp.stage) {
|
||||
case MTP_DATA_IN:
|
||||
break;
|
||||
case MTP_SEND_RESPONSE:
|
||||
usbd_mtp_send_response(MTP_RESPONSE_OK);
|
||||
break;
|
||||
case MTP_WAIT_RESPONSE:
|
||||
USB_LOG_DBG("Start reading command\r\n");
|
||||
g_usbd_mtp.stage = MTP_READ_COMMAND;
|
||||
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mtp_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
USB_LOG_DBG("Start reading command\r\n");
|
||||
g_usbd_mtp.stage = MTP_READ_COMMAND;
|
||||
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep)
|
||||
{
|
||||
intf->class_interface_handler = mtp_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = mtp_notify_handler;
|
||||
|
||||
mtp_ep_data[MTP_OUT_EP_IDX].ep_addr = out_ep;
|
||||
mtp_ep_data[MTP_OUT_EP_IDX].ep_cb = usbd_mtp_bulk_out;
|
||||
mtp_ep_data[MTP_IN_EP_IDX].ep_addr = in_ep;
|
||||
mtp_ep_data[MTP_IN_EP_IDX].ep_cb = usbd_mtp_bulk_in;
|
||||
mtp_ep_data[MTP_INT_EP_IDX].ep_addr = int_ep;
|
||||
mtp_ep_data[MTP_INT_EP_IDX].ep_cb = NULL;
|
||||
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_IN_EP_IDX]);
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_INT_EP_IDX]);
|
||||
|
||||
return intf;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_MTP_H
|
||||
#define USBD_MTP_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_MTP_H */
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MTP_CONFIG_H
|
||||
#define USB_MTP_CONFIG_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
static const uint16_t VendExtDesc[] = { 'm', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '.', 'c', 'o', 'm', ':', ' ', '1', '.', '0', ';', ' ', 0 }; /* last 2 bytes must be 0*/
|
||||
|
||||
static const uint16_t SuppOP[] = { MTP_OP_GET_DEVICE_INFO, MTP_OP_OPEN_SESSION, MTP_OP_CLOSE_SESSION,
|
||||
MTP_OP_GET_STORAGE_IDS, MTP_OP_GET_STORAGE_INFO, MTP_OP_GET_NUM_OBJECTS,
|
||||
MTP_OP_GET_OBJECT_HANDLES, MTP_OP_GET_OBJECT_INFO, MTP_OP_GET_OBJECT,
|
||||
MTP_OP_DELETE_OBJECT, MTP_OP_SEND_OBJECT_INFO, MTP_OP_SEND_OBJECT,
|
||||
MTP_OP_GET_DEVICE_PROP_DESC, MTP_OP_GET_DEVICE_PROP_VALUE,
|
||||
MTP_OP_SET_OBJECT_PROP_VALUE, MTP_OP_GET_OBJECT_PROP_VALUE,
|
||||
MTP_OP_GET_OBJECT_PROPS_SUPPORTED, MTP_OP_GET_OBJECT_PROPLIST,
|
||||
MTP_OP_GET_OBJECT_PROP_DESC, MTP_OP_GET_OBJECT_PROP_REFERENCES };
|
||||
|
||||
static const uint16_t SuppEvents[] = { MTP_EVENT_OBJECTADDED };
|
||||
|
||||
static const uint16_t DevicePropSupp[] = { MTP_DEV_PROP_DEVICE_FRIENDLY_NAME, MTP_DEV_PROP_BATTERY_LEVEL };
|
||||
|
||||
static const uint16_t SuppCaptFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_ASSOCIATION, MTP_OBJ_FORMAT_TEXT };
|
||||
|
||||
static const uint16_t SuppImgFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_TEXT, MTP_OBJ_FORMAT_ASSOCIATION,
|
||||
MTP_OBJ_FORMAT_EXECUTABLE, MTP_OBJ_FORMAT_WAV, MTP_OBJ_FORMAT_MP3,
|
||||
MTP_OBJ_FORMAT_EXIF_JPEG, MTP_OBJ_FORMAT_MPEG, MTP_OBJ_FORMAT_MP4_CONTAINER,
|
||||
MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT, MTP_OBJ_FORMAT_PNG, MTP_OBJ_FORMAT_WMA,
|
||||
MTP_OBJ_FORMAT_WMV };
|
||||
|
||||
static const uint16_t Manuf[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t Model[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t DeviceVers[] = { 'V', '1', '.', '0', '0', 0 }; /* last 2 bytes must be 0*/
|
||||
/*SerialNbr shall be 32 character hexadecimal string for legacy compatibility reasons */
|
||||
static const uint16_t SerialNbr[] = { '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0', '0',
|
||||
'1', '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0',
|
||||
'0', '1', '0', '0', 0 }; /* last 2 bytes must be 0*/
|
||||
|
||||
static const uint16_t DefaultFileName[] = { 'N', 'e', 'w', ' ', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
|
||||
|
||||
static const uint16_t DevicePropDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t DevicePropCurDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 };
|
||||
|
||||
/* required for all object format : storageID, objectFormat, ObjectCompressedSize,
|
||||
persistent unique object identifier, name*/
|
||||
static const uint16_t ObjectPropCode[] = { MTP_OB_PROP_STORAGE_ID, MTP_OB_PROP_OBJECT_FORMAT, MTP_OB_PROP_OBJECT_SIZE,
|
||||
MTP_OB_PROP_OBJ_FILE_NAME, MTP_OB_PROP_PARENT_OBJECT, MTP_OB_PROP_NAME,
|
||||
MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN, MTP_OB_PROP_PROTECTION_STATUS };
|
||||
|
||||
#define MTP_STORAGE_ID 0x00010001U /* SD card is inserted*/
|
||||
|
||||
#define CONFIG_MTP_VEND_EXT_DESC_LEN (sizeof(VendExtDesc) / 2U)
|
||||
#define CONFIG_MTP_SUPP_OP_LEN (sizeof(SuppOP) / 2U)
|
||||
#define CONFIG_MTP_SUPP_EVENTS_LEN (sizeof(SuppEvents) / 2U)
|
||||
#define CONFIG_MTP_SUPP_DEVICE_PROP_LEN (sizeof(DevicePropSupp) / 2U)
|
||||
#define CONFIG_MTP_SUPP_CAPT_FORMAT_LEN (sizeof(SuppCaptFormat) / 2U)
|
||||
#define CONFIG_MTP_SUPP_IMG_FORMAT_LEN (sizeof(SuppImgFormat) / 2U)
|
||||
#define CONFIG_MTP_MANUF_LEN (sizeof(Manuf) / 2U)
|
||||
#define CONFIG_MTP_MODEL_LEN (sizeof(Model) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_VERSION_LEN (sizeof(DeviceVers) / 2U)
|
||||
#define CONFIG_MTP_SERIAL_NBR_LEN (sizeof(SerialNbr) / 2U)
|
||||
#define CONFIG_MTP_SUPP_OBJ_PROP_LEN (sizeof(ObjectPropCode) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN (sizeof(DevicePropDefVal) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN (sizeof(DevicePropCurDefVal) / 2U)
|
||||
#define CONFIG_MTP_STORAGE_ID_LEN 1
|
||||
#define CONFIG_MTP_OBJECT_HANDLE_LEN 100
|
||||
|
||||
struct mtp_device_info {
|
||||
uint16_t StandardVersion;
|
||||
uint32_t VendorExtensionID;
|
||||
uint16_t VendorExtensionVersion;
|
||||
uint8_t VendorExtensionDesc_len;
|
||||
uint16_t VendorExtensionDesc[CONFIG_MTP_VEND_EXT_DESC_LEN];
|
||||
uint16_t FunctionalMode;
|
||||
uint32_t OperationsSupported_len;
|
||||
uint16_t OperationsSupported[CONFIG_MTP_SUPP_OP_LEN];
|
||||
uint32_t EventsSupported_len;
|
||||
uint16_t EventsSupported[CONFIG_MTP_SUPP_EVENTS_LEN];
|
||||
uint32_t DevicePropertiesSupported_len;
|
||||
uint16_t DevicePropertiesSupported[CONFIG_MTP_SUPP_DEVICE_PROP_LEN];
|
||||
uint32_t CaptureFormats_len;
|
||||
uint16_t CaptureFormats[CONFIG_MTP_SUPP_CAPT_FORMAT_LEN];
|
||||
uint32_t ImageFormats_len;
|
||||
uint16_t ImageFormats[CONFIG_MTP_SUPP_IMG_FORMAT_LEN];
|
||||
uint8_t Manufacturer_len;
|
||||
uint16_t Manufacturer[CONFIG_MTP_MANUF_LEN];
|
||||
uint8_t Model_len;
|
||||
uint16_t Model[CONFIG_MTP_MODEL_LEN];
|
||||
uint8_t DeviceVersion_len;
|
||||
uint16_t DeviceVersion[CONFIG_MTP_DEVICE_VERSION_LEN];
|
||||
uint8_t SerialNumber_len;
|
||||
uint16_t SerialNumber[CONFIG_MTP_SERIAL_NBR_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_props_support {
|
||||
uint32_t ObjectPropCode_len;
|
||||
uint16_t ObjectPropCode[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_device_prop_desc {
|
||||
uint16_t DevicePropertyCode;
|
||||
uint16_t DataType;
|
||||
uint8_t GetSet;
|
||||
uint8_t DefaultValue_len;
|
||||
uint16_t DefaultValue[CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN];
|
||||
uint8_t CurrentValue_len;
|
||||
uint16_t CurrentValue[CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN];
|
||||
uint8_t FormFlag;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_storage_id {
|
||||
uint32_t StorageIDS_len;
|
||||
uint32_t StorageIDS[CONFIG_MTP_STORAGE_ID_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_storage_info {
|
||||
uint16_t StorageType;
|
||||
uint16_t FilesystemType;
|
||||
uint16_t AccessCapability;
|
||||
uint64_t MaxCapability;
|
||||
uint64_t FreeSpaceInBytes;
|
||||
uint32_t FreeSpaceInObjects;
|
||||
uint8_t StorageDescription;
|
||||
uint8_t VolumeLabel;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_handle {
|
||||
uint32_t ObjectHandle_len;
|
||||
uint32_t ObjectHandle[CONFIG_MTP_OBJECT_HANDLE_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_info {
|
||||
uint32_t Storage_id;
|
||||
uint16_t ObjectFormat;
|
||||
uint16_t ProtectionStatus;
|
||||
uint32_t ObjectCompressedSize;
|
||||
uint16_t ThumbFormat;
|
||||
uint32_t ThumbCompressedSize;
|
||||
uint32_t ThumbPixWidth;
|
||||
uint32_t ThumbPixHeight;
|
||||
uint32_t ImagePixWidth;
|
||||
uint32_t ImagePixHeight;
|
||||
uint32_t ImageBitDepth;
|
||||
uint32_t ParentObject;
|
||||
uint16_t AssociationType;
|
||||
uint32_t AssociationDesc;
|
||||
uint32_t SequenceNumber;
|
||||
uint8_t Filename_len;
|
||||
uint16_t Filename[255];
|
||||
uint32_t CaptureDate;
|
||||
uint32_t ModificationDate;
|
||||
uint8_t Keywords;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_desc {
|
||||
uint16_t ObjectPropertyCode;
|
||||
uint16_t DataType;
|
||||
uint8_t GetSet;
|
||||
uint8_t *DefValue;
|
||||
uint32_t GroupCode;
|
||||
uint8_t FormFlag;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_element {
|
||||
uint32_t ObjectHandle;
|
||||
uint16_t PropertyCode;
|
||||
uint16_t Datatype;
|
||||
uint8_t *propval;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_list {
|
||||
uint32_t Properties_len;
|
||||
struct mtp_object_prop_element Properties[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
|
||||
} __PACKED;
|
||||
|
||||
#endif /* USB_MTP_CONFIG_H */
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_mtp.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/mtp"
|
||||
|
||||
static int usbh_mtp_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_mtp *mtp_class = usb_malloc(sizeof(struct usbh_mtp));
|
||||
if (mtp_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc mtp_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mtp_class, 0, sizeof(struct usbh_mtp));
|
||||
mtp_class->hport = hport;
|
||||
mtp_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = mtp_class;
|
||||
|
||||
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&mtp_class->intin, hport, ep_desc);
|
||||
#endif
|
||||
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(&mtp_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&mtp_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register MTP Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_mtp_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_mtp *mtp_class = (struct usbh_mtp *)hport->config.intf[intf].priv;
|
||||
|
||||
if (mtp_class) {
|
||||
if (mtp_class->bulkin) {
|
||||
usbh_pipe_free(mtp_class->bulkin);
|
||||
}
|
||||
|
||||
if (mtp_class->bulkout) {
|
||||
usbh_pipe_free(mtp_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MTP Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
|
||||
memset(mtp_class, 0, sizeof(struct usbh_mtp));
|
||||
usb_free(mtp_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver mtp_class_driver = {
|
||||
.driver_name = "mtp",
|
||||
.connect = usbh_mtp_connect,
|
||||
.disconnect = usbh_mtp_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info mtp_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_MTP_CLASS,
|
||||
.subclass = USB_MTP_SUB_CLASS,
|
||||
.protocol = USB_MTP_PROTOCOL,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &mtp_class_driver
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_MTP_H
|
||||
#define USBH_MTP_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
struct usbh_mtp {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_MTP_H */
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_PRINTER_H
|
||||
#define USB_PRINTER_H
|
||||
|
||||
#define PRINTER_SUBCLASS 0x01U
|
||||
|
||||
#define PRINTER_REQUEST_GET_DEVICE_ID 0x00U
|
||||
#define PRINTER_REQUEST_GET_PORT_SATTUS 0x01U
|
||||
#define PRINTER_REQUEST_SOFT_RESET 0x02U
|
||||
|
||||
#define PRINTER_STATUS_NO_ERROR 0x00U
|
||||
#define PRINTER_STATUS_SELECTED 0x08U
|
||||
#define PRINTER_STATUS_PAPER_EMPTY 0x10U
|
||||
|
||||
#endif /* USB_PRINTER_H */
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_printer.h"
|
||||
|
||||
struct printer_cfg_priv {
|
||||
const uint8_t *device_id;
|
||||
uint8_t device_id_len;
|
||||
uint8_t port_status;
|
||||
} usbd_printer_cfg;
|
||||
|
||||
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("Printer Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
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;
|
||||
break;
|
||||
case PRINTER_REQUEST_GET_PORT_SATTUS:
|
||||
|
||||
break;
|
||||
case PRINTER_REQUEST_SOFT_RESET:
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Printer Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void printer_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len)
|
||||
{
|
||||
intf->class_interface_handler = printer_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
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;
|
||||
return intf;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_PRINTER_H
|
||||
#define USBD_PRINTER_H
|
||||
|
||||
#include "usb_printer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init printer interface driver */
|
||||
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_PRINTER_H */
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_printer.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/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;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_GET_DEVICE_ID;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 256;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||
}
|
||||
|
||||
static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_GET_PORT_SATTUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||
}
|
||||
|
||||
static int usbh_printer_soft_reset(struct usbh_printer *printer_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_SOFT_RESET;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
static int usbh_printer_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_printer *printer_class = usb_malloc(sizeof(struct usbh_printer));
|
||||
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;
|
||||
|
||||
hport->config.intf[intf].priv = printer_class;
|
||||
|
||||
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(&printer_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&printer_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
// uint8_t *device_id = usb_iomalloc(256);
|
||||
// ret = usbh_printer_get_device_id(printer_class, device_id);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_printer *printer_class = (struct usbh_printer *)hport->config.intf[intf].priv;
|
||||
|
||||
if (printer_class) {
|
||||
if (printer_class->bulkin) {
|
||||
usbh_pipe_free(printer_class->bulkin);
|
||||
}
|
||||
|
||||
if (printer_class->bulkout) {
|
||||
usbh_pipe_free(printer_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver printer_class_driver = {
|
||||
.driver_name = "printer",
|
||||
.connect = usbh_printer_connect,
|
||||
.disconnect = usbh_printer_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info printer_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_PRINTER,
|
||||
.subclass = PRINTER_SUBCLASS,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &printer_class_driver
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_PRINTER_H
|
||||
#define USBH_PRINTER_H
|
||||
|
||||
#include "usb_printer.h"
|
||||
|
||||
struct usbh_printer {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_PRINTER_H */
|
||||
@@ -28,12 +28,12 @@ static void xxx_notify_handler(uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf)
|
||||
{
|
||||
intf->class_interface_handler = xxx_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = xxx_notify_handler;
|
||||
|
||||
usbd_class_add_interface(devclass, intf);
|
||||
return intf;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -3,43 +3,47 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/xxx"
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CUSTOM_CLASS 1
|
||||
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 -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,25 +54,32 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;
|
||||
|
||||
if (xxx_class) {
|
||||
if (xxx_class->bulkin) {
|
||||
usbh_pipe_free(xxx_class->bulkin);
|
||||
if (xxx_class->xxxin) {
|
||||
usbh_kill_urb(&xxx_class->xxxin_urb);
|
||||
}
|
||||
|
||||
if (xxx_class->bulkout) {
|
||||
usbh_pipe_free(xxx_class->bulkout);
|
||||
if (xxx_class->xxxout) {
|
||||
usbh_kill_urb(&xxx_class->xxxout_urb);
|
||||
}
|
||||
|
||||
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",
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
|
||||
struct usbh_xxx {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *xxxin;
|
||||
struct usb_endpoint_descriptor *xxxout;
|
||||
struct usbh_urb xxxin_urb;
|
||||
struct usbh_urb xxxout_urb;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t intin; /* INTR IN endpoint */
|
||||
usbh_pipe_t intout; /* INTR OUT endpoint */
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
void usbh_xxx_run(struct usbh_xxx *xxx_class);
|
||||
void usbh_xxx_stop(struct usbh_xxx *xxx_class);
|
||||
|
||||
#endif
|
||||
596
class/vendor/asix.h
vendored
596
class/vendor/asix.h
vendored
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Change Logs
|
||||
* Date Author Notes
|
||||
* 2022-04-17 aozima the first version for CherryUSB.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USBNET_ASIX_H
|
||||
#define __LINUX_USBNET_ASIX_H
|
||||
|
||||
// #define __BIG_ENDIAN_BITFIELD
|
||||
#define __LITTLE_ENDIAN_BITFIELD
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
||||
#define KERNEL_VERSION(...) (0)
|
||||
#define LINUX_VERSION_CODE (1)
|
||||
|
||||
/*
|
||||
* Turn on this flag if the implementation of your USB host controller
|
||||
* cannot handle non-double word aligned buffer.
|
||||
* When turn on this flag, driver will fixup egress packet aligned on double
|
||||
* word boundary before deliver to USB host controller. And will Disable the
|
||||
* function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
|
||||
* double word alignment for ingress packets.
|
||||
*/
|
||||
#define AX_FORCE_BUFF_ALIGN 0
|
||||
|
||||
//#define RX_SKB_COPY
|
||||
|
||||
#define AX_MONITOR_MODE 0x01
|
||||
#define AX_MONITOR_LINK 0x02
|
||||
#define AX_MONITOR_MAGIC 0x04
|
||||
#define AX_MONITOR_HSFS 0x10
|
||||
|
||||
/* AX88172 Medium Status Register values */
|
||||
#define AX_MEDIUM_FULL_DUPLEX 0x02
|
||||
#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
|
||||
#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
|
||||
#define AX_MCAST_FILTER_SIZE 8
|
||||
#define AX_MAX_MCAST 64
|
||||
|
||||
#define AX_EEPROM_LEN 0x40
|
||||
|
||||
#define AX_SWRESET_CLEAR 0x00
|
||||
#define AX_SWRESET_RR 0x01
|
||||
#define AX_SWRESET_RT 0x02
|
||||
#define AX_SWRESET_PRTE 0x04
|
||||
#define AX_SWRESET_PRL 0x08
|
||||
#define AX_SWRESET_BZ 0x10
|
||||
#define AX_SWRESET_IPRL 0x20
|
||||
#define AX_SWRESET_IPPD 0x40
|
||||
#define AX_SWRESET_IPOSC 0x0080
|
||||
#define AX_SWRESET_IPPSL_0 0x0100
|
||||
#define AX_SWRESET_IPPSL_1 0x0200
|
||||
#define AX_SWRESET_IPCOPS 0x0400
|
||||
#define AX_SWRESET_IPCOPSC 0x0800
|
||||
#define AX_SWRESET_AUTODETACH 0x1000
|
||||
#define AX_SWRESET_WOLLP 0x8000
|
||||
|
||||
#define AX88772_IPG0_DEFAULT 0x15
|
||||
#define AX88772_IPG1_DEFAULT 0x0c
|
||||
#define AX88772_IPG2_DEFAULT 0x0E
|
||||
|
||||
#define AX88772A_IPG0_DEFAULT 0x15
|
||||
#define AX88772A_IPG1_DEFAULT 0x16
|
||||
#define AX88772A_IPG2_DEFAULT 0x1A
|
||||
|
||||
#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
|
||||
#define AX88772_MEDIUM_RESERVED 0x0004
|
||||
#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
|
||||
#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
|
||||
#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
|
||||
#define AX88772_MEDIUM_RX_ENABLE 0x0100
|
||||
#define AX88772_MEDIUM_100MB 0x0200
|
||||
#define AX88772_MEDIUM_DEFAULT \
|
||||
(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
|
||||
AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
|
||||
AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
|
||||
|
||||
#define AX_CMD_SET_SW_MII 0x06
|
||||
#define AX_CMD_READ_MII_REG 0x07
|
||||
#define AX_CMD_WRITE_MII_REG 0x08
|
||||
#define AX_CMD_READ_STATMNGSTS_REG 0x09
|
||||
#define AX_HOST_EN 0x01
|
||||
|
||||
#define AX_CMD_SET_HW_MII 0x0a
|
||||
#define AX_CMD_READ_EEPROM 0x0b
|
||||
#define AX_CMD_WRITE_EEPROM 0x0c
|
||||
#define AX_CMD_WRITE_EEPROM_EN 0x0d
|
||||
#define AX_CMD_WRITE_EEPROM_DIS 0x0e
|
||||
#define AX_CMD_WRITE_RX_CTL 0x10
|
||||
#define AX_CMD_READ_IPG012 0x11
|
||||
#define AX_CMD_WRITE_IPG0 0x12
|
||||
#define AX_CMD_WRITE_IPG1 0x13
|
||||
#define AX_CMD_WRITE_IPG2 0x14
|
||||
#define AX_CMD_WRITE_MULTI_FILTER 0x16
|
||||
#define AX_CMD_READ_NODE_ID 0x17
|
||||
#define AX_CMD_READ_PHY_ID 0x19
|
||||
#define AX_CMD_READ_MEDIUM_MODE 0x1a
|
||||
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
|
||||
#define AX_CMD_READ_MONITOR_MODE 0x1c
|
||||
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
|
||||
#define AX_CMD_WRITE_GPIOS 0x1f
|
||||
#define AX_CMD_SW_RESET 0x20
|
||||
#define AX_CMD_SW_PHY_STATUS 0x21
|
||||
#define AX_CMD_SW_PHY_SELECT 0x22
|
||||
#define AX_PHYSEL_PSEL (1 << 0)
|
||||
#define AX_PHYSEL_ASEL (1 << 1)
|
||||
#define AX_PHYSEL_SSMII (0 << 2)
|
||||
#define AX_PHYSEL_SSRMII (1 << 2)
|
||||
#define AX_PHYSEL_SSRRMII (3 << 2)
|
||||
#define AX_PHYSEL_SSEN (1 << 4)
|
||||
#define AX88772_CMD_READ_NODE_ID 0x13
|
||||
#define AX88772_CMD_WRITE_NODE_ID 0x14
|
||||
#define AX_CMD_READ_WKFARY 0x23
|
||||
#define AX_CMD_WRITE_WKFARY 0x24
|
||||
#define AX_CMD_READ_RXCOE_CTL 0x2b
|
||||
#define AX_CMD_WRITE_RXCOE_CTL 0x2c
|
||||
#define AX_CMD_READ_TXCOE_CTL 0x2d
|
||||
#define AX_CMD_WRITE_TXCOE_CTL 0x2e
|
||||
|
||||
#define REG_LENGTH 2
|
||||
#define PHY_ID_MASK 0x1f
|
||||
|
||||
#define AX_RXCOE_IPCE 0x0001
|
||||
#define AX_RXCOE_IPVE 0x0002
|
||||
#define AX_RXCOE_V6VE 0x0004
|
||||
#define AX_RXCOE_TCPE 0x0008
|
||||
#define AX_RXCOE_UDPE 0x0010
|
||||
#define AX_RXCOE_ICMP 0x0020
|
||||
#define AX_RXCOE_IGMP 0x0040
|
||||
#define AX_RXCOE_ICV6 0x0080
|
||||
#define AX_RXCOE_TCPV6 0x0100
|
||||
#define AX_RXCOE_UDPV6 0x0200
|
||||
#define AX_RXCOE_ICMV6 0x0400
|
||||
#define AX_RXCOE_IGMV6 0x0800
|
||||
#define AX_RXCOE_ICV6V6 0x1000
|
||||
#define AX_RXCOE_FOPC 0x8000
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||
AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
|
||||
AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
|
||||
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
|
||||
#else
|
||||
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||
AX_RXCOE_TCPE | AX_RXCOE_UDPE)
|
||||
#endif
|
||||
|
||||
#define AX_RXCOE_64TE 0x0100
|
||||
#define AX_RXCOE_PPPOE 0x0200
|
||||
#define AX_RXCOE_RPCE 0x8000
|
||||
|
||||
#define AX_TXCOE_IP 0x0001
|
||||
#define AX_TXCOE_TCP 0x0002
|
||||
#define AX_TXCOE_UDP 0x0004
|
||||
#define AX_TXCOE_ICMP 0x0008
|
||||
#define AX_TXCOE_IGMP 0x0010
|
||||
#define AX_TXCOE_ICV6 0x0020
|
||||
|
||||
#define AX_TXCOE_TCPV6 0x0100
|
||||
#define AX_TXCOE_UDPV6 0x0200
|
||||
#define AX_TXCOE_ICMV6 0x0400
|
||||
#define AX_TXCOE_IGMV6 0x0800
|
||||
#define AX_TXCOE_ICV6V6 0x1000
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
|
||||
AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
|
||||
#else
|
||||
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
|
||||
#endif
|
||||
|
||||
#define AX_TXCOE_64TE 0x0001
|
||||
#define AX_TXCOE_PPPE 0x0002
|
||||
|
||||
#define AX88772B_MAX_BULKIN_2K 0
|
||||
#define AX88772B_MAX_BULKIN_4K 1
|
||||
#define AX88772B_MAX_BULKIN_6K 2
|
||||
#define AX88772B_MAX_BULKIN_8K 3
|
||||
#define AX88772B_MAX_BULKIN_16K 4
|
||||
#define AX88772B_MAX_BULKIN_20K 5
|
||||
#define AX88772B_MAX_BULKIN_24K 6
|
||||
#define AX88772B_MAX_BULKIN_32K 7
|
||||
struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
|
||||
/* 2k */
|
||||
{2048, 0x8000, 0x8001},
|
||||
/* 4k */
|
||||
{4096, 0x8100, 0x8147},
|
||||
/* 6k */
|
||||
{6144, 0x8200, 0x81EB},
|
||||
/* 8k */
|
||||
{8192, 0x8300, 0x83D7},
|
||||
/* 16 */
|
||||
{16384, 0x8400, 0x851E},
|
||||
/* 20k */
|
||||
{20480, 0x8500, 0x8666},
|
||||
/* 24k */
|
||||
{24576, 0x8600, 0x87AE},
|
||||
/* 32k */
|
||||
{32768, 0x8700, 0x8A3D},
|
||||
};
|
||||
|
||||
|
||||
#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
|
||||
#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
|
||||
#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
|
||||
#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
|
||||
|
||||
#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
|
||||
#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
|
||||
#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
|
||||
#define AX_RX_CTL_AM 0x0010
|
||||
#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
|
||||
#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
|
||||
#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
|
||||
#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
|
||||
#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
|
||||
|
||||
#define AX_MONITOR_MODE 0x01
|
||||
#define AX_MONITOR_LINK 0x02
|
||||
#define AX_MONITOR_MAGIC 0x04
|
||||
#define AX_MONITOR_HSFS 0x10
|
||||
|
||||
#define AX_MCAST_FILTER_SIZE 8
|
||||
#define AX_MAX_MCAST 64
|
||||
#define AX_INTERRUPT_BUFSIZE 8
|
||||
|
||||
#define AX_EEPROM_LEN 0x40
|
||||
#define AX_EEPROM_MAGIC 0xdeadbeef
|
||||
#define EEPROMMASK 0x7f
|
||||
|
||||
/* GPIO REGISTER */
|
||||
#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
|
||||
#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
|
||||
#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
|
||||
#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
|
||||
#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
|
||||
#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
|
||||
#define AXGPIOS_RSE 0X80 /* 1 << 7 */
|
||||
|
||||
/* TX-header format */
|
||||
#define AX_TX_HDR_CPHI 0x4000
|
||||
#define AX_TX_HDR_DICF 0x8000
|
||||
|
||||
/* GMII register definitions */
|
||||
#define GMII_PHY_CONTROL 0x00 /* control reg */
|
||||
#define GMII_PHY_STATUS 0x01 /* status reg */
|
||||
#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
|
||||
#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
|
||||
#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
|
||||
#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
|
||||
#define GMII_PHY_ANER 0x06 /* AN expansion reg */
|
||||
#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
|
||||
#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
|
||||
|
||||
/* Bit definitions: GMII Control */
|
||||
#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
|
||||
#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
|
||||
#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
|
||||
#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
|
||||
#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
|
||||
#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
|
||||
#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
|
||||
#define GMII_CONTROL_POWER_DOWN 0x0800
|
||||
#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
|
||||
#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
|
||||
#define GMII_CONTROL_FULL_DUPLEX 0x0100
|
||||
|
||||
/* Bit definitions: GMII Status */
|
||||
#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
|
||||
#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
|
||||
#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
|
||||
#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
|
||||
#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
|
||||
#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
|
||||
#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
|
||||
#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
|
||||
#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
|
||||
#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
|
||||
#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
|
||||
|
||||
/* Bit definitions: Auto-Negotiation Advertisement */
|
||||
#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||
#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
|
||||
#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
|
||||
#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||
#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||
#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||
#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
|
||||
#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
|
||||
|
||||
/* Bit definitions: Auto-Negotiation Link Partner Ability */
|
||||
#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
|
||||
#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||
#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||
#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||
#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
|
||||
#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
|
||||
#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||
#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
|
||||
#define GMII_SELECTOR_8023 0x0001;
|
||||
|
||||
/* Bit definitions: 1000BaseT AUX Control */
|
||||
#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
|
||||
#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
|
||||
#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
|
||||
|
||||
/* Bit definitions: 1000BaseT AUX Status */
|
||||
#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
|
||||
#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
|
||||
|
||||
/* Cicada MII Registers */
|
||||
#define GMII_AUX_CTRL_STATUS 0x1C
|
||||
#define GMII_AUX_ANEG_CPLT 0x8000
|
||||
#define GMII_AUX_FDX 0x0020
|
||||
#define GMII_AUX_SPEED_1000 0x0010
|
||||
#define GMII_AUX_SPEED_100 0x0008
|
||||
|
||||
#ifndef ADVERTISE_PAUSE_CAP
|
||||
#define ADVERTISE_PAUSE_CAP 0x0400
|
||||
#endif
|
||||
|
||||
#ifndef MII_STAT1000
|
||||
#define MII_STAT1000 0x000A
|
||||
#endif
|
||||
|
||||
#ifndef LPA_1000FULL
|
||||
#define LPA_1000FULL 0x0800
|
||||
#endif
|
||||
|
||||
/* medium mode register */
|
||||
#define MEDIUM_GIGA_MODE 0x0001
|
||||
#define MEDIUM_FULL_DUPLEX_MODE 0x0002
|
||||
#define MEDIUM_TX_ABORT_MODE 0x0004
|
||||
#define MEDIUM_ENABLE_125MHZ 0x0008
|
||||
#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
|
||||
#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
|
||||
#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
|
||||
#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
|
||||
#define MEDIUM_ENABLE_RECEIVE 0x0100
|
||||
#define MEDIUM_MII_100M_MODE 0x0200
|
||||
#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
|
||||
#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
|
||||
#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
|
||||
|
||||
/* PHY mode */
|
||||
#define PHY_MODE_MARVELL 0
|
||||
#define PHY_MODE_CICADA_FAMILY 1
|
||||
#define PHY_MODE_CICADA_V1 1
|
||||
#define PHY_MODE_AGERE_FAMILY 2
|
||||
#define PHY_MODE_AGERE_V0 2
|
||||
#define PHY_MODE_CICADA_V2 5
|
||||
#define PHY_MODE_AGERE_V0_GMII 6
|
||||
#define PHY_MODE_CICADA_V2_ASIX 9
|
||||
#define PHY_MODE_VSC8601 10
|
||||
#define PHY_MODE_RTL8211CL 12
|
||||
#define PHY_MODE_RTL8211BN 13
|
||||
#define PHY_MODE_RTL8251CL 14
|
||||
#define PHY_MODE_ATTANSIC_V0 0x40
|
||||
#define PHY_MODE_ATTANSIC_FAMILY 0x40
|
||||
#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
|
||||
|
||||
/* */
|
||||
#define LED_MODE_MARVELL 0
|
||||
#define LED_MODE_CAMEO 1
|
||||
|
||||
#define MARVELL_LED_CTRL 0x18
|
||||
#define MARVELL_MANUAL_LED 0x19
|
||||
|
||||
#define PHY_IDENTIFIER 0x0002
|
||||
#define PHY_AGERE_IDENTIFIER 0x0282
|
||||
#define PHY_CICADA_IDENTIFIER 0x000f
|
||||
#define PHY_MARVELL_IDENTIFIER 0x0141
|
||||
|
||||
#define PHY_MARVELL_STATUS 0x001b
|
||||
#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
|
||||
|
||||
#define PHY_MARVELL_CTRL 0x0014
|
||||
#define MARVELL_CTRL_RXDELAY 0x0080
|
||||
#define MARVELL_CTRL_TXDELAY 0x0002
|
||||
|
||||
#define PHY_CICADA_EXTPAGE 0x001f
|
||||
#define CICADA_EXTPAGE_EN 0x0001
|
||||
#define CICADA_EXTPAGE_DIS 0x0000
|
||||
|
||||
/* External ethernet phy */
|
||||
#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
|
||||
#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
|
||||
|
||||
#define EXTPHY_BROADCOM_OUI 0x2B8094
|
||||
#define EXTPHY_BCM89811_MODEL 0x02
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
|
||||
{0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
|
||||
{0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
|
||||
{0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
|
||||
{0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
|
||||
{0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
|
||||
{0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
|
||||
{0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
|
||||
{0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||
{0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
|
||||
{0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||
{0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
|
||||
{0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
|
||||
{0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
|
||||
{0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
|
||||
{0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
|
||||
{0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
|
||||
{0x0002, 0x0012},
|
||||
};
|
||||
|
||||
struct ax88178_data {
|
||||
u16 EepromData;
|
||||
u16 MediaLink;
|
||||
int UseGpio0;
|
||||
int UseRgmii;
|
||||
u8 PhyMode;
|
||||
u8 LedMode;
|
||||
u8 BuffaloOld;
|
||||
};
|
||||
|
||||
enum watchdog_state {
|
||||
AX_NOP = 0,
|
||||
CHK_LINK, /* Routine A */
|
||||
CHK_CABLE_EXIST, /* Called by A */
|
||||
CHK_CABLE_EXIST_AGAIN, /* Routine B */
|
||||
PHY_POWER_UP, /* Called by B */
|
||||
PHY_POWER_UP_BH,
|
||||
PHY_POWER_DOWN,
|
||||
CHK_CABLE_STATUS, /* Routine C */
|
||||
WAIT_AUTONEG_COMPLETE,
|
||||
AX_SET_RX_CFG,
|
||||
AX_CHK_AUTODETACH,
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct ax88772b_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long time_to_chk;
|
||||
u16 psc;
|
||||
u8 pw_enabled;
|
||||
u8 Event;
|
||||
u8 checksum;
|
||||
u8 PhySelect:1;
|
||||
u8 OperationMode:1;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
|
||||
u32 ext_phy_oui;
|
||||
u8 ext_phy_model;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* define for MAC or PHY mode */
|
||||
#define OPERATION_MAC_MODE 0
|
||||
#define OPERATION_PHY_MODE 1
|
||||
|
||||
#if 0
|
||||
struct ax88772a_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long autoneg_start;
|
||||
#define AX88772B_WATCHDOG (6 * HZ)
|
||||
u8 Event;
|
||||
u8 TickToExpire;
|
||||
u8 DlyIndex;
|
||||
u8 DlySel;
|
||||
u16 EepromData;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
};
|
||||
|
||||
struct ax88772_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long autoneg_start;
|
||||
u8 Event;
|
||||
u8 TickToExpire;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define AX_RX_CHECKSUM 1
|
||||
#define AX_TX_CHECKSUM 2
|
||||
|
||||
#if 0
|
||||
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
|
||||
struct ax8817x_data {
|
||||
u8 multi_filter[AX_MCAST_FILTER_SIZE];
|
||||
int (*resume) (struct usb_interface *intf);
|
||||
int (*suspend) (struct usb_interface *intf,
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
|
||||
pm_message_t message);
|
||||
#else
|
||||
u32 message);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ax88172_int_data {
|
||||
u16 res1;
|
||||
#define AX_INT_PPLS_LINK (1 << 0)
|
||||
#define AX_INT_SPLS_LINK (1 << 1)
|
||||
#define AX_INT_CABOFF_UNPLUG (1 << 7)
|
||||
u8 link;
|
||||
u16 res2;
|
||||
u8 status;
|
||||
u16 res3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define AX_RXHDR_L4_ERR (1 << 8)
|
||||
#define AX_RXHDR_L3_ERR (1 << 9)
|
||||
|
||||
#define AX_RXHDR_L4_TYPE_UDP 1
|
||||
#define AX_RXHDR_L4_TYPE_ICMP 2
|
||||
#define AX_RXHDR_L4_TYPE_IGMP 3
|
||||
#define AX_RXHDR_L4_TYPE_TCP 4
|
||||
#define AX_RXHDR_L4_TYPE_TCMPV6 5
|
||||
#define AX_RXHDR_L4_TYPE_MASK 7
|
||||
|
||||
#define AX_RXHDR_L3_TYPE_IP 1
|
||||
#define AX_RXHDR_L3_TYPE_IPV6 2
|
||||
|
||||
struct ax88772b_rx_header {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
u16 len:11,
|
||||
res1:1,
|
||||
crc:1,
|
||||
mii:1,
|
||||
runt:1,
|
||||
mc_bc:1;
|
||||
|
||||
u16 len_bar:11,
|
||||
res2:5;
|
||||
|
||||
u8 vlan_ind:3,
|
||||
vlan_tag_striped:1,
|
||||
pri:3,
|
||||
res3:1;
|
||||
|
||||
u8 l4_csum_err:1,
|
||||
l3_csum_err:1,
|
||||
l4_type:3,
|
||||
l3_type:2,
|
||||
ce:1;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
u16 mc_bc:1,
|
||||
runt:1,
|
||||
mii:1,
|
||||
crc:1,
|
||||
res1:1,
|
||||
len:11;
|
||||
|
||||
u16 res2:5,
|
||||
len_bar:11;
|
||||
|
||||
u8 res3:1,
|
||||
pri:3,
|
||||
vlan_tag_striped:1,
|
||||
vlan_ind:3;
|
||||
|
||||
u8 ce:1,
|
||||
l3_type:2,
|
||||
l4_type:3,
|
||||
l3_csum_err:1,
|
||||
l4_csum_err:1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#endif /* __LINUX_USBNET_ASIX_H */
|
||||
|
||||
1208
class/vendor/axusbnet.c
vendored
1208
class/vendor/axusbnet.c
vendored
File diff suppressed because it is too large
Load Diff
30
class/vendor/axusbnet.h
vendored
30
class/vendor/axusbnet.h
vendored
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, aozima
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
* Change Logs
|
||||
* Date Author Notes
|
||||
* 2022-04-17 aozima the first version for CherryUSB.
|
||||
*/
|
||||
|
||||
#ifndef __USB_CLASHH_AXUSBNET_H__
|
||||
#define __USB_CLASHH_AXUSBNET_H__
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "asix.h"
|
||||
|
||||
struct usbh_axusbnet {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
|
||||
usbh_pipe_t int_notify; /* Notify endpoint */
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
uint32_t bulkin_buf[2048/sizeof(uint32_t)];
|
||||
};
|
||||
|
||||
#endif /* __USB_CLASHH_AXUSBNET_H__ */
|
||||
107
class/vendor/usbh_air724.c
vendored
107
class/vendor/usbh_air724.c
vendored
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/air724"
|
||||
|
||||
struct usbh_cdc_custom_air724 {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
};
|
||||
|
||||
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;
|
||||
struct usbh_urb *urb = &cdc_custom_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkout, 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;
|
||||
|
||||
if (intf != 3) {
|
||||
USB_LOG_WRN("ignore intf:%d\r\n", intf);
|
||||
return 0;
|
||||
}
|
||||
struct usbh_cdc_custom_air724 *cdc_custom_class = usb_malloc(sizeof(struct usbh_cdc_custom_air724));
|
||||
if (cdc_custom_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc cdc_custom_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(cdc_custom_class, 0, sizeof(struct usbh_cdc_custom_air724));
|
||||
cdc_custom_class->hport = hport;
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
hport->config.intf[intf].priv = cdc_custom_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_custom_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_custom_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_air724_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_custom_class_driver = {
|
||||
.driver_name = "cdc_acm",
|
||||
.connect = usbh_air724_connect,
|
||||
.disconnect = usbh_air724_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = 0xff,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x1782,
|
||||
.pid = 0x4e00,
|
||||
.class_driver = &cdc_custom_class_driver
|
||||
};
|
||||
@@ -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,77 +21,91 @@
|
||||
#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, 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;
|
||||
|
||||
memcpy(g_video_buf, buf, len);
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
usb_osal_msleep(5);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, g_video_buf);
|
||||
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,9 +140,10 @@ 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
|
||||
@@ -144,47 +161,81 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
if (altsetting > (video_class->num_of_intf_altsettings - 1)) {
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 1;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 2;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
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) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 6;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 7;
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
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;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(video_class->hport, 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;
|
||||
@@ -192,16 +243,20 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
video_class->isoin_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&video_class->isoin, video_class->hport, ep_desc);
|
||||
USBH_EP_INIT(video_class->isoin, ep_desc);
|
||||
} else {
|
||||
video_class->isoout_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc);
|
||||
USBH_EP_INIT(video_class->isoout, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
|
||||
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)
|
||||
@@ -214,12 +269,10 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
video_class->is_opened = false;
|
||||
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
video_class->isoin = NULL;
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
video_class->isoout = NULL;
|
||||
}
|
||||
|
||||
@@ -229,7 +282,7 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -292,14 +345,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;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
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,14 +452,10 @@ 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);
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
@@ -416,8 +463,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 +479,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 +487,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,17 +25,19 @@ 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);
|
||||
};
|
||||
|
||||
struct usbh_video {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* interface number */
|
||||
uint8_t data_intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t isoin; /* ISO IN endpoint */
|
||||
usbh_pipe_t isoout; /* ISO OUT endpoint */
|
||||
struct video_probe_and_commit_controls probe;
|
||||
struct video_probe_and_commit_controls commit;
|
||||
uint16_t isoin_mps;
|
||||
@@ -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,14 +38,15 @@ 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;
|
||||
|
||||
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];
|
||||
#if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
|
||||
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
|
||||
@@ -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,12 +507,12 @@ 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;
|
||||
}
|
||||
|
||||
if (g_rndis_tx_data_length > 0) {
|
||||
return -EBUSY;
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
|
||||
@@ -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,33 @@
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
|
||||
|
||||
/* eth rx size must be a multiple of 512 or 64 */
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE];
|
||||
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16];
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
// int ret;
|
||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
||||
|
||||
// usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
// ret = usbh_submit_urb(urb);
|
||||
// if (ret == 0) {
|
||||
// ret = urb->actual_length;
|
||||
// }
|
||||
// return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
@@ -33,13 +60,13 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_initialize_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -49,7 +76,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
@@ -79,15 +106,15 @@ 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);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_query_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -97,7 +124,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
@@ -131,15 +158,15 @@ 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);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_set_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -149,7 +176,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
@@ -158,32 +185,22 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
uint8_t data[32];
|
||||
uint32_t data_len;
|
||||
|
||||
usbh_bulk_urb_fill(urb, rndis_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, rndis_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
rndis_class->link_status = true;
|
||||
} else {
|
||||
rndis_class->link_status = false;
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
@@ -205,13 +222,13 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_keepalive_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_keepalive_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -221,7 +238,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
@@ -232,7 +249,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 +258,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));
|
||||
|
||||
@@ -257,17 +269,16 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
hport->config.intf[intf].priv = rndis_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
#ifdef CONFIG_USBHOST_RNDIS_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&rndis_class->intin, hport, ep_desc);
|
||||
#endif
|
||||
// ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
// USBH_EP_INIT(rndis_class->intin, ep_desc);
|
||||
|
||||
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(&rndis_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(rndis_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&rndis_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(rndis_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +374,15 @@ 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);
|
||||
USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
rndis_class->mac[0],
|
||||
rndis_class->mac[1],
|
||||
rndis_class->mac[2],
|
||||
rndis_class->mac[3],
|
||||
rndis_class->mac[4],
|
||||
rndis_class->mac[5]);
|
||||
|
||||
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);
|
||||
@@ -381,25 +400,153 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (rndis_class) {
|
||||
if (rndis_class->bulkin) {
|
||||
usbh_pipe_free(rndis_class->bulkin);
|
||||
usbh_kill_urb(&rndis_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (rndis_class->bulkout) {
|
||||
usbh_pipe_free(rndis_class->bulkout);
|
||||
usbh_kill_urb(&rndis_class->bulkout_urb);
|
||||
}
|
||||
|
||||
// if (rndis_class->intin) {
|
||||
// usbh_kill_urb(&rndis_class->intin_urb);
|
||||
// }
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_stop(rndis_class);
|
||||
}
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
usb_free(rndis_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_rndis_rx_thread(void *argument)
|
||||
{
|
||||
uint32_t g_rndis_rx_length;
|
||||
uint32_t pmg_offset;
|
||||
uint32_t payload_offset;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p, *q;
|
||||
rndis_data_packet_t *pmsg;
|
||||
rndis_data_packet_t temp;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
|
||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
g_rndis_class.link_status = false;
|
||||
if (usbh_find_class_instance("/dev/rndis") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_rndis_class.link_status == false) {
|
||||
ret = usbh_rndis_get_connect_status(&g_rndis_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
g_rndis_rx_length = 0;
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_rndis_rx_length = g_rndis_class.bulkin_urb.actual_length;
|
||||
pmg_offset = 0;
|
||||
while (g_rndis_rx_length > 0) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
|
||||
|
||||
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
|
||||
|
||||
/* Not word-aligned case */
|
||||
if (pmg_offset & 0x3) {
|
||||
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
|
||||
pmsg = &temp;
|
||||
}
|
||||
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
payload_offset = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset);
|
||||
memcpy(q->payload, src, q->len);
|
||||
payload_offset += q->len;
|
||||
}
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
pmg_offset += pmsg->MessageLength;
|
||||
g_rndis_rx_length -= pmsg->MessageLength;
|
||||
} else {
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
|
||||
}
|
||||
} else {
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("Error rndis packet message\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete rndis rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (g_rndis_class.link_status == false) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = p->tot_len;
|
||||
|
||||
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
|
||||
if (!(hdr->MessageLength % g_rndis_class.bulkout->wMaxPacketSize)) {
|
||||
hdr->MessageLength += 1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength);
|
||||
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,36 +8,45 @@
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
struct usbh_rndis {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
|
||||
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 */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
uint32_t request_id;
|
||||
|
||||
uint32_t link_speed;
|
||||
bool link_status;
|
||||
uint8_t mac[6];
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class);
|
||||
|
||||
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
void usbh_rndis_rx_thread(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,18 +12,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB Endpoint Configuration.
|
||||
*
|
||||
* Structure containing the USB endpoint configuration.
|
||||
*/
|
||||
struct usbd_endpoint_cfg {
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_mult; /* Endpoint additional transcations in micro frame */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief init device controller registers.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
@@ -61,7 +49,7 @@ uint8_t usbd_get_port_speed(const uint8_t port);
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
|
||||
|
||||
/**
|
||||
* @brief Disable the selected endpoint
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_GET_ENDPOINT_TYPE(x) ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT)
|
||||
|
||||
#define USB_ENDPOINT_SYNC_SHIFT 2
|
||||
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
@@ -245,6 +246,8 @@
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_GET_MAXPACKETSIZE(x) ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT)
|
||||
#define USB_GET_MULT(x) ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
|
||||
/* bDevCapabilityType in Device Capability Descriptor */
|
||||
#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
|
||||
@@ -484,13 +487,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 */
|
||||
|
||||
@@ -1,320 +1,24 @@
|
||||
/*
|
||||
* Apache NuttX
|
||||
* Copyright 2020 The Apache Software Foundation
|
||||
* Copyright (c) 2023, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __INCLUDE_ERRNO_H
|
||||
#define __INCLUDE_ERRNO_H
|
||||
#ifndef USB_ERRNO_H
|
||||
#define USB_ERRNO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
#define USB_ERR_NOMEM 1
|
||||
#define USB_ERR_INVAL 2
|
||||
#define USB_ERR_NODEV 3
|
||||
#define USB_ERR_NOTCONN 4
|
||||
#define USB_ERR_NOTSUPP 5
|
||||
#define USB_ERR_BUSY 6
|
||||
#define USB_ERR_RANGE 7
|
||||
#define USB_ERR_STALL 8
|
||||
#define USB_ERR_BABBLE 9
|
||||
#define USB_ERR_NAK 10
|
||||
#define USB_ERR_DT 11
|
||||
#define USB_ERR_IO 12
|
||||
#define USB_ERR_SHUTDOWN 13
|
||||
#define USB_ERR_TIMEOUT 14
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Convenience/compatibility definition. If the errno is accessed from the
|
||||
* internal OS code, then the OS code should use the set_errno() and
|
||||
* get_errno(). Currently, those are just placeholders but would be needed
|
||||
* in the KERNEL mode build in order to instantiate the process address
|
||||
* environment as necessary to access the TLS-based errno variable.
|
||||
*/
|
||||
|
||||
/* Definitions of error numbers and the string that would be
|
||||
* returned by strerror().
|
||||
*/
|
||||
#ifndef CONFIG_USB_ERROR_USE_SYSTEM
|
||||
|
||||
#define EPERM 1
|
||||
#define EPERM_STR "Operation not permitted"
|
||||
#define ENOENT 2
|
||||
#define ENOENT_STR "No such file or directory"
|
||||
#define ESRCH 3
|
||||
#define ESRCH_STR "No such process"
|
||||
#define EINTR 4
|
||||
#define EINTR_STR "Interrupted system call"
|
||||
#define EIO 5
|
||||
#define EIO_STR "I/O error"
|
||||
#define ENXIO 6
|
||||
#define ENXIO_STR "No such device or address"
|
||||
#define E2BIG 7
|
||||
#define E2BIG_STR "Arg list too long"
|
||||
#define ENOEXEC 8
|
||||
#define ENOEXEC_STR "Exec format error"
|
||||
#define EBADF 9
|
||||
#define EBADF_STR "Bad file number"
|
||||
#define ECHILD 10
|
||||
#define ECHILD_STR "No child processes"
|
||||
#define EAGAIN 11
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
#define EAGAIN_STR "Try again"
|
||||
#define ENOMEM 12
|
||||
#define ENOMEM_STR "Out of memory"
|
||||
#define EACCES 13
|
||||
#define EACCES_STR "Permission denied"
|
||||
#define EFAULT 14 /* Linux errno extension */
|
||||
#define EFAULT_STR "Bad address"
|
||||
#define ENOTBLK 15
|
||||
#define ENOTBLK_STR "Block device required"
|
||||
#define EBUSY 16
|
||||
#define EBUSY_STR "Device or resource busy"
|
||||
#define EEXIST 17
|
||||
#define EEXIST_STR "File exists"
|
||||
#define EXDEV 18
|
||||
#define EXDEV_STR "Cross-device link"
|
||||
#define ENODEV 19
|
||||
#define ENODEV_STR "No such device"
|
||||
#define ENOTDIR 20
|
||||
#define ENOTDIR_STR "Not a directory"
|
||||
#define EISDIR 21
|
||||
#define EISDIR_STR "Is a directory"
|
||||
#define EINVAL 22
|
||||
#define EINVAL_STR "Invalid argument"
|
||||
#define ENFILE 23
|
||||
#define ENFILE_STR "File table overflow"
|
||||
#define EMFILE 24
|
||||
#define EMFILE_STR "Too many open files"
|
||||
#define ENOTTY 25
|
||||
#define ENOTTY_STR "Not a typewriter"
|
||||
#define ETXTBSY 26
|
||||
#define ETXTBSY_STR "Text file busy"
|
||||
#define EFBIG 27
|
||||
#define EFBIG_STR "File too large"
|
||||
#define ENOSPC 28
|
||||
#define ENOSPC_STR "No space left on device"
|
||||
#define ESPIPE 29
|
||||
#define ESPIPE_STR "Illegal seek"
|
||||
#define EROFS 30
|
||||
#define EROFS_STR "Read-only file system"
|
||||
#define EMLINK 31
|
||||
#define EMLINK_STR "Too many links"
|
||||
#define EPIPE 32
|
||||
#define EPIPE_STR "Broken pipe"
|
||||
#define EDOM 33
|
||||
#define EDOM_STR "Math argument out of domain of func"
|
||||
#define ERANGE 34
|
||||
#define ERANGE_STR "Math result not representable"
|
||||
#define ENOMSG 35
|
||||
#define ENOMSG_STR "No message of desired type"
|
||||
#define EIDRM 36
|
||||
#define EIDRM_STR "Identifier removed"
|
||||
#define ECHRNG 37 /* Linux errno extension */
|
||||
#define ECHRNG_STR "Channel number out of range"
|
||||
#define EL2NSYNC 38 /* Linux errno extension */
|
||||
#define EL2NSYNC_STR "Level 2 not synchronized"
|
||||
#define EL3HLT 39 /* Linux errno extension */
|
||||
#define EL3HLT_STR "Level 3 halted"
|
||||
#define EL3RST 40 /* Linux errno extension */
|
||||
#define EL3RST_STR "Level 3 reset"
|
||||
#define ELNRNG 41 /* Linux errno extension */
|
||||
#define ELNRNG_STR "Link number out of range"
|
||||
#define EUNATCH 42 /* Linux errno extension */
|
||||
#define EUNATCH_STR "Protocol driver not attached"
|
||||
#define ENOCSI 43 /* Linux errno extension */
|
||||
#define ENOCSI_STR "No CSI structure available"
|
||||
#define EL2HLT 44 /* Linux errno extension */
|
||||
#define EL2HLT_STR "Level 2 halted"
|
||||
#define EDEADLK 45
|
||||
#define EDEADLK_STR "Resource deadlock would occur"
|
||||
#define ENOLCK 46
|
||||
#define ENOLCK_STR "No record locks available"
|
||||
|
||||
#define EBADE 50 /* Linux errno extension */
|
||||
#define EBADE_STR "Invalid exchange"
|
||||
#define EBADR 51 /* Linux errno extension */
|
||||
#define EBADR_STR "Invalid request descriptor"
|
||||
#define EXFULL 52 /* Linux errno extension */
|
||||
#define EXFULL_STR "Exchange full"
|
||||
#define ENOANO 53 /* Linux errno extension */
|
||||
#define ENOANO_STR "No anode"
|
||||
#define EBADRQC 54 /* Linux errno extension */
|
||||
#define EBADRQC_STR "Invalid request code"
|
||||
#define EBADSLT 55 /* Linux errno extension */
|
||||
#define EBADSLT_STR "Invalid slot"
|
||||
#define EDEADLOCK 56 /* Linux errno extension */
|
||||
#define EDEADLOCK_STR "File locking deadlock error"
|
||||
#define EBFONT 57 /* Linux errno extension */
|
||||
#define EBFONT_STR "Bad font file format"
|
||||
|
||||
#define ENOSTR 60
|
||||
#define ENOSTR_STR "Device not a stream"
|
||||
#define ENODATA 61
|
||||
#define ENODATA_STR "No data available"
|
||||
#define ETIME 62
|
||||
#define ETIME_STR "Timer expired"
|
||||
#define ENOSR 63
|
||||
#define ENOSR_STR "Out of streams resources"
|
||||
#define ENONET 64 /* Linux errno extension */
|
||||
#define ENONET_STR "Machine is not on the network"
|
||||
#define ENOPKG 65 /* Linux errno extension */
|
||||
#define ENOPKG_STR "Package not installed"
|
||||
#define EREMOTE 66 /* Linux errno extension */
|
||||
#define EREMOTE_STR "Object is remote"
|
||||
#define ENOLINK 67
|
||||
#define ENOLINK_STR "Link has been severed"
|
||||
#define EADV 68 /* Linux errno extension */
|
||||
#define EADV_STR "Advertise error"
|
||||
#define ESRMNT 69 /* Linux errno extension */
|
||||
#define ESRMNT_STR "Srmount error"
|
||||
#define ECOMM 70 /* Linux errno extension */
|
||||
#define ECOMM_STR "Communication error on send"
|
||||
#define EPROTO 71
|
||||
#define EPROTO_STR "Protocol error"
|
||||
|
||||
#define EMULTIHOP 74
|
||||
#define EMULTIHOP_STR "Multihop attempted"
|
||||
#define ELBIN 75 /* Linux errno extension */
|
||||
#define ELBIN_STR "Inode is remote"
|
||||
#define EDOTDOT 76 /* Linux errno extension */
|
||||
#define EDOTDOT_STR "RFS specific error"
|
||||
#define EBADMSG 77
|
||||
#define EBADMSG_STR "Not a data message"
|
||||
|
||||
#define EFTYPE 79
|
||||
#define EFTYPE_STR "Inappropriate file type or format"
|
||||
#define ENOTUNIQ 80 /* Linux errno extension */
|
||||
#define ENOTUNIQ_STR "Name not unique on network"
|
||||
#define EBADFD 81 /* Linux errno extension */
|
||||
#define EBADFD_STR "File descriptor in bad state"
|
||||
#define EREMCHG 82 /* Linux errno extension */
|
||||
#define EREMCHG_STR "Remote address changed"
|
||||
#define ELIBACC 83 /* Linux errno extension */
|
||||
#define ELIBACC_STR "Can not access a needed shared library"
|
||||
#define ELIBBAD 84 /* Linux errno extension */
|
||||
#define ELIBBAD_STR "Accessing a corrupted shared library"
|
||||
#define ELIBSCN 85 /* Linux errno extension */
|
||||
#define ELIBSCN_STR ".lib section in a.out corrupted"
|
||||
#define ELIBMAX 86 /* Linux errno extension */
|
||||
#define ELIBMAX_STR "Attempting to link in too many shared libraries"
|
||||
#define ELIBEXEC 87 /* Linux errno extension */
|
||||
#define ELIBEXEC_STR "Cannot exec a shared library directly"
|
||||
#define ENOSYS 88
|
||||
#define ENOSYS_STR "Function not implemented"
|
||||
#define ENMFILE 89 /* Cygwin */
|
||||
#define ENMFILE_STR "No more files"
|
||||
#define ENOTEMPTY 90
|
||||
#define ENOTEMPTY_STR "Directory not empty"
|
||||
#define ENAMETOOLONG 91
|
||||
#define ENAMETOOLONG_STR "File name too long"
|
||||
#define ELOOP 92
|
||||
#define ELOOP_STR "Too many symbolic links encountered"
|
||||
|
||||
#define EOPNOTSUPP 95
|
||||
#define EOPNOTSUPP_STR "Operation not supported on transport endpoint"
|
||||
#define EPFNOSUPPORT 96
|
||||
#define EPFNOSUPPORT_STR "Protocol family not supported"
|
||||
|
||||
#define ECONNRESET 104
|
||||
#define ECONNRESET_STR "Connection reset by peer"
|
||||
#define ENOBUFS 105
|
||||
#define ENOBUFS_STR "No buffer space available"
|
||||
#define EAFNOSUPPORT 106
|
||||
#define EAFNOSUPPORT_STR "Address family not supported by protocol"
|
||||
#define EPROTOTYPE 107
|
||||
#define EPROTOTYPE_STR "Protocol wrong type for socket"
|
||||
#define ENOTSOCK 108
|
||||
#define ENOTSOCK_STR "Socket operation on non-socket"
|
||||
#define ENOPROTOOPT 109
|
||||
#define ENOPROTOOPT_STR "Protocol not available"
|
||||
#define ESHUTDOWN 110 /* Linux errno extension */
|
||||
#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown"
|
||||
#define ECONNREFUSED 111
|
||||
#define ECONNREFUSED_STR "Connection refused"
|
||||
#define EADDRINUSE 112
|
||||
#define EADDRINUSE_STR "Address already in use"
|
||||
#define ECONNABORTED 113
|
||||
#define ECONNABORTED_STR "Software caused connection abort"
|
||||
#define ENETUNREACH 114
|
||||
#define ENETUNREACH_STR "Network is unreachable"
|
||||
#define ENETDOWN 115
|
||||
#define ENETDOWN_STR "Network is down"
|
||||
#define ETIMEDOUT 116
|
||||
#define ETIMEDOUT_STR "Connection timed out"
|
||||
#define EHOSTDOWN 117
|
||||
#define EHOSTDOWN_STR "Host is down"
|
||||
#define EHOSTUNREACH 118
|
||||
#define EHOSTUNREACH_STR "No route to host"
|
||||
#define EINPROGRESS 119
|
||||
#define EINPROGRESS_STR "Operation now in progress"
|
||||
#define EALREADY 120
|
||||
#define EALREADY_STR "Socket already connected"
|
||||
#define EDESTADDRREQ 121
|
||||
#define EDESTADDRREQ_STR "Destination address required"
|
||||
#define EMSGSIZE 122
|
||||
#define EMSGSIZE_STR "Message too long"
|
||||
#define EPROTONOSUPPORT 123
|
||||
#define EPROTONOSUPPORT_STR "Protocol not supported"
|
||||
#define ESOCKTNOSUPPORT 124 /* Linux errno extension */
|
||||
#define ESOCKTNOSUPPORT_STR "Socket type not supported"
|
||||
#define EADDRNOTAVAIL 125
|
||||
#define EADDRNOTAVAIL_STR "Cannot assign requested address"
|
||||
#define ENETRESET 126
|
||||
#define ENETRESET_STR "Network dropped connection because of reset"
|
||||
#define EISCONN 127
|
||||
#define EISCONN_STR "Transport endpoint is already connected"
|
||||
#define ENOTCONN 128
|
||||
#define ENOTCONN_STR "Transport endpoint is not connected"
|
||||
#define ETOOMANYREFS 129
|
||||
#define ETOOMANYREFS_STR "Too many references: cannot splice"
|
||||
#define EPROCLIM 130
|
||||
#define EPROCLIM_STR "Limit would be exceeded by attempted fork"
|
||||
#define EUSERS 131
|
||||
#define EUSERS_STR "Too many users"
|
||||
#define EDQUOT 132
|
||||
#define EDQUOT_STR "Quota exceeded"
|
||||
#define ESTALE 133
|
||||
#define ESTALE_STR "Stale NFS file handle"
|
||||
#define ENOTSUP 134
|
||||
#define ENOTSUP_STR "Not supported"
|
||||
#define ENOMEDIUM 135 /* Linux errno extension */
|
||||
#define ENOMEDIUM_STR "No medium found"
|
||||
#define ENOSHARE 136 /* Cygwin */
|
||||
#define ENOSHARE_STR "No such host or network path"
|
||||
#define ECASECLASH 137 /* Cygwin */
|
||||
#define ECASECLASH_STR "Filename exists with different case"
|
||||
#define EILSEQ 138
|
||||
#define EILSEQ_STR "Illegal byte sequence"
|
||||
#define EOVERFLOW 139
|
||||
#define EOVERFLOW_STR "Value too large for defined data type"
|
||||
#define ECANCELED 140
|
||||
#define ECANCELED_STR "Operation cancelled"
|
||||
#define ENOTRECOVERABLE 141
|
||||
#define ENOTRECOVERABLE_STR "State not recoverable"
|
||||
#define EOWNERDEAD 142
|
||||
#define EOWNERDEAD_STR "Previous owner died"
|
||||
#define ESTRPIPE 143 /* Linux errno extension */
|
||||
#define ESTRPIPE_STR "Streams pipe error"
|
||||
|
||||
#define __ELASTERROR 2000 /* Users can add values starting here */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the thread specific errno. */
|
||||
|
||||
int *__errno(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_ERRNO_H */
|
||||
#endif /* USB_ERRNO_H */
|
||||
|
||||
@@ -13,21 +13,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
|
||||
typedef void *usbh_pipe_t;
|
||||
|
||||
/**
|
||||
* @brief USB Endpoint Configuration.
|
||||
*
|
||||
* Structure containing the USB endpoint configuration.
|
||||
*/
|
||||
struct usbh_endpoint_cfg {
|
||||
struct usbh_hubport *hport;
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_interval; /* Endpoint interval */
|
||||
uint8_t mult; /* Endpoint additional transcation */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief USB Iso Configuration.
|
||||
@@ -47,7 +32,10 @@ struct usbh_iso_frame_packet {
|
||||
* Structure containing the USB Urb configuration.
|
||||
*/
|
||||
struct usbh_urb {
|
||||
usbh_pipe_t pipe;
|
||||
void *hcpriv;
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
uint8_t data_toggle;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
@@ -59,7 +47,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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -69,6 +61,13 @@ struct usbh_urb {
|
||||
*/
|
||||
int usb_hc_init(void);
|
||||
|
||||
/**
|
||||
* @brief usb host controller hardware deinit.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_hc_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Get frame number.
|
||||
*
|
||||
@@ -84,34 +83,6 @@ uint16_t usbh_get_frame_number(void);
|
||||
*/
|
||||
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief reconfig endpoint pipe.
|
||||
*
|
||||
* @param pipe A memory allocated for pipe.
|
||||
* @param dev_addr device address.
|
||||
* @param ep_mps endpoint max packet size.
|
||||
* @param mult endpoint additional transcation
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
/**
|
||||
* @brief Allocate pipe for endpoint
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to save the allocated pipe.
|
||||
* @param ep_cfg Describes the endpoint info to be allocated.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
|
||||
|
||||
/**
|
||||
* @brief Free a pipe in which saves endpoint info.
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_free(usbh_pipe_t pipe);
|
||||
|
||||
/**
|
||||
* @brief Submit a usb transfer request to an endpoint.
|
||||
*
|
||||
@@ -126,7 +97,7 @@ int usbh_submit_urb(struct usbh_urb *urb);
|
||||
/**
|
||||
* @brief Cancel a transfer request.
|
||||
*
|
||||
* This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
|
||||
* This function will call When calls usbh_submit_urb and return -USB_ERR_TIMEOUT or -USB_ERR_SHUTDOWN.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MEM_H
|
||||
#define USB_MEM_H
|
||||
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
#if (CONFIG_USB_ALIGN_SIZE > 4)
|
||||
static inline void *usb_iomalloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
void *align_ptr;
|
||||
int uintptr_size;
|
||||
size_t align_size;
|
||||
uint32_t align = CONFIG_USB_ALIGN_SIZE;
|
||||
|
||||
/* sizeof pointer */
|
||||
uintptr_size = sizeof(void *);
|
||||
uintptr_size -= 1;
|
||||
|
||||
/* align the alignment size to uintptr size byte */
|
||||
align = ((align + uintptr_size) & ~uintptr_size);
|
||||
|
||||
/* get total aligned size */
|
||||
align_size = ((size + uintptr_size) & ~uintptr_size) + align;
|
||||
/* allocate memory block from heap */
|
||||
ptr = usb_malloc(align_size);
|
||||
if (ptr != NULL) {
|
||||
/* the allocated memory block is aligned */
|
||||
if (((unsigned long)ptr & (align - 1)) == 0) {
|
||||
align_ptr = (void *)((unsigned long)ptr + align);
|
||||
} else {
|
||||
align_ptr = (void *)(((unsigned long)ptr + (align - 1)) & ~(align - 1));
|
||||
}
|
||||
|
||||
/* set the pointer before alignment pointer to the real pointer */
|
||||
*((unsigned long *)((unsigned long)align_ptr - sizeof(void *))) = (unsigned long)ptr;
|
||||
|
||||
ptr = align_ptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void usb_iofree(void *ptr)
|
||||
{
|
||||
void *real_ptr;
|
||||
|
||||
real_ptr = (void *)*(unsigned long *)((unsigned long)ptr - sizeof(void *));
|
||||
usb_free(real_ptr);
|
||||
}
|
||||
#else
|
||||
#define usb_iomalloc(size) usb_malloc(size)
|
||||
#define usb_iofree(ptr) usb_free(ptr)
|
||||
#endif
|
||||
|
||||
#endif /* USB_MEM_H */
|
||||
@@ -9,18 +9,25 @@
|
||||
#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);
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem);
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem);
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void);
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
|
||||
@@ -28,6 +35,7 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq);
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
||||
|
||||
@@ -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 */
|
||||
@@ -203,4 +203,6 @@
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
#endif /* USB_UTIL_H */
|
||||
|
||||
602
core/usbd_core.c
602
core/usbd_core.c
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@ extern "C" {
|
||||
#include "usb_errno.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_list.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_dc.h"
|
||||
|
||||
@@ -46,15 +45,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;
|
||||
@@ -65,21 +61,19 @@ struct usbd_interface {
|
||||
};
|
||||
|
||||
struct usb_descriptor {
|
||||
const uint8_t *device_descriptor;
|
||||
const uint8_t *fs_config_descriptor;
|
||||
const uint8_t *hs_config_descriptor;
|
||||
const uint8_t *device_quality_descriptor;
|
||||
const uint8_t *fs_other_speed_descriptor;
|
||||
const uint8_t *hs_other_speed_descriptor;
|
||||
const char **string_descriptor;
|
||||
struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
|
||||
struct usb_bos_descriptor *bos_descriptor;
|
||||
const uint8_t *(*device_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*config_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*device_quality_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*other_speed_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
||||
const struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
const struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
const struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
|
||||
const struct usb_bos_descriptor *bos_descriptor;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
void usbd_desc_register(struct usb_descriptor *desc);
|
||||
void usbd_desc_register(const struct usb_descriptor *desc);
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc);
|
||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
|
||||
@@ -91,7 +85,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);
|
||||
|
||||
|
||||
315
core/usbh_core.c
315
core/usbh_core.c
@@ -4,7 +4,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
struct usbh_class_info *usbh_class_info_table_begin = NULL;
|
||||
struct usbh_class_info *usbh_class_info_table_end = NULL;
|
||||
@@ -13,8 +12,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
|
||||
@@ -59,12 +58,12 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
|
||||
}
|
||||
|
||||
if (startaddr == devaddr) {
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
|
||||
static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
|
||||
{
|
||||
int index;
|
||||
int bitno;
|
||||
@@ -127,10 +126,10 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device
|
||||
{
|
||||
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
|
||||
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else {
|
||||
if (length <= 8) {
|
||||
return 0;
|
||||
@@ -183,10 +182,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
|
||||
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
|
||||
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
|
||||
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else {
|
||||
if (length <= USB_SIZEOF_CONFIG_DESC) {
|
||||
return 0;
|
||||
@@ -228,15 +227,15 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
cur_ep = 0;
|
||||
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
|
||||
USB_LOG_ERR("Interface num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
|
||||
USB_LOG_ERR("Interface altsetting num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
|
||||
USB_LOG_ERR("Endpoint num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
#if 0
|
||||
USB_LOG_DBG("Interface Descriptor:\r\n");
|
||||
@@ -270,23 +269,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");
|
||||
@@ -317,25 +299,25 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport)
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
|
||||
USB_LOG_RAW("Interface Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("bAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("bNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("bInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("bInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("bInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("iInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
USB_LOG_RAW("\tInterface Descriptor:\r\n");
|
||||
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
|
||||
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
|
||||
USB_LOG_RAW("Endpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("wMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("bInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,55 +339,64 @@ static int usbh_get_default_mps(int speed)
|
||||
}
|
||||
}
|
||||
|
||||
int usbh_hport_activate_ep0(struct usbh_hubport *hport)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep0_cfg = { 0 };
|
||||
|
||||
ep0_cfg.ep_addr = 0x00;
|
||||
ep0_cfg.ep_interval = 0x00;
|
||||
ep0_cfg.ep_mps = usbh_get_default_mps(hport->speed);
|
||||
ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep0_cfg.hport = hport;
|
||||
|
||||
usbh_pipe_alloc(&hport->ep0, &ep0_cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hport_deactivate_ep0(struct usbh_hubport *hport)
|
||||
int usbh_free_devaddr(struct usbh_hubport *hport)
|
||||
{
|
||||
#ifndef CONFIG_USBHOST_XHCI
|
||||
if (hport->dev_addr > 0) {
|
||||
usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
|
||||
__usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
|
||||
}
|
||||
#endif
|
||||
if (hport->ep0) {
|
||||
usbh_pipe_free(hport->ep0);
|
||||
}
|
||||
|
||||
hport->ep0 = NULL;
|
||||
hport->dev_addr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc)
|
||||
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
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;
|
||||
|
||||
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 & USB_MAXPACKETSIZE_MASK;
|
||||
ep_cfg.ep_interval = ep_desc->bInterval;
|
||||
ep_cfg.mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
ep_cfg.hport = hport;
|
||||
/* 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;
|
||||
|
||||
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
ep_cfg.ep_addr,
|
||||
ep_desc->bmAttributes,
|
||||
ep_cfg.ep_mps,
|
||||
ep_cfg.ep_interval,
|
||||
ep_cfg.mult);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return usbh_pipe_alloc(pipe, &ep_cfg);
|
||||
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 = altsetting;
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_enumerate(struct usbh_hubport *hport)
|
||||
@@ -413,12 +404,25 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
struct usb_interface_descriptor *intf_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usb_device_descriptor *dev_desc;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
int dev_addr;
|
||||
uint16_t ep_mps;
|
||||
int ret;
|
||||
|
||||
hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1];
|
||||
setup = hport->setup;
|
||||
ep = &hport->ep0;
|
||||
|
||||
/* Config EP0 mps from speed */
|
||||
ep->bEndpointAddress = 0x00;
|
||||
ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
|
||||
ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
|
||||
ep->bInterval = 0;
|
||||
ep->bLength = 7;
|
||||
|
||||
/* Configure EP0 with zero address */
|
||||
hport->dev_addr = 0;
|
||||
|
||||
/* Read the first 8 bytes of the device descriptor */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
@@ -427,7 +431,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 8;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -448,7 +452,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
dev_desc->bDeviceProtocol, ep_mps);
|
||||
|
||||
/* Reconfigure EP0 with the correct maximum packet size */
|
||||
usbh_ep_pipe_reconfigure(hport->ep0, 0, ep_mps, 0);
|
||||
ep->wMaxPacketSize = ep_mps;
|
||||
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
|
||||
@@ -475,7 +479,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -484,12 +488,9 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
/* Wait device set address completely */
|
||||
usb_osal_msleep(2);
|
||||
|
||||
/* Assign the function address to the port */
|
||||
/*Reconfigure EP0 with the correct address */
|
||||
hport->dev_addr = dev_addr;
|
||||
|
||||
/* And reconfigure EP0 with the correct address */
|
||||
usbh_ep_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, 0);
|
||||
|
||||
/* Read the full device descriptor */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
@@ -497,7 +498,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_DEVICE_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -516,7 +517,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_CONFIG_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -533,7 +534,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = wTotalLength;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -547,56 +548,43 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces);
|
||||
hport->raw_config_desc = usb_malloc(wTotalLength);
|
||||
if (hport->raw_config_desc == NULL) {
|
||||
ret = -ENOMEM;
|
||||
ret = -USB_ERR_NOMEM;
|
||||
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
||||
goto errout;
|
||||
}
|
||||
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;
|
||||
@@ -605,12 +593,25 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
|
||||
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,46 +640,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;
|
||||
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) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
||||
return hport->config.intf[itf].priv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int usbh_initialize(void)
|
||||
{
|
||||
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
|
||||
@@ -705,24 +666,52 @@ int usbh_initialize(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
int usbh_deinitialize(void)
|
||||
{
|
||||
return usbh_hub_deinitialize();
|
||||
}
|
||||
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
int ret;
|
||||
|
||||
urb = usb_malloc(sizeof(struct usbh_urb));
|
||||
urb = &hport->ep0_urb;
|
||||
|
||||
usb_osal_mutex_take(hport->mutex);
|
||||
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
|
||||
|
||||
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
usb_free(urb);
|
||||
|
||||
usb_osal_mutex_give(hport->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *usbh_find_class_instance(const char *devname)
|
||||
{
|
||||
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) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
||||
return hport->config.intf[itf].priv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lsusb(int argc, char **argv)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
|
||||
167
core/usbh_core.h
167
core/usbh_core.h
@@ -16,11 +16,10 @@
|
||||
#include "usb_errno.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_list.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_hc.h"
|
||||
#include "usb_osal.h"
|
||||
#include "usb_hub.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -32,8 +31,8 @@ extern "C" {
|
||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
|
||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
@@ -44,57 +43,16 @@ extern "C" {
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#endif
|
||||
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
#define USBH_EP_INIT(ep, ep_desc) \
|
||||
do { \
|
||||
ep = ep_desc; \
|
||||
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \
|
||||
ep_desc->bEndpointAddress, \
|
||||
USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \
|
||||
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
|
||||
ep_desc->bInterval, \
|
||||
USB_GET_MULT(ep_desc->bmAttributes)); \
|
||||
} while (0)
|
||||
|
||||
struct usbh_class_info {
|
||||
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
|
||||
@@ -140,7 +98,6 @@ struct usbh_hubport {
|
||||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
usbh_pipe_t ep0; /* control ep pipe info */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
@@ -152,6 +109,9 @@ struct usbh_hubport {
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
struct usbh_urb ep0_urb;
|
||||
usb_osal_mutex_t mutex;
|
||||
};
|
||||
|
||||
struct usbh_hub {
|
||||
@@ -160,15 +120,70 @@ struct usbh_hub {
|
||||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
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;
|
||||
struct usb_endpoint_descriptor *intin;
|
||||
struct usbh_urb intin_urb;
|
||||
uint8_t *int_buffer;
|
||||
};
|
||||
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = &hport->ep0;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_endpoint_descriptor *ep,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = ep;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_endpoint_descriptor *ep,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = ep;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Submit an control transfer to an endpoint.
|
||||
@@ -180,10 +195,38 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
|
||||
* @param buffer buffer used for sending the request and for returning any responses.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, 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);
|
||||
int usbh_deinitialize(void);
|
||||
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,151 @@
|
||||
/*!< 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
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
static const uint8_t device_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
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, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00)
|
||||
};
|
||||
|
||||
static const uint8_t device_quality_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x02,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const uint8_t string0_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
static const uint8_t string1_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// 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 */
|
||||
};
|
||||
|
||||
static const uint8_t string2_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// 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 */
|
||||
'C', 0x00, /* wcChar10 */
|
||||
'-', 0x00, /* wcChar11 */
|
||||
'M', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
};
|
||||
|
||||
static const uint8_t string3_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// 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 */
|
||||
};
|
||||
|
||||
static const uint8_t *string_descriptors[4] = { string0_descriptor, string1_descriptor, string2_descriptor, string3_descriptor };
|
||||
|
||||
static const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return config_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_quality_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *string_descriptor_callback(uint8_t speed, uint8_t index)
|
||||
{
|
||||
if (index > 3) {
|
||||
return NULL;
|
||||
}
|
||||
return string_descriptors[index];
|
||||
}
|
||||
|
||||
const struct usb_descriptor cdc_msc_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback
|
||||
};
|
||||
#else
|
||||
/*!< 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
|
||||
///////////////////////////////////////
|
||||
@@ -97,6 +236,7 @@ static const uint8_t cdc_msc_descriptor[] = {
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||
@@ -109,10 +249,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)
|
||||
@@ -151,7 +312,11 @@ struct usbd_interface intf2;
|
||||
|
||||
void cdc_acm_msc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
usbd_desc_register(&cdc_msc_descriptor);
|
||||
#else
|
||||
usbd_desc_register(cdc_msc_descriptor);
|
||||
#endif
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
||||
usbd_add_endpoint(&cdc_out_ep);
|
||||
|
||||
@@ -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
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
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)
|
||||
|
||||
674
demo/usb_host.c
674
demo/usb_host.c
@@ -12,12 +12,17 @@
|
||||
#define TEST_USBH_AUDIO 0
|
||||
#define TEST_USBH_VIDEO 0
|
||||
|
||||
#if __has_include("lwip/pbuf.h")
|
||||
#define TEST_USBH_CDC_ECM 1
|
||||
#define TEST_USBH_RNDIS 1
|
||||
#else
|
||||
#define TEST_USBH_CDC_ECM 0
|
||||
#define TEST_USBH_RNDIS 0
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ACM
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
|
||||
|
||||
struct usbh_urb cdc_bulkin_urb;
|
||||
struct usbh_urb cdc_bulkout_urb;
|
||||
|
||||
void usbh_cdc_acm_callback(void *arg, int nbytes)
|
||||
{
|
||||
//struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
|
||||
@@ -35,74 +40,53 @@ static void usbh_cdc_acm_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_cdc_acm *cdc_acm_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
|
||||
if (cdc_acm_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/ttyACM0\r\n");
|
||||
usb_osal_msleep(1000);
|
||||
continue;
|
||||
}
|
||||
memset(cdc_buffer, 0, 512);
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("recv over:%d\r\n", cdc_bulkin_urb.actual_length);
|
||||
for (size_t i = 0; i < cdc_bulkin_urb.actual_length; i++) {
|
||||
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_RAW("\r\n");
|
||||
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||
|
||||
memcpy(cdc_buffer, data1, 8);
|
||||
usbh_bulk_urb_fill(&cdc_bulkout_urb, cdc_acm_class->bulkout, cdc_buffer, 8, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_bulkout_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", cdc_bulkout_urb.actual_length);
|
||||
}
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, usbh_cdc_acm_callback, cdc_acm_class);
|
||||
ret = usbh_submit_urb(&cdc_bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
}
|
||||
|
||||
while (1) {
|
||||
cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
|
||||
if (cdc_acm_class == NULL) {
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(1000);
|
||||
}
|
||||
// clang-format on
|
||||
while ((cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
memset(cdc_buffer, 0, 512);
|
||||
|
||||
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||
|
||||
memcpy(cdc_buffer, data1, 10);
|
||||
usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, cdc_buffer, 10, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_acm_class->bulkout_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||
goto find_class;
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", cdc_acm_class->bulkout_urb.actual_length);
|
||||
}
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_acm_class->bulkin_urb, cdc_acm_class->hport, cdc_acm_class->bulkin, cdc_buffer, cdc_acm_class->bulkin->wMaxPacketSize, 3000, usbh_cdc_acm_callback, cdc_acm_class);
|
||||
ret = usbh_submit_urb(&cdc_acm_class->bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_HID
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_buffer[128];
|
||||
|
||||
struct usbh_urb hid_intin_urb;
|
||||
|
||||
void usbh_hid_callback(void *arg, int nbytes)
|
||||
{
|
||||
//struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
USB_LOG_RAW("0x%02x ", hid_buffer[i]);
|
||||
}
|
||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||
usbh_submit_urb(&hid_intin_urb);
|
||||
usbh_submit_urb(&hid_class->intin_urb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,31 +95,22 @@ static void usbh_hid_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_hid *hid_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
|
||||
if (hid_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/input0\r\n");
|
||||
usb_osal_msleep(1500);
|
||||
continue;
|
||||
}
|
||||
usbh_int_urb_fill(&hid_intin_urb, hid_class->intin, hid_buffer, 8, 0, usbh_hid_callback, hid_class);
|
||||
ret = usbh_submit_urb(&hid_intin_urb);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(1500);
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
|
||||
if (hid_class == NULL) {
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(1500);
|
||||
}
|
||||
// clang-format on
|
||||
while ((hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_buffer, hid_class->intin->wMaxPacketSize, 0, usbh_hid_callback, hid_class);
|
||||
ret = usbh_submit_urb(&hid_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -171,7 +146,7 @@ int usb_msc_fatfs_test()
|
||||
if (res_sd == FR_OK) {
|
||||
res_sd = f_write(&fnew, read_write_buffer, sizeof(read_write_buffer), &fnum);
|
||||
if (res_sd == FR_OK) {
|
||||
USB_LOG_RAW("write success, write len:%d\n", fnum);
|
||||
USB_LOG_RAW("write success, write len:%d\n", fnum);
|
||||
} else {
|
||||
USB_LOG_RAW("write fail\r\n");
|
||||
goto unmount;
|
||||
@@ -187,7 +162,7 @@ int usb_msc_fatfs_test()
|
||||
if (res_sd == FR_OK) {
|
||||
res_sd = f_read(&fnew, read_write_buffer, sizeof(read_write_buffer), &fnum);
|
||||
if (res_sd == FR_OK) {
|
||||
USB_LOG_RAW("read success, read len:%d\n", fnum);
|
||||
USB_LOG_RAW("read success, read len:%d\n", fnum);
|
||||
} else {
|
||||
USB_LOG_RAW("read fail\r\n");
|
||||
goto unmount;
|
||||
@@ -212,50 +187,494 @@ static void usbh_msc_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_msc *msc_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/sda\r\n");
|
||||
usb_osal_msleep(2000);
|
||||
continue;
|
||||
}
|
||||
// clang-format on
|
||||
while ((msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* get the partition table */
|
||||
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||
usb_osal_msleep(2000);
|
||||
goto find_class;
|
||||
/* get the partition table */
|
||||
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||
goto find_class;
|
||||
}
|
||||
for (uint32_t i = 0; i < 512; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
for (uint32_t i = 0; i < 512; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_MSC_FATFS
|
||||
usb_msc_fatfs_test();
|
||||
usb_msc_fatfs_test();
|
||||
#endif
|
||||
while (1) {
|
||||
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
|
||||
if (msc_class == NULL) {
|
||||
goto find_class;
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#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) {
|
||||
}
|
||||
usb_osal_msleep(2000);
|
||||
}
|
||||
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 || TEST_USBH_RNDIS
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#if LWIP_DHCP
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/prot/dhcp.h"
|
||||
#endif
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
|
||||
#ifndef RT_USING_TIMER_SOFT
|
||||
#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <netif/ethernetif.h>
|
||||
#include <netdev.h>
|
||||
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#include "timers.h"
|
||||
|
||||
TimerHandle_t dhcp_handle1;
|
||||
TimerHandle_t dhcp_handle2;
|
||||
|
||||
static void dhcp_timeout(TimerHandle_t xTimer)
|
||||
{
|
||||
struct netif *netif = (struct netif *)pvTimerGetTimerID(xTimer);
|
||||
struct dhcp *dhcp;
|
||||
|
||||
if (netif_is_up(netif)) {
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
|
||||
if (dhcp && (dhcp->state == DHCP_STATE_BOUND)) {
|
||||
USB_LOG_INFO("IPv4 Address : %s\r\n", ipaddr_ntoa(&netif->ip_addr));
|
||||
USB_LOG_INFO("IPv4 Subnet mask : %s\r\n", ipaddr_ntoa(&netif->netmask));
|
||||
USB_LOG_INFO("IPv4 Gateway : %s\r\n\r\n", ipaddr_ntoa(&netif->gw));
|
||||
|
||||
xTimerStop(xTimer, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ECM
|
||||
#include "usbh_cdc_ecm.h"
|
||||
|
||||
struct netif g_cdc_ecm_netif;
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
static struct eth_device cdc_ecm_dev;
|
||||
|
||||
static rt_err_t rt_usbh_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)dev->user_data;
|
||||
|
||||
switch (cmd) {
|
||||
case NIOCTL_GADDR:
|
||||
|
||||
/* get mac address */
|
||||
if (args)
|
||||
rt_memcpy(args, cdc_ecm_class->mac, 6);
|
||||
else
|
||||
return -RT_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||
{
|
||||
return usbh_cdc_ecm_linkoutput(NULL, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
struct netdev *netdev;
|
||||
|
||||
memset(&cdc_ecm_dev, 0, sizeof(struct eth_device));
|
||||
|
||||
cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
|
||||
cdc_ecm_dev.eth_rx = NULL;
|
||||
cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
|
||||
cdc_ecm_dev.parent.user_data = cdc_ecm_class;
|
||||
|
||||
eth_device_init(&cdc_ecm_dev, "u0");
|
||||
eth_device_linkchange(&cdc_ecm_dev, RT_TRUE);
|
||||
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, cdc_ecm_dev.netif);
|
||||
#else
|
||||
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)) {
|
||||
}
|
||||
|
||||
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||
if (dhcp_handle1 == NULL) {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, netif);
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
xTimerStart(dhcp_handle1, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
eth_device_deinit(&cdc_ecm_dev);
|
||||
#else
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_RNDIS
|
||||
#include "usbh_rndis.h"
|
||||
|
||||
struct netif g_rndis_netif;
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
|
||||
static struct eth_device rndis_dev;
|
||||
|
||||
static rt_timer_t keep_timer = RT_NULL;
|
||||
|
||||
static void rndis_dev_keepalive_timeout(void *parameter)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
|
||||
usbh_rndis_keepalive(rndis_class);
|
||||
}
|
||||
|
||||
static void timer_init(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
keep_timer = rt_timer_create("keep",
|
||||
rndis_dev_keepalive_timeout,
|
||||
rndis_class,
|
||||
5000,
|
||||
RT_TIMER_FLAG_PERIODIC |
|
||||
RT_TIMER_FLAG_SOFT_TIMER);
|
||||
|
||||
rt_timer_start(keep_timer);
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
|
||||
|
||||
switch (cmd) {
|
||||
case NIOCTL_GADDR:
|
||||
|
||||
/* get mac address */
|
||||
if (args)
|
||||
rt_memcpy(args, rndis_class->mac, 6);
|
||||
else
|
||||
return -RT_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||
{
|
||||
return usbh_rndis_linkoutput(NULL, p);
|
||||
}
|
||||
|
||||
#else
|
||||
TimerHandle_t timer_handle;
|
||||
|
||||
static void rndis_dev_keepalive_timeout(TimerHandle_t xTimer)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)pvTimerGetTimerID(xTimer);
|
||||
usbh_rndis_keepalive(rndis_class);
|
||||
}
|
||||
|
||||
void timer_init(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
timer_handle = xTimerCreate((const char *)NULL, (TickType_t)5000, (UBaseType_t)pdTRUE, (void *const)rndis_class, (TimerCallbackFunction_t)rndis_dev_keepalive_timeout);
|
||||
if (NULL != timer_handle) {
|
||||
xTimerStart(timer_handle, 0);
|
||||
} else {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static err_t usbh_rndis_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_rndis_linkoutput;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
struct netdev *netdev;
|
||||
|
||||
memset(&rndis_dev, 0, sizeof(struct eth_device));
|
||||
|
||||
rndis_dev.parent.control = rt_usbh_rndis_control;
|
||||
rndis_dev.eth_rx = NULL;
|
||||
rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
|
||||
rndis_dev.parent.user_data = rndis_class;
|
||||
|
||||
eth_device_init(&rndis_dev, "u1");
|
||||
eth_device_linkchange(&rndis_dev, RT_TRUE);
|
||||
|
||||
usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, rndis_dev.netif);
|
||||
timer_init(rndis_class);
|
||||
#else
|
||||
struct netif *netif = &g_rndis_netif;
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, rndis_class->mac, 6);
|
||||
|
||||
IP4_ADDR(&rndis_class->ipaddr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&rndis_class->netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&rndis_class->gateway, 0, 0, 0, 0);
|
||||
|
||||
netif = netif_add(netif, &rndis_class->ipaddr, &rndis_class->netmask, &rndis_class->gateway, NULL, usbh_rndis_if_init, tcpip_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
dhcp_handle2 = xTimerCreate((const char *)"dhcp2", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||
if (dhcp_handle2 == NULL) {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, netif);
|
||||
timer_init(rndis_class);
|
||||
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
xTimerStart(dhcp_handle2, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
eth_device_deinit(&rndis_dev);
|
||||
rt_timer_stop(keep_timer);
|
||||
rt_timer_delete(keep_timer);
|
||||
#else
|
||||
struct netif *netif = &g_rndis_netif;
|
||||
#if LWIP_DHCP
|
||||
dhcp_stop(netif);
|
||||
dhcp_cleanup(netif);
|
||||
#endif
|
||||
netif_set_down(netif);
|
||||
netif_remove(netif);
|
||||
xTimerStop(timer_handle, 0);
|
||||
xTimerDelete(timer_handle, 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
#if TEST_USBH_CDC_ACM
|
||||
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
@@ -264,22 +683,34 @@ void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
#if TEST_USBH_HID
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef __RTTHREAD__
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
#if TEST_USBH_MSC
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbh_audio_run(struct usbh_audio *audio_class)
|
||||
{
|
||||
#if TEST_USBH_AUDIO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_audio", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_audio_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
@@ -288,6 +719,10 @@ void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
|
||||
void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
#if TEST_USBH_VIDEO
|
||||
#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
|
||||
}
|
||||
|
||||
void usbh_video_stop(struct usbh_video *video_class)
|
||||
@@ -296,21 +731,12 @@ void usbh_video_stop(struct usbh_video *video_class)
|
||||
|
||||
void usbh_class_test(void)
|
||||
{
|
||||
#if TEST_USBH_CDC_ACM
|
||||
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, NULL);
|
||||
#ifdef __RTTHREAD__
|
||||
/* do nothing */
|
||||
#else
|
||||
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
|
||||
/* Initialize the LwIP stack */
|
||||
tcpip_init(NULL, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_HID
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_MSC
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_AUDIO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_audio", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_audio_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_VIDEO
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
1
docs/assets/CherryUSB.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
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,151 @@ 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
|
||||
|
||||
CONFIG_USBHOST_PSC_PRIO
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
主机插拔线程的优先级,默认是 0,数值越小,优先级越高
|
||||
|
||||
CONFIG_USBHOST_PSC_STACKSIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
主机插拔线程的堆栈大小,默认 2K 字节
|
||||
|
||||
CONFIG_USBHOST_REQUEST_BUFFER_LEN
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制传输能够接收或者发送的最大长度
|
||||
|
||||
CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
控制传输发送或者接收的超时时间,默认 1s
|
||||
|
||||
CONFIG_USBHOST_MSC_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
MSC 读写传输的超时时间,默认 5s
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user