87 Commits

Author SHA1 Message Date
sakumisu
c1435548e7 release v0.10.2 2023-11-15 22:02:16 +08:00
sakumisu
a8d40eb706 fix ecm mac buffer size 2023-11-15 22:02:07 +08:00
zhugengyu
aeffaea016 add pusb2 port, fix issue for rt-thread, add msc storage demo for rt-thread 2023-11-15 16:48:07 +08:00
sakumisu
9ce7b0ceb7 fix rndis query & set msg wLength, only support one rndis device 2023-11-13 20:03:35 +08:00
sakumisu
1c31156a37 add ms os request 2023-11-13 19:51:53 +08:00
sakumisu
e795ab73a0 check and execute modeswitch first 2023-11-13 19:50:37 +08:00
sakumisu
5e689dfe15 fix class api name 2023-11-13 19:50:04 +08:00
sakumisu
d10cbd5daf check if token is active without errors, if token has errors, go to wakeup sem 2023-11-13 19:49:49 +08:00
sakumisu
40a019e063 add ecm host demo 2023-11-13 19:49:27 +08:00
sakumisu
2080cf1206 add usbh_set_interface api 2023-11-11 14:00:29 +08:00
Yang Xijing
ae521bf95c add nuvoton port(not release) 2023-11-05 14:38:26 +08:00
sakumisu
a2f7b67dc4 update config rst 2023-11-04 17:16:43 +08:00
sakumisu
e79319cac9 add cdc ecm host 2023-11-04 17:16:24 +08:00
sakumisu
7acb667e20 support usb modeswitch 2023-11-04 16:45:20 +08:00
sakumisu
a04b1fa551 add cdc ecm device 2023-11-04 16:44:02 +08:00
sakumisu
c37c60c7c7 add usbh_get_string_desc api 2023-11-04 15:24:15 +08:00
sakumisu
0738c09a4d check qtd active status to fix nbytes = 0 in nak or ping status 2023-11-03 22:18:58 +08:00
sakumisu
cf4dfde49d update quick start, add readthedocs yaml 2023-10-13 20:39:11 +08:00
Zhihong Chen
d4ba2eef57 osal: add USB_OSAL_WAITING_FOREVER for Semaphore and Queue use
- add USB_OSAL_WAITING_FOREVER for Semaphore and Queue use

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-10-12 14:38:13 +08:00
Chen Leeren
3d96f64f94 Fix possible errors in endpoint 0 datapid 2023-10-07 23:46:28 +08:00
sakumisu
a746eb4bb1 update demo version 2023-10-05 17:12:32 +08:00
sakumisu
c84e769f78 remove ununsed input variable 2023-09-30 22:01:12 +08:00
helloeagleyang
d11260ef67 [common] Avoid IAR compiling error on USB HOST stack
- Avoided using a structure with zero-length array as a field in another
  structure when IAR toolchain is used.

Signed-off-by: helloeagleyang <helloeagleyang@163.com>
2023-09-18 00:10:39 +08:00
Wayne Lin
e6193bd131 Revert original parameter. 2023-09-07 15:07:04 +08:00
Wayne Lin
dd1f1d3ba8 Update hcd-ehci, dcd-dwc2 and examples.
1. Add some example Msh commands.
2. Fix device enumeration on EXT hub.
3. Re-file some templates.
4. Extend end-point number of dwc2 device driver.
5. Re-file rndis_host implementation includes
   a. rt_mutex_take in ISR
   b. 2rd pmsg is unaligned issue.
   c. destroy u0 ethernet resource after removing dongle.
2023-09-07 15:07:04 +08:00
sakumisu
bc1e7c4bd5 ignore dwc2 EPENA check 2023-09-04 15:43:32 +08:00
Runcheng Lu
7d76b4bae1 third_party: rtthread: add rndis to adapt lwip2.1.2 2023-09-01 16:13:34 +08:00
sakumisu
7c0ef50bb3 release v0.10.1 2023-08-30 20:05:04 +08:00
sakumisu
0f2cb9f900 fix warning 2023-08-30 20:03:18 +08:00
sakumisu
7c1fae04b2 fix video packet caculation 2023-08-30 17:43:13 +08:00
sakimisu
14f5dd2dd3 implement msc device thread,remove other unused os thread 2023-08-29 14:40:03 +08:00
sakimisu
9029f8c5b1 fix warning 2023-08-27 13:38:13 +08:00
Zhihong Chen
b9915e0e1b port: hpmicro: separate host and device USB instance config
- separate host and device USB instance config

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-26 12:45:31 +08:00
sakimisu
1387790744 add config for hpmicro usb instance and irq 2023-08-26 01:09:33 +08:00
sakimisu
c5fc9f338e fix macro spelling 2023-08-25 21:37:14 +08:00
sakimisu
4d61e5e053 copy bouffalo ehci glue from official sdk 2023-08-25 21:36:58 +08:00
sakimisu
1a7259649b standardize video control api 2023-08-25 21:36:27 +08:00
sakimisu
628e4ee928 improve ehci driver, enable iaad feature 2023-08-25 21:36:14 +08:00
sakimisu
749369b6fc remove usb_phy_init, because hpm sdk v1.2 implement it 2023-08-25 21:35:42 +08:00
Fan YANG
89cd77374c common: Add support for IAR for risc-v toolchain
- Added support for the IAR for risc-v toolchain

Signed-off-by: Fan YANG <fan.yang@hpmicro.com>
2023-08-18 23:33:02 +08:00
sakumisu
3792ad4905 add test scripts 2023-08-15 14:33:54 +08:00
heyuanjie87
2789633b50 [hub 修正] 快速断开的情况下无法处理断开事件 2023-08-13 09:40:01 +08:00
sakimisu
94505f9e41 change rndis_encapsulated_resp_buffer size to 156 2023-08-05 11:11:03 +08:00
sakimisu
c8b832e1a0 fix function name 2023-08-05 11:08:24 +08:00
Zhihong Chen
d3aa9449e1 class: rndis: host: fix function name
- fix function name

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-05 11:05:44 +08:00
Zhihong Chen
4d7938e349 update for midi
- add MidiCodeIndexNumber enum
- update midi descriptor. Audio v1.0's endpoint has 9 bytes instead of 7.

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-05 11:05:44 +08:00
Zhihong Chen
4777a65f54 ehci: update hardcode for hpmicro
- should define CONFIG_USB_EHCI_HPMICRO and CONFIG_HPM_USB_BASE in usb_config.h

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-01 20:10:02 +08:00
sakimisu
96c0b655fd update version 0.10.0 2023-07-29 17:05:21 +08:00
sakimisu
61da3794cf update device api 2023-07-29 16:09:23 +08:00
Chen Leeren
45ea9928bc Fix the callback api in usbd_hid.c 2023-07-21 12:38:23 +08:00
sakimisu
64e2b8d480 update hid inout demo 2023-07-20 22:03:45 +08:00
sakumisu
fed6f26ebd fix log 2023-07-14 17:58:39 +08:00
sakimisu
513772a534 update doc 2023-07-13 20:34:11 +08:00
sakumisu
e45a2857df fix missing function 2023-07-13 20:14:28 +08:00
sakumisu
c8ecf31c99 remove ununsed code 2023-07-13 20:13:51 +08:00
sakimisu
4395c7f039 update device & host usage 2023-07-13 19:36:31 +08:00
sakimisu
3057f41020 use static memory to malloc & free class 2023-07-12 22:48:18 +08:00
sakimisu
47c0255cdc fix rt-thread once thread delete 2023-07-12 21:48:18 +08:00
sakumisu
d53e8a2adf add msc popup function 2023-07-11 22:17:03 +08:00
sakimisu
3bdb3bbf84 clasify vendor driver 2023-07-09 17:57:35 +08:00
sakimisu
3c1168d58c update cmakelist for common 2023-07-09 14:44:44 +08:00
lenovo
f672591d58 Silicon Laboratories CP210x USB to RS232 serial adaptor driver is suppported 2023-07-09 00:52:30 +08:00
sakumisu
84598eed7c fix rndis build error 2023-07-08 21:44:20 +08:00
sakimisu
7574063e94 enum device with disposable thread, do not block hub thread 2023-07-05 22:53:13 +08:00
sakimisu
0d916af297 check if urb is null 2023-07-02 22:29:07 +08:00
sakimisu
b90d6a727e update double winusb demo 2023-06-30 23:53:23 +08:00
sakimisu
d0d6f99c90 use DxEPCTL to check if ep is busy 2023-06-30 22:19:23 +08:00
sakumisu
9673b2cf67 update outline pic 2023-06-30 18:08:30 +08:00
sakimisu
7061367484 support multi winusb 2023-06-28 22:59:22 +08:00
sakimisu
faf90663a9 format code 2023-06-28 21:45:06 +08:00
sakimisu
bb58348510 check if current context is in irq when gives sem 2023-06-28 21:44:28 +08:00
sakimisu
8253f074ce implment musb usbh_kill_urb 2023-06-28 21:11:38 +08:00
sakimisu
8a93ca4bce remove dap 2023-06-25 22:38:18 +08:00
sakimisu
8968b7b3c9 update dwc2 iso transfer 2023-06-22 13:40:07 +08:00
sakimisu
2ca22deaad remove unused code 2023-06-21 23:30:44 +08:00
sakimisu
340fa4e024 use usbd_event_handler instead of usbd_configure_done_callback 2023-06-21 21:26:25 +08:00
sakimisu
822cd9d679 add dwc2 param log 2023-06-21 20:51:10 +08:00
sakimisu
e061b8e784 fix winusb demo 2023-06-21 20:46:59 +08:00
sakimisu
8856361be0 remove unused code 2023-06-21 20:44:32 +08:00
sakimisu
1c7110bd86 refactor audio device class 2023-06-21 20:43:35 +08:00
sakimisu
48efbfe521 update demo, move hid buffer into nocache ram 2023-06-21 20:43:25 +08:00
sakimisu
c540080c96 format class struct and global variable name 2023-06-21 20:43:06 +08:00
sakimisu
d970f88f06 add cdc send break request 2023-06-21 19:39:48 +08:00
sakimisu
2d1b4b8b82 export cdc/msc/rndis/mtp mps, configured by user 2023-06-21 19:39:22 +08:00
sakumisu
9bac9537db remove ununsed code 2023-06-19 22:25:32 +08:00
Runcheng Lu
f35b345680 third_party: rtthread: fix rndis_host some issue
- fix some issue

Signed-off-by: Runcheng Lu <runcheng.lu@hpmicro.com>
2023-06-16 10:43:49 +08:00
Runcheng Lu
56868b513a third_party: freertos: add adapt rndis_host APIs
- add adapt rndis_host APIs

Signed-off-by: Runcheng Lu <runcheng.lu@hpmicro.com>
2023-06-16 10:43:49 +08:00
139 changed files with 10652 additions and 8859 deletions

35
.readthedocs.yaml Normal file
View 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

View File

@@ -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()

View File

@@ -4,7 +4,7 @@
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
![CherryUSB](./docs/assets/usb_outline.png)
![CherryUSB](./docs/assets/CherryUSB.svg)
## Why choose
@@ -85,12 +85,13 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3263 | 384 | 17 | 0 |
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 501 | 0 | 0 | 0 |
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|usbd_video.c | 2272 | 0 | 82 | 0 |
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host Stack Overview
@@ -116,13 +117,14 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros
@@ -134,6 +136,18 @@ Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affe
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
```
x is affected by the following macros
```
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
```
## Documentation Tutorial
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
@@ -148,23 +162,22 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
## Demo Repo
| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
| Manufacturer | CHIP or Series | USB IP| Repo Url |Current version|
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.7.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|latest |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|Phytium | PhytiumPI | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
## Contact

View File

@@ -4,7 +4,7 @@
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
![CherryUSB](./docs/assets/usb_outline.png)
![CherryUSB](./docs/assets/CherryUSB.svg)
## 为什么选择
@@ -83,12 +83,13 @@ CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3263 | 384 | 17 | 0 |
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 501 | 0 | 0 | 0 |
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|usbd_video.c | 2272 | 0 | 82 | 0 |
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host 协议栈简介
@@ -114,13 +115,14 @@ CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:
@@ -132,6 +134,18 @@ CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
```
x 受以下宏影响:
```
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
```
## 文档教程
CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
@@ -146,23 +160,22 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
## 示例仓库
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 当前版本 |
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.7.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|latest |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|Phytium | e2000 | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
## Contact

View File

@@ -16,7 +16,9 @@ CPPDEFINES = []
# USB DEVICE
if GetDepend(['PKG_CHERRYUSB_DEVICE']):
path += [cwd + '/osal']
src += Glob('core/usbd_core.c')
src += Glob('osal/usb_osal_rtthread.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
CPPDEFINES+=['CONFIG_USB_HS']
@@ -44,6 +46,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/hid_keyboard_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
src += Glob('demo/msc_ram_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
src += Glob('demo/msc_storage_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
@@ -81,6 +85,12 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
else:
src += Glob('port/ch32/usb_dc_usbfs.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
path += [cwd + '/port/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_dc_pusb2.c')
# USB HOST
if GetDepend(['PKG_CHERRYUSB_HOST']):
path += [cwd + '/osal']
@@ -97,6 +107,7 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('class/msc/usbh_msc.c')
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
src += Glob('class/wireless/usbh_rndis.c')
src += Glob('third_party/rt-thread-4.1.1/rndis_host/rndis_host.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
@@ -111,9 +122,27 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
src += Glob('port/ehci/usb_glue_hpm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
src += Glob('port/xhci/usb_hc_xhci.c')
src += Glob('port/xhci/xhci_dbg.c')
src += Glob('port/xhci/xhci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_hc_pusb2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
src += Glob('demo/usb_host.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
path += [cwd + '/class/vendor/cp201x']
src += Glob('class/vendor/cp201x/usbh_cp210x.c')
src += Glob('third_party/rt-thread-4.1.1/dfs/drv_usbh_cp210x_rtt.c')
src += Glob('third_party/rt-thread-4.1.1/msh_cmd.c')
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')

View File

@@ -6,7 +6,7 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x000900
#define CHERRYUSB_VERSION 0x001002
/* ================ USB common Configuration ================ */
@@ -44,27 +44,6 @@
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
//#define CONFIG_USBDEV_TX_THREAD
//#define CONFIG_USBDEV_RX_THREAD
#ifdef CONFIG_USBDEV_TX_THREAD
#ifndef CONFIG_USBDEV_TX_PRIO
#define CONFIG_USBDEV_TX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_TX_STACKSIZE
#define CONFIG_USBDEV_TX_STACKSIZE 2048
#endif
#endif
#ifdef CONFIG_USBDEV_RX_THREAD
#ifndef CONFIG_USBDEV_RX_PRIO
#define CONFIG_USBDEV_RX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_RX_STACKSIZE
#define CONFIG_USBDEV_RX_STACKSIZE 2048
#endif
#endif
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
#endif
@@ -81,16 +60,18 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
#ifndef CONFIG_USBDEV_AUDIO_VERSION
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
// #define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
#define CONFIG_USBDEV_MSC_PRIO 4
#endif
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
@@ -116,6 +97,12 @@
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_DEV_NAMELEN 16
#ifndef CONFIG_USBHOST_PSC_PRIO
@@ -127,6 +114,9 @@
//#define CONFIG_USBHOST_GET_STRING_DESC
// #define CONFIG_USBHOST_MSOS_ENABLE
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
/* Ep0 max transfer buffer */
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
@@ -154,7 +144,7 @@
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER

View File

@@ -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 */ \

View File

@@ -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, &current_feature_control->volume[ch].vol_current, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
memcpy(*data, &current_feature_control->volume[ch].vol_min, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
memcpy(*data, &current_feature_control->volume[ch].vol_max, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
memcpy(*data, &current_feature_control->volume[ch].vol_res, 2);
*len = 2;
break;
case AUDIO_REQUEST_SET_RES:
memcpy(&current_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)
{
}

View File

@@ -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
}

View File

@@ -17,33 +17,38 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
static uint32_t g_devinuse = 0;
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
static int usbh_audio_devno_alloc(struct usbh_audio *audio_class)
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_audio *usbh_audio_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
audio_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
g_audio_class[devno].minor = devno;
return &g_audio_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_audio_devno_free(struct usbh_audio *audio_class)
static void usbh_audio_class_free(struct usbh_audio *audio_class)
{
int devno = audio_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
}
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
@@ -269,14 +274,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t format_offset = 0;
uint8_t *p;
struct usbh_audio *audio_class = usb_malloc(sizeof(struct usbh_audio));
struct usbh_audio *audio_class = usbh_audio_class_alloc();
if (audio_class == NULL) {
USB_LOG_ERR("Fail to alloc audio_class\r\n");
return -ENOMEM;
}
memset(audio_class, 0, sizeof(struct usbh_audio));
usbh_audio_devno_alloc(audio_class);
audio_class->hport = hport;
audio_class->ctrl_intf = intf;
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
@@ -412,8 +415,6 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_audio *audio_class = (struct usbh_audio *)hport->config.intf[intf].priv;
if (audio_class) {
usbh_audio_devno_free(audio_class);
if (audio_class->isoin) {
usbh_pipe_free(audio_class->isoin);
}
@@ -427,8 +428,7 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_audio_stop(audio_class);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
usb_free(audio_class);
usbh_audio_class_free(audio_class);
}
return ret;

View File

@@ -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 */

View File

@@ -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)
{
}

View File

@@ -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
View File

@@ -0,0 +1,237 @@
/*
* Copyright (c) 2023, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
#define CDC_ECM_OUT_EP_IDX 0
#define CDC_ECM_IN_EP_IDX 1
#define CDC_ECM_INT_EP_IDX 2
/* Describe EndPoints configuration */
static struct usbd_endpoint cdc_ecm_ep_data[3];
#ifdef CONFIG_USB_HS
#define CDC_ECM_MAX_PACKET_SIZE 512
#else
#define CDC_ECM_MAX_PACKET_SIZE 64
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
volatile uint32_t g_cdc_ecm_tx_data_length = 0;
static volatile uint8_t g_current_net_status = 0;
static volatile uint8_t g_cmd_intf = 0;
static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
CDC_ECM_CONNECT_SPEED_DOWNSTREAM };
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
{
struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
uint8_t bytes2send = 0;
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
notify->bNotificationType = notifycode;
switch (notifycode) {
case CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION:
notify->wValue = value;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0x0008U;
bytes2send = 16U;
memcpy(notify->data, speed, 8);
break;
default:
break;
}
if (bytes2send) {
usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
}
}
static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC ECM Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
g_cmd_intf = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
if (g_current_net_status == 0) {
g_current_net_status = 1;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
}
break;
default:
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
void cdc_ecm_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
g_current_net_status = 0;
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_tx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
break;
case USBD_EVENT_CONFIGURED:
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
break;
default:
break;
}
}
void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
{
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done();
} else {
usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
}
}
void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(ep, NULL, 0);
} else {
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
{
if (g_current_net_status == 1) {
g_current_net_status = 2;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
}
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
struct pbuf *usbd_cdc_ecm_eth_rx(void)
{
struct pbuf *p;
if (g_cdc_ecm_rx_data_buffer == NULL) {
return NULL;
}
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
if (p == NULL) {
return NULL;
}
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
p->len = g_cdc_ecm_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
return p;
}
int usbd_cdc_ecm_eth_tx(struct pbuf *p)
{
struct pbuf *q;
uint8_t *buffer;
if (g_cdc_ecm_tx_data_length > 0) {
return -EBUSY;
}
if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
p->tot_len = sizeof(g_cdc_ecm_tx_buffer);
}
buffer = g_cdc_ecm_tx_buffer;
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
g_cdc_ecm_tx_data_length = p->tot_len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
}
#endif
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = cdc_ecm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = cdc_ecm_notify_handler;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr = out_ep;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_cb = cdc_ecm_bulk_out;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr = in_ep;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_cb = cdc_ecm_bulk_in;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
return intf;
}
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
{
memcpy(g_connect_speed_table, speed, 8);
}
__WEAK void usbd_cdc_ecm_data_recv_done(void)
{
}

36
class/cdc/usbd_cdc_ecm.h Normal file
View 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 */

View File

@@ -8,32 +8,34 @@
#define DEV_FORMAT "/dev/ttyACM%d"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *cdc_acm_class)
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
cdc_acm_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
g_cdc_acm_class[devno].minor = devno;
return &g_cdc_acm_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *cdc_acm_class)
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
{
int devno = cdc_acm_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
}
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -91,14 +93,12 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_cdc_acm *cdc_acm_class = usb_malloc(sizeof(struct usbh_cdc_acm));
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
if (cdc_acm_class == NULL) {
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
return -ENOMEM;
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
usbh_cdc_acm_devno_alloc(cdc_acm_class);
cdc_acm_class->hport = hport;
cdc_acm_class->ctrl_intf = intf;
cdc_acm_class->data_intf = intf + 1;
@@ -151,8 +151,6 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv;
if (cdc_acm_class) {
usbh_cdc_acm_devno_free(cdc_acm_class);
if (cdc_acm_class->bulkin) {
usbh_pipe_free(cdc_acm_class->bulkin);
}
@@ -166,8 +164,7 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_cdc_acm_stop(cdc_acm_class);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
usb_free(cdc_acm_class);
usbh_cdc_acm_class_free(cdc_acm_class);
}
return ret;

330
class/cdc/usbh_cdc_ecm.c Normal file
View File

@@ -0,0 +1,330 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ecm.h"
#define DEV_FORMAT "/dev/cdc_ether"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
static struct usbh_cdc_ecm g_cdc_ecm_class;
static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class, uint16_t filter_value)
{
struct usb_setup_packet *setup = cdc_ecm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
setup->wValue = filter_value;
setup->wIndex = cdc_ecm_class->ctrl_intf;
setup->wLength = 0;
return usbh_control_transfer(cdc_ecm_class->hport->ep0, setup, NULL);
}
int usbh_cdc_ecm_get_notification(struct usbh_cdc_ecm *cdc_ecm_class)
{
int ret;
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&cdc_ecm_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
cdc_ecm_class->connect_status = g_cdc_ecm_inttx_buffer[2];
} else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8);
}
return 0;
}
static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t altsetting = 0;
char mac_buffer[12];
uint8_t *p;
uint8_t cur_iface = 0xff;
uint8_t mac_str_idx = 0xff;
struct usbh_cdc_ecm *cdc_ecm_class = &g_cdc_ecm_class;
cdc_ecm_class->hport = hport;
cdc_ecm_class->ctrl_intf = intf;
cdc_ecm_class->data_intf = intf + 1;
hport->config.intf[intf].priv = cdc_ecm_class;
hport->config.intf[intf + 1].priv = NULL;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
break;
case CDC_CS_INTERFACE:
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
struct cdc_ecm_descriptor *desc = (struct cdc_ecm_descriptor *)p;
mac_str_idx = desc->iMACAddress;
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
goto get_mac;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
get_mac:
if (mac_str_idx == 0xff) {
USB_LOG_ERR("Do not find cdc ecm mac string\r\n");
return -1;
}
memset(mac_buffer, 0, 8);
ret = usbh_get_string_desc(cdc_ecm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
if (ret < 0) {
return ret;
}
for (int i = 0, j = 0; i < 12; i += 2, j++) {
char byte_str[3];
byte_str[0] = mac_buffer[i];
byte_str[1] = mac_buffer[i + 1];
byte_str[2] = '\0';
uint32_t byte = strtoul(byte_str, NULL, 16);
cdc_ecm_class->mac[j] = (unsigned char)byte;
}
USB_LOG_INFO("CDC ECM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
cdc_ecm_class->mac[0],
cdc_ecm_class->mac[1],
cdc_ecm_class->mac[2],
cdc_ecm_class->mac[3],
cdc_ecm_class->mac[4],
cdc_ecm_class->mac[5]);
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE) {
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE, cdc_ecm_class->max_segment_size);
} else {
USB_LOG_INFO("CDC ECM Max Segment Size:%u\r\n", cdc_ecm_class->max_segment_size);
}
/* enable int ep */
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
usbh_hport_activate_epx(&cdc_ecm_class->intin, hport, ep_desc);
if (hport->config.intf[intf + 1].altsetting_num > 1) {
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
}
}
USB_LOG_INFO("Select cdc ecm altsetting: %d\r\n", altsetting);
usbh_set_interface(cdc_ecm_class->hport, cdc_ecm_class->data_intf, altsetting);
} else {
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
}
}
}
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
ret = usbh_cdc_ecm_set_eth_packet_filter(cdc_ecm_class, CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Set CDC ECM packet filter:%04x\r\n", CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_run(cdc_ecm_class);
return ret;
}
static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)hport->config.intf[intf].priv;
if (cdc_ecm_class) {
if (cdc_ecm_class->bulkin) {
usbh_pipe_free(cdc_ecm_class->bulkin);
}
if (cdc_ecm_class->bulkout) {
usbh_pipe_free(cdc_ecm_class->bulkout);
}
if (cdc_ecm_class->intin) {
usbh_pipe_free(cdc_ecm_class->intin);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_stop(cdc_ecm_class);
}
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
}
return ret;
}
static void usbh_cdc_ecm_rx_thread(void *argument)
{
uint32_t g_cdc_ecm_rx_length;
int ret;
err_t err;
struct pbuf *p;
struct netif *netif = (struct netif *)argument;
uint16_t ep_mps;
// clang-format off
find_class:
// clang-format on
while (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
usb_osal_msleep(1000);
}
while (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
if (ret < 0) {
goto find_class;
}
}
if (g_cdc_ecm_class.hport->speed == USB_SPEED_FULL) {
ep_mps = 64;
} else {
ep_mps = 512;
}
g_cdc_ecm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
if (g_cdc_ecm_rx_length % ep_mps) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
if (p != NULL) {
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
g_cdc_ecm_rx_length = 0;
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
g_cdc_ecm_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
}
} else {
}
}
}
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
{
int ret;
struct pbuf *q;
uint8_t *buffer = g_cdc_ecm_tx_buffer;
if (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
return ERR_BUF;
}
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
}
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif)
{
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, netif);
}
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
}
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
}
const struct usbh_class_driver cdc_ecm_class_driver = {
.driver_name = "cdc_ecm",
.connect = usbh_cdc_ecm_connect,
.disconnect = usbh_cdc_ecm_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.vid = 0x00,
.pid = 0x00,
.class_driver = &cdc_ecm_class_driver
};

50
class/cdc/usbh_cdc_ecm.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_ECM_H
#define USBH_CDC_ECM_H
#include "usb_cdc.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_cdc_ecm {
struct usbh_hubport *hport;
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
uint8_t mac[6];
uint32_t max_segment_size;
uint8_t connect_status;
uint32_t speed[2];
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
usbh_pipe_t intin; /* Interrupt IN endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
struct usbh_urb intin_urb;
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
};
#ifdef __cplusplus
extern "C" {
#endif
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_ACM_H */

View File

@@ -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;
}
}

View File

@@ -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)
{
}

View File

@@ -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
}

View File

@@ -8,33 +8,34 @@
#define DEV_FORMAT "/dev/input%d"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_hid *usbh_hid_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
hid_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
g_hid_class[devno].minor = devno;
return &g_hid_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_hid_devno_free(struct usbh_hid *hid_class)
static void usbh_hid_class_free(struct usbh_hid *hid_class)
{
int devno = hid_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
}
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
@@ -106,14 +107,12 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid));
struct usbh_hid *hid_class = usbh_hid_class_alloc();
if (hid_class == NULL) {
USB_LOG_ERR("Fail to alloc hid_class\r\n");
return -ENOMEM;
}
memset(hid_class, 0, sizeof(struct usbh_hid));
usbh_hid_devno_alloc(hid_class);
hid_class->hport = hport;
hid_class->intf = intf;
@@ -159,8 +158,6 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
if (hid_class) {
usbh_hid_devno_free(hid_class);
if (hid_class->intin) {
usbh_pipe_free(hid_class->intin);
}
@@ -174,8 +171,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_hid_stop(hid_class);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
usb_free(hid_class);
usbh_hid_class_free(hid_class);
}
return ret;

View File

@@ -14,10 +14,6 @@
#define EXTHUB_FIRST_INDEX 2
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static uint32_t g_devinuse = 0;
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
@@ -28,9 +24,6 @@ usb_osal_mq_t hub_mq;
struct usbh_hub roothub;
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
#endif
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
extern int usbh_enumerate(struct usbh_hubport *hport);
@@ -46,26 +39,32 @@ struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
#endif
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int usbh_hub_devno_alloc(void)
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
static uint32_t g_devinuse = 0;
static struct usbh_hub *usbh_hub_class_alloc(void)
{
int devno;
for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
return devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
return &g_hub_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_hub_devno_free(uint8_t devno)
static void usbh_hub_class_free(struct usbh_hub *hub_class)
{
if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
#endif
@@ -109,7 +108,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
return ret;
}
#if 0
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -131,6 +130,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
return ret;
}
#endif
#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -299,7 +299,8 @@ static void hub_int_complete_callback(void *arg, int nbytes)
{
struct usbh_hub *hub = (struct usbh_hub *)arg;
if (nbytes > 0) {
if (nbytes > 0)
{
usbh_hub_thread_wakeup(hub);
}
}
@@ -309,21 +310,15 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
struct hub_port_status port_status;
int ret;
int index;
index = usbh_hub_devno_alloc();
if (index > (CONFIG_USBHOST_MAX_EXTHUBS + EXTHUB_FIRST_INDEX - 1)) {
USB_LOG_ERR("No memory to alloc hub class\r\n");
usbh_hub_devno_free(index);
struct usbh_hub *hub = usbh_hub_class_alloc();
if (hub == NULL) {
USB_LOG_ERR("Fail to alloc hub_class\r\n");
return -ENOMEM;
}
struct usbh_hub *hub = &exthub[index - EXTHUB_FIRST_INDEX];
memset(hub, 0, sizeof(struct usbh_hub));
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->index = index;
hport->config.intf[intf].priv = hub;
@@ -394,8 +389,6 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
if (hub) {
usbh_hub_devno_free(hub->index);
if (hub->intin) {
usbh_pipe_free(hub->intin);
}
@@ -413,11 +406,12 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
child->parent = NULL;
}
usbh_hub_unregister(hub);
memset(hub, 0, sizeof(struct usbh_hub));
if (hport->config.intf[intf].devname[0] != '\0')
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hub_unregister(hub);
}
usbh_hub_class_free(hub);
}
return ret;
}
@@ -437,6 +431,21 @@ static void usbh_hubport_release(struct usbh_hubport *child)
}
}
static void usbh_hubport_enumerate_thread(void *argument)
{
struct usbh_hubport *child = (struct usbh_hubport *)argument;
/* Configure EP0 with the default maximum packet size */
usbh_hport_activate_ep0(child);
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
}
usb_osal_thread_delete(NULL);
}
static void usbh_hub_events(struct usbh_hub *hub)
{
struct usbh_hubport *child;
@@ -453,9 +462,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
return;
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
portchange_index = hub->int_buffer[0];
portchange_index = hub->int_buffer[0];
hub->int_buffer[0] = 0;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
if (!(portchange_index & (1 << (port + 1)))) {
@@ -597,14 +607,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
/* Configure EP0 with the default maximum packet size */
usbh_hport_activate_ep0(child);
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1);
}
/* create disposable thread to enumerate device on current hport, do not block hub thread */
child->thread = usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
} else {
child = &hub->child[port];
/** release child sources */
@@ -624,7 +628,6 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
hub->int_buffer[0] = 0;
/* Start next hub int transfer */
if (!hub->is_roothub && hub->connected) {
usbh_submit_urb(&hub->intin_urb);
@@ -638,7 +641,7 @@ static void usbh_hub_thread(void *argument)
usb_hc_init();
while (1) {
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, 0xffffffff);
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}

View File

@@ -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, \

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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
}

View File

@@ -9,33 +9,35 @@
#define DEV_FORMAT "/dev/sd%c"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
static int usbh_msc_devno_alloc(struct usbh_msc *msc_class)
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
static struct usbh_msc *usbh_msc_class_alloc(void)
{
int devno;
for (devno = 0; devno < 26; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
msc_class->sdchar = 'a' + devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
g_msc_class[devno].sdchar = 'a' + devno;
return &g_msc_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_msc_devno_free(struct usbh_msc *msc_class)
static void usbh_msc_class_free(struct usbh_msc *msc_class)
{
int devno = msc_class->sdchar - 'a';
if (devno >= 0 && devno < 26) {
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
}
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
@@ -273,19 +275,39 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
{
if (config) {
g_msc_modeswitch_config = config;
} else {
g_msc_modeswitch_config = NULL;
}
}
void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memcpy(g_msc_buf, message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_msc_modeswitch_config *config;
struct usbh_msc *msc_class = usb_malloc(sizeof(struct usbh_msc));
struct usbh_msc *msc_class = usbh_msc_class_alloc();
if (msc_class == NULL) {
USB_LOG_ERR("Fail to alloc msc_class\r\n");
return -ENOMEM;
}
memset(msc_class, 0, sizeof(struct usbh_msc));
usbh_msc_devno_alloc(msc_class);
msc_class->hport = hport;
msc_class->intf = intf;
@@ -307,6 +329,23 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
}
}
if (g_msc_modeswitch_config) {
uint8_t num = 0;
while (1) {
config = &g_msc_modeswitch_config[num];
if (config) {
if ((hport->device_desc.idVendor == config->vid) &&
(hport->device_desc.idProduct == config->pid)) {
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
usbh_msc_modeswitch(msc_class, config->message_content);
return 0;
}
} else {
break;
}
}
}
ret = usbh_msc_scsi_testunitready(msc_class);
if (ret < 0) {
ret = usbh_msc_scsi_requestsense(msc_class);
@@ -315,6 +354,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
@@ -349,8 +389,6 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
if (msc_class) {
usbh_msc_devno_free(msc_class);
if (msc_class->bulkin) {
usbh_pipe_free(msc_class->bulkin);
}
@@ -364,8 +402,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_msc_stop(msc_class);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
usb_free(msc_class);
usbh_msc_class_free(msc_class);
}
return ret;

View File

@@ -22,6 +22,14 @@ struct usbh_msc {
uint16_t blocksize; /* Block size of USB mass storage device */
};
struct usbh_msc_modeswitch_config {
const char *name;
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
uint16_t pid; /* Product ID (for vendor/product specific devices) */
const uint8_t *message_content;
};
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);

View File

@@ -437,9 +437,8 @@ struct mtp_container_response {
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
// clang-format off
#ifndef CONFIG_USB_HS
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
/* Interface */ \
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
@@ -453,13 +452,13 @@ struct mtp_container_response {
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
@@ -467,37 +466,6 @@ struct mtp_container_response {
0x03, /* bmAttributes */ \
0x1c, 0x00, /* wMaxPacketSize */ \
0x06 /* bInterval */
#else
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x03, /* bNumEndpoints */ \
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, 0x00, /* wMaxPacketSize */ \
0x06 /* bInterval */
#endif
// clang-format on
#endif /* USB_MTP_H */

View File

@@ -16,7 +16,7 @@ enum Stage {
MTP_WAIT_RESPONSE = 4,
};
USB_NOCACHE_RAM_SECTION struct usbd_mtp {
USB_NOCACHE_RAM_SECTION struct usbd_mtp_priv {
USB_MEM_ALIGNX struct mtp_container_command con_command;
USB_MEM_ALIGNX struct mtp_container_data con_data;
USB_MEM_ALIGNX struct mtp_container_response con_response;

View File

@@ -6,11 +6,11 @@
#include "usbd_core.h"
#include "usbd_printer.h"
struct printer_cfg_priv {
struct usbd_printer_priv {
const uint8_t *device_id;
uint8_t device_id_len;
uint8_t port_status;
} usbd_printer_cfg;
} g_usbd_printer;
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
@@ -20,8 +20,8 @@ static int printer_class_interface_request_handler(struct usb_setup_packet *setu
switch (setup->bRequest) {
case PRINTER_REQUEST_GET_DEVICE_ID:
memcpy(*data, usbd_printer_cfg.device_id, usbd_printer_cfg.device_id_len);
*len = usbd_printer_cfg.device_id_len;
memcpy(*data, g_usbd_printer.device_id, g_usbd_printer.device_id_len);
*len = g_usbd_printer.device_id_len;
break;
case PRINTER_REQUEST_GET_PORT_SATTUS:
@@ -55,7 +55,7 @@ struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const
intf->vendor_handler = NULL;
intf->notify_handler = printer_notify_handler;
usbd_printer_cfg.device_id = device_id;
usbd_printer_cfg.device_id_len = device_id_len;
g_usbd_printer.device_id = device_id;
g_usbd_printer.device_id_len = device_id_len;
return intf;
}

View File

@@ -8,6 +8,34 @@
#define DEV_FORMAT "/dev/printer"
static struct usbh_printer g_printer_class[CONFIG_USBHOST_MAX_PRINTER_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_printer *usbh_printer_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_PRINTER_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_printer_class[devno], 0, sizeof(struct usbh_printer));
g_printer_class[devno].minor = devno;
return &g_printer_class[devno];
}
}
return NULL;
}
static void usbh_printer_class_free(struct usbh_printer *printer_class)
{
int devno = printer_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(printer_class, 0, sizeof(struct usbh_printer));
}
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
{
struct usb_setup_packet *setup = &printer_class->hport->setup;
@@ -56,14 +84,12 @@ static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_printer *printer_class = usb_malloc(sizeof(struct usbh_printer));
struct usbh_printer *printer_class = usbh_printer_class_alloc();
if (printer_class == NULL) {
USB_LOG_ERR("Fail to alloc printer_class\r\n");
return -ENOMEM;
}
memset(printer_class, 0, sizeof(struct usbh_printer));
printer_class->hport = hport;
printer_class->intf = intf;
@@ -107,8 +133,7 @@ static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
}
memset(printer_class, 0, sizeof(struct usbh_printer));
usb_free(printer_class);
usbh_printer_class_free(printer_class);
}
return ret;

View File

@@ -12,6 +12,7 @@ struct usbh_printer {
struct usbh_hubport *hport;
uint8_t intf; /* interface number */
uint8_t minor;
usbh_pipe_t bulkin; /* BULK IN endpoint */
usbh_pipe_t bulkout; /* BULK OUT endpoint */
};

View File

@@ -3,43 +3,47 @@
#define DEV_FORMAT "/dev/xxx"
static struct usbh_xxx g_xxx_class[CONFIG_USBHOST_MAX_CUSTOM_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_xxx *usbh_xxx_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
g_xxx_class[devno].minor = devno;
return &g_xxx_class[devno];
}
}
return NULL;
}
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
{
int devno = xxx_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
}
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_xxx *xxx_class = usb_malloc(sizeof(struct usbh_xxx));
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
if (xxx_class == NULL) {
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
return -ENOMEM;
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
xxx_class->hport = hport;
xxx_class->intf = intf;
hport->config.intf[intf].priv = xxx_class;
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.hport = hport;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
} else {
usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
}
}
return ret;
}
@@ -58,17 +62,24 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_pipe_free(xxx_class->bulkout);
}
usb_free(xxx_class);
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xxx_stop(xxx_class);
}
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
hport->config.intf[intf].priv = NULL;
usbh_xxx_class_free(xxx_class);
}
return ret;
}
__WEAK void usbh_xxx_run(struct usbh_xxx *xxx_class)
{
}
__WEAK void usbh_xxx_stop(struct usbh_xxx *xxx_class)
{
}
static const struct usbh_class_driver xxx_class_driver = {
.driver_name = "xxx",

View File

@@ -7,8 +7,9 @@ struct usbh_xxx {
struct usbh_hubport *hport;
uint8_t intf; /* interface number */
usbh_pipe_t intin; /* INTR IN endpoint */
usbh_pipe_t intout; /* INTR OUT endpoint */
uint8_t minor;
usbh_pipe_t bulkin; /* bulk IN endpoint */
usbh_pipe_t bulkout; /* bulk OUT endpoint */
};
#endif

View File

@@ -16,6 +16,8 @@ struct usbh_cdc_custom_air724 {
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_air724_buf[32];
static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
@@ -30,12 +32,26 @@ static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *c
return ret;
}
static inline int usbh_air724_bulk_in_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_custom_class->bulkin_urb;
memset(urb, 0, sizeof(struct usbh_urb));
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
/* interface 3 is AT command */
if (intf != 3) {
USB_LOG_WRN("ignore intf:%d\r\n", intf);
return 0;
@@ -65,20 +81,22 @@ int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
uint8_t cdc_buffer[32] = { 0x41, 0x54, 0x0d, 0x0a };
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkout, cdc_buffer, 4, 3000);
const uint8_t AT[4] = { 0x41, 0x54, 0x0d, 0x0a };
memcpy(g_air724_buf, AT, 4);
ret = usbh_air724_bulk_out_transfer(cdc_custom_class, g_air724_buf, 4, 3000);
if (ret < 0) {
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
} else {
USB_LOG_RAW("send over:%d\r\n", ret);
}
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkin, cdc_buffer, 10, 3000);
ret = usbh_air724_bulk_in_transfer(cdc_custom_class, g_air724_buf, 10, 3000);
if (ret < 0) {
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
} else {
USB_LOG_RAW("recv over:%d\r\n", ret);
for (size_t i = 0; i < ret; i++) {
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
USB_LOG_RAW("0x%02x ", g_air724_buf[i]);
}
}

1763
class/vendor/cp201x/usbh_cp210x.c vendored Normal file

File diff suppressed because it is too large Load Diff

99
class/vendor/cp201x/usbh_cp210x.h vendored Normal file
View File

@@ -0,0 +1,99 @@
#ifndef USBH_CP210X_H
#define USBH_CP210X_H
#include <stdint.h>
#include "usbh_core.h"
typedef int32_t speed_t;
typedef int32_t tcflag_t;
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
struct usb_serial_port{
uint8_t partnum;
uint8_t ctrlpipe_rx;
uint8_t ctrlpipe_tx;
int32_t max_speed;
speed_t use_actual_rate;
uint8_t bInterfaceNumber;
int has_swapped_line_ctl;
};
typedef unsigned char cc_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* Alpha has identical termios and termios2 */
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* Alpha has matching termios and ktermios */
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
struct tty_struct{
struct usb_serial_port driver_data;
struct termios termios;
};
int cp210x_attach(struct usb_serial_port *port);
int cp210x_port_probe(struct usb_serial_port *port);
void cp210x_break_ctl(struct tty_struct *tty, int break_state);
int cp210x_open(struct tty_struct *tty);
int cp210x_tiocmget(struct tty_struct *tty);
void cp210x_set_termios(struct tty_struct *tty);
void cp210x_change_speed(struct tty_struct *tty);
void cp210x_dtr_rts(struct usb_serial_port *port, int on);
struct usbh_cp210x
{
struct usbh_hubport *hport;
uint8_t intf;
usbh_pipe_t bulkin;
usbh_pipe_t bulkout;
struct usbh_urb bulkin_urb;
struct usbh_urb bulkout_urb;
struct tty_struct drv_data;
int index;
};
/* weak defined function */
void drv_usbh_cp210x_run(struct usbh_cp210x *p_device);
void drv_usbh_cp210x_stop(struct usbh_cp210x *p_device);
#endif

View File

@@ -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;

View File

@@ -21,63 +21,77 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
static const char *format_type[] = { "uncompressed", "mjpeg" };
static int usbh_video_devno_alloc(struct usbh_video *video_class)
static struct usbh_video g_video_class[CONFIG_USBHOST_MAX_VIDEO_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_video *usbh_video_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
video_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
g_video_class[devno].minor = devno;
return &g_video_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_video_devno_free(struct usbh_video *video_class)
static void usbh_video_class_free(struct usbh_video *video_class)
{
int devno = video_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(video_class, 0, sizeof(struct usbh_video));
}
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
{
struct usb_setup_packet *setup = video_class->hport->setup;
int ret;
uint8_t retry;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = VIDEO_REQUEST_GET_CUR;
setup->bRequest = request;
setup->wValue = cs << 8;
setup->wIndex = (entity_id << 8) | intf;
setup->wLength = len;
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
if (ret < 0) {
return ret;
retry = 0;
while (1) {
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
if (ret > 0) {
break;
}
retry++;
if (retry == 3) {
return ret;
}
}
memcpy(buf, g_video_buf, len);
if (buf) {
memcpy(buf, g_video_buf, len);
}
return ret;
}
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
{
struct usb_setup_packet *setup = video_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = VIDEO_REQUEST_SET_CUR;
setup->bRequest = request;
setup->wValue = cs << 8;
setup->wIndex = (entity_id << 8) | intf;
setup->wLength = len;
@@ -85,13 +99,13 @@ int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t ent
memcpy(g_video_buf, buf, len);
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
usb_osal_msleep(5);
usb_osal_msleep(50);
return ret;
}
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
{
return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
}
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
@@ -99,7 +113,8 @@ int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t fo
video_class->probe.bFormatIndex = formatindex;
video_class->probe.bFrameIndex = frameindex;
video_class->probe.dwMaxPayloadTransferSize = 0;
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
video_class->probe.dwFrameInterval = 333333;
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
}
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
@@ -107,7 +122,8 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
video_class->commit.bFormatIndex = formatindex;
video_class->commit.bFrameIndex = frameindex;
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
video_class->commit.dwFrameInterval = 333333;
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
}
int usbh_video_open(struct usbh_video *video_class,
@@ -124,6 +140,7 @@ int usbh_video_open(struct usbh_video *video_class,
bool found = false;
uint8_t formatidx = 0;
uint8_t frameidx = 0;
uint8_t step;
if (video_class->is_opened) {
return -EMFILE;
@@ -151,31 +168,65 @@ int usbh_video_open(struct usbh_video *video_class,
return -EINVAL;
}
/* Open video step:
* Get CUR request (probe)
* Set CUR request (probe)
* Get CUR request (probe)
* Get MAX request (probe)
* Get MIN request (probe)
* Get CUR request (probe)
* Set CUR request (commit)
*
*/
step = 0;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
}
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
}
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
}
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
}
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
}
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
goto errout;
}
step = 1;
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
goto errout;
}
step = 2;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
goto errout;
}
step = 3;
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MAX, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
if (ret < 0) {
goto errout;
}
step = 4;
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MIN, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
if (ret < 0) {
goto errout;
}
step = 5;
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
goto errout;
}
step = 6;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
goto errout;
}
step = 7;
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
if (ret < 0) {
goto errout;
}
step = 8;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = altsetting;
@@ -184,7 +235,7 @@ int usbh_video_open(struct usbh_video *video_class,
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
if (ret < 0) {
return ret;
goto errout;
}
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
@@ -202,6 +253,10 @@ int usbh_video_open(struct usbh_video *video_class,
video_class->is_opened = true;
video_class->current_format = format_type;
return ret;
errout:
USB_LOG_ERR("Fail to open video in step %u\r\n", step);
return ret;
}
int usbh_video_close(struct usbh_video *video_class)
@@ -292,14 +347,12 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t num_of_frames = 0xff;
uint8_t *p;
struct usbh_video *video_class = usb_malloc(sizeof(struct usbh_video));
struct usbh_video *video_class = usbh_video_class_alloc();
if (video_class == NULL) {
USB_LOG_ERR("Fail to alloc video_class\r\n");
return -ENOMEM;
}
memset(video_class, 0, sizeof(struct usbh_video));
usbh_video_devno_alloc(video_class);
video_class->hport = hport;
video_class->ctrl_intf = intf;
video_class->data_intf = intf + 1;
@@ -401,8 +454,6 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
if (video_class) {
usbh_video_devno_free(video_class);
if (video_class->isoin) {
usbh_pipe_free(video_class->isoin);
}
@@ -416,8 +467,7 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_video_stop(video_class);
}
memset(video_class, 0, sizeof(struct usbh_video));
usb_free(video_class);
usbh_video_class_free(video_class);
}
return ret;
@@ -433,132 +483,6 @@ static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t i
return 0;
}
#if 0
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
if ((stream->bufoffset == 0) && ((iso_packet[i].transfer_buffer[header_len] != 0xff) || (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8))) {
stream->bufoffset = 0;
continue;
}
data_offset = header_len;
data_len = iso_packet[i].actual_length - header_len;
/** do something here */
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) || (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
stream->bufoffset = 0;
continue;
}
/** do something here */
if (stream->video_one_frame_callback) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
/** do something here */
}
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
data_offset = header_len;
data_len = iso_packet[i].actual_length - header_len;
/** do something here */
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
/** do something here */
if (stream->video_one_frame_callback && (stream->bufoffset == stream->buflen)) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
/** do something here */
}
#endif
__WEAK void usbh_video_run(struct usbh_video *video_class)
{
}
@@ -567,10 +491,6 @@ __WEAK void usbh_video_stop(struct usbh_video *video_class)
{
}
__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len)
{
}
const struct usbh_class_driver video_ctrl_class_driver = {
.driver_name = "video_ctrl",
.connect = usbh_video_ctrl_connect,

View File

@@ -25,6 +25,8 @@ struct usbh_video_format {
struct usbh_videostreaming {
uint32_t bufoffset;
uint32_t buflen;
uint16_t width;
uint16_t heigth;
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
};
@@ -52,14 +54,8 @@ struct usbh_video {
extern "C" {
#endif
void usbh_video_inityuyv2rgb_table(void);
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len);
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_video_open(struct usbh_video *video_class,
uint8_t format_type,
@@ -70,10 +66,6 @@ int usbh_video_close(struct usbh_video *video_class);
void usbh_video_list_info(struct usbh_video *video_class);
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream);
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream);
void usbh_videostreaming_output(uint8_t *input, uint32_t input_len);
void usbh_video_run(struct usbh_video *video_class);
void usbh_video_stop(struct usbh_video *video_class);

View File

@@ -30,7 +30,7 @@ static struct usbd_endpoint rndis_ep_data[3];
#endif
/* Device data structure */
struct usbd_rndis_cfg_priv {
struct usbd_rndis_priv {
uint32_t drv_version;
uint32_t link_status;
uint32_t speed;
@@ -38,11 +38,12 @@ struct usbd_rndis_cfg_priv {
usb_eth_stat_t eth_state;
rndis_state_t init_state;
uint8_t mac[6];
} usbd_rndis_cfg = { .drv_version = 0x0001,
.link_status = NDIS_MEDIA_STATE_DISCONNECTED,
.speed = RNDIS_LINK_SPEED,
.init_state = rndis_uninitialized,
.mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
} g_usbd_rndis;
#if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
@@ -174,7 +175,7 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
resp->AfListOffset = 0;
resp->AfListSize = 0;
usbd_rndis_cfg.init_state = rndis_initialized;
g_usbd_rndis.init_state = rndis_initialized;
rndis_notify_rsp();
return 0;
@@ -187,7 +188,7 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
resp->MessageLength = 0;
usbd_rndis_cfg.init_state = rndis_uninitialized;
g_usbd_rndis.init_state = rndis_uninitialized;
return 0;
}
@@ -241,7 +242,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
break;
case OID_802_3_CURRENT_ADDRESS:
case OID_802_3_PERMANENT_ADDRESS:
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
infomation_len = 6;
break;
case OID_GEN_PHYSICAL_MEDIUM:
@@ -253,7 +254,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_CURRENT_PACKET_FILTER:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
infomation_len = 4;
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
@@ -261,7 +262,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
infomation_len = 4;
break;
case OID_GEN_RNDIS_CONFIG_PARAMETER:
@@ -301,19 +302,19 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_XMIT_OK:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
infomation_len = 4;
break;
case OID_GEN_RCV_OK:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
infomation_len = 4;
break;
case OID_GEN_RCV_ERROR:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
infomation_len = 4;
break;
case OID_GEN_XMIT_ERROR:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
infomation_len = 4;
break;
case OID_GEN_RCV_NO_BUFFER:
@@ -354,7 +355,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
param->ParameterValueOffset, param->ParameterValueLength);
break;
case OID_GEN_CURRENT_PACKET_FILTER:
if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
USB_LOG_WRN("PACKET_FILTER!\r\n");
resp->Status = RNDIS_STATUS_INVALID_DATA;
} else {
@@ -362,12 +363,12 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
/* Parameter starts at offset buf_offset of the req_id field */
filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
//usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
usbd_rndis_cfg.net_filter = *(uint32_t *)filter;
if (usbd_rndis_cfg.net_filter) {
usbd_rndis_cfg.init_state = rndis_data_initialized;
//g_usbd_rndis.net_filter = param->ParameterNameOffset;
g_usbd_rndis.net_filter = *(uint32_t *)filter;
if (g_usbd_rndis.net_filter) {
g_usbd_rndis.init_state = rndis_data_initialized;
} else {
usbd_rndis_cfg.init_state = rndis_initialized;
g_usbd_rndis.init_state = rndis_initialized;
}
}
break;
@@ -393,7 +394,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
{
rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
rndis_reset_cmplt_t *resp;
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
@@ -402,7 +403,7 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
resp->Status = RNDIS_STATUS_SUCCESS;
resp->AddressingReset = 1;
usbd_rndis_cfg.init_state = rndis_uninitialized;
g_usbd_rndis.init_state = rndis_uninitialized;
rndis_notify_rsp();
@@ -429,12 +430,12 @@ static void rndis_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
break;
case USBD_EVENT_CONFIGURED:
g_rndis_rx_data_length = 0;
g_rndis_tx_data_length = 0;
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
break;
@@ -458,7 +459,7 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
g_rndis_rx_data_length = hdr->DataLength;
usbd_rndis_data_recv((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
usbd_rndis_data_recv_done();
}
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
@@ -506,7 +507,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
uint8_t *buffer;
rndis_data_packet_t *hdr;
if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
return 0;
}
@@ -543,7 +544,11 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep, uint8_t mac[6])
{
memcpy(usbd_rndis_cfg.mac, mac, 6);
memcpy(g_usbd_rndis.mac, mac, 6);
g_usbd_rndis.drv_version = 0x0001;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;

View File

@@ -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);

View File

@@ -11,6 +11,8 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
static struct usbh_rndis g_rndis_class;
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
@@ -79,7 +81,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(rndis_query_msg_t);
setup->wLength = query_len + sizeof(rndis_query_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
if (ret < 0) {
@@ -131,7 +133,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(rndis_set_msg_t);
setup->wLength = info_len + sizeof(rndis_set_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
if (ret < 0) {
@@ -232,7 +234,6 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint32_t *oid_support_list;
@@ -242,11 +243,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t tmp_buffer[512];
uint8_t data[32];
struct usbh_rndis *rndis_class = usb_malloc(sizeof(struct usbh_rndis));
if (rndis_class == NULL) {
USB_LOG_ERR("Fail to alloc rndis_class\r\n");
return -ENOMEM;
}
struct usbh_rndis *rndis_class = &g_rndis_class;
memset(rndis_class, 0, sizeof(struct usbh_rndis));
@@ -363,7 +360,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
}
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rndis_run(rndis_class);
@@ -394,7 +391,6 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
memset(rndis_class, 0, sizeof(struct usbh_rndis));
usb_free(rndis_class);
}
return ret;

View File

@@ -13,7 +13,7 @@ struct usbh_rndis {
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
usbh_pipe_t intin; /* Notify endpoint */

View File

@@ -484,13 +484,10 @@ struct usb_msosv1_comp_id_function_descriptor {
};
struct usb_msosv1_descriptor {
uint8_t *string;
uint8_t string_len;
const uint8_t *string;
uint8_t vendor_code;
uint8_t *compat_id;
uint16_t compat_id_len;
uint8_t *comp_id_property;
uint16_t comp_id_property_len;
const uint8_t *compat_id;
const uint8_t **comp_id_property;
};
/* MS OS 2.0 Header descriptor */

View File

@@ -59,7 +59,11 @@ struct usbh_urb {
uint32_t start_frame;
usbh_complete_callback_t complete;
void *arg;
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
struct usbh_iso_frame_packet *iso_packet;
#else
struct usbh_iso_frame_packet iso_packet[0];
#endif
};
/**

View File

@@ -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 */

View File

@@ -6,9 +6,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
#include "usb_osal.h"
#endif
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
@@ -32,7 +29,7 @@ struct usbd_tx_rx_msg {
usbd_endpoint_callback cb;
};
USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
/** Setup packet */
USB_MEM_ALIGNX struct usb_setup_packet setup;
/** Pointer to data buffer */
@@ -45,41 +42,28 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
bool zlp_flag;
/** Pointer to registered descriptors */
#ifdef CONFIG_USBDEV_ADVANCE_DESC
struct usb_descriptor *descriptors;
const struct usb_descriptor *descriptors;
#else
const uint8_t *descriptors;
#endif
struct usb_msosv1_descriptor *msosv1_desc;
struct usb_msosv2_descriptor *msosv2_desc;
struct usb_bos_descriptor *bos_desc;
/* Buffer used for storing standard, class and vendor request data */
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
/** Variable to check whether the usb has been configured */
bool configured;
/** Currently selected configuration */
uint8_t configuration;
uint8_t speed;
#ifdef CONFIG_USBDEV_TEST_MODE
bool test_mode;
#endif
struct usbd_interface *intf[8];
uint8_t intf_offset;
} usbd_core_cfg;
usb_slist_t usbd_intf_head = USB_SLIST_OBJECT_INIT(usbd_intf_head);
static struct usb_msosv1_descriptor *msosv1_desc;
static struct usb_msosv2_descriptor *msosv2_desc;
static struct usb_bos_descriptor *bos_desc;
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
#if defined(CONFIG_USBDEV_TX_THREAD)
usb_osal_mq_t usbd_tx_mq;
usb_osal_thread_t usbd_tx_thread;
#endif
#if defined(CONFIG_USBDEV_RX_THREAD)
usb_osal_mq_t usbd_rx_mq;
usb_osal_thread_t usbd_rx_thread;
#endif
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
} g_usbd_core;
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
@@ -96,7 +80,7 @@ static void usbd_print_setup(struct usb_setup_packet *setup)
static bool is_device_configured(void)
{
return (usbd_core_cfg.configuration != 0);
return (g_usbd_core.configuration != 0);
}
/**
@@ -171,24 +155,24 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
switch (type) {
case USB_DESCRIPTOR_TYPE_DEVICE:
*data = (uint8_t *)usbd_core_cfg.descriptors->device_descriptor;
*len = usbd_core_cfg.descriptors->device_descriptor[0];
*data = (uint8_t *)g_usbd_core.descriptors->device_descriptor;
*len = g_usbd_core.descriptors->device_descriptor[0];
break;
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
usbd_core_cfg.speed = usbd_get_port_speed(0);
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
if (usbd_core_cfg.descriptors->hs_config_descriptor) {
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
*len = (usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
(usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
g_usbd_core.speed = usbd_get_port_speed(0);
if (g_usbd_core.speed == USB_SPEED_HIGH) {
if (g_usbd_core.descriptors->hs_config_descriptor) {
*data = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
*len = (g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
(g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
} else {
found = false;
}
} else {
if (usbd_core_cfg.descriptors->fs_config_descriptor) {
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
*len = (usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
(usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
if (g_usbd_core.descriptors->fs_config_descriptor) {
*data = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
*len = (g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
(g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
} else {
found = false;
}
@@ -203,20 +187,20 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
(*data)[3] = 0x04;
*len = 4;
} else if (index == USB_OSDESC_STRING_DESC_INDEX) {
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
if (g_usbd_core.descriptors->msosv1_descriptor) {
USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n");
*data = usbd_core_cfg.descriptors->msosv1_descriptor->string;
*len = usbd_core_cfg.descriptors->msosv1_descriptor->string_len;
*data = g_usbd_core.descriptors->msosv1_descriptor->string;
*len = g_usbd_core.descriptors->msosv1_descriptor->string_len;
} else {
}
} else {
if (usbd_core_cfg.descriptors->string_descriptor[index - 1]) {
str_len = strlen((const char *)usbd_core_cfg.descriptors->string_descriptor[index - 1]);
if (g_usbd_core.descriptors->string_descriptor[index - 1]) {
str_len = strlen((const char *)g_usbd_core.descriptors->string_descriptor[index - 1]);
(*data)[0] = str_len * 2 + 2;
(*data)[1] = 0x03;
for (uint16_t i = 0; i < str_len; i++) {
(*data)[i * 2 + 2] = usbd_core_cfg.descriptors->string_descriptor[index - 1][i];
(*data)[i * 2 + 2] = g_usbd_core.descriptors->string_descriptor[index - 1][i];
(*data)[i * 2 + 3] = 0;
}
@@ -227,28 +211,28 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
}
break;
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
if (usbd_core_cfg.descriptors->device_quality_descriptor) {
*data = (uint8_t *)usbd_core_cfg.descriptors->device_quality_descriptor;
*len = usbd_core_cfg.descriptors->device_quality_descriptor[0];
if (g_usbd_core.descriptors->device_quality_descriptor) {
*data = (uint8_t *)g_usbd_core.descriptors->device_quality_descriptor;
*len = g_usbd_core.descriptors->device_quality_descriptor[0];
} else {
found = false;
}
break;
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
if (usbd_core_cfg.descriptors->fs_other_speed_descriptor) {
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_other_speed_descriptor;
*len = (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
(usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
if (g_usbd_core.speed == USB_SPEED_HIGH) {
if (g_usbd_core.descriptors->fs_other_speed_descriptor) {
*data = (uint8_t *)g_usbd_core.descriptors->fs_other_speed_descriptor;
*len = (g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
(g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
} else {
found = false;
}
} else {
if (usbd_core_cfg.descriptors->hs_other_speed_descriptor) {
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_other_speed_descriptor;
*len = (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
(usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
if (g_usbd_core.descriptors->hs_other_speed_descriptor) {
*data = (uint8_t *)g_usbd_core.descriptors->hs_other_speed_descriptor;
*len = (g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
(g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
} else {
found = false;
}
@@ -285,25 +269,25 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
if (!msosv1_desc) {
if (!g_usbd_core.msosv1_desc) {
return false;
}
//*data = (uint8_t *)msosv1_desc->string;
memcpy(*data, (uint8_t *)msosv1_desc->string, msosv1_desc->string_len);
*len = msosv1_desc->string_len;
//*data = (uint8_t *)g_usbd_core.msosv1_desc->string;
memcpy(*data, (uint8_t *)g_usbd_core.msosv1_desc->string, g_usbd_core.msosv1_desc->string[0]);
*len = g_usbd_core.msosv1_desc->string[0];
return true;
} else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) {
USB_LOG_INFO("read BOS descriptor string\r\n");
if (!bos_desc) {
if (!g_usbd_core.bos_desc) {
return false;
}
//*data = bos_desc->string;
memcpy(*data, (uint8_t *)bos_desc->string, bos_desc->string_len);
*len = bos_desc->string_len;
//*data = g_usbd_core.bos_desc->string;
memcpy(*data, (uint8_t *)g_usbd_core.bos_desc->string, g_usbd_core.bos_desc->string_len);
*len = g_usbd_core.bos_desc->string_len;
return true;
}
/*
@@ -319,7 +303,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
return false;
}
p = (uint8_t *)usbd_core_cfg.descriptors;
p = (uint8_t *)g_usbd_core.descriptors;
cur_index = 0U;
@@ -351,7 +335,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
memcpy(*data, p, *len);
} else {
/* nothing found */
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
USB_LOG_ERR("descriptor <type:0x%02x,index:0x%02x> not found!\r\n", type, index);
}
return found;
@@ -377,13 +361,13 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
bool found = false;
uint8_t *p;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
if (g_usbd_core.speed == USB_SPEED_HIGH) {
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
} else {
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
}
#else
p = (uint8_t *)usbd_core_cfg.descriptors;
p = (uint8_t *)g_usbd_core.descriptors;
#endif
/* configure endpoints for this configuration/altsetting */
while (p[DESC_bLength] != 0U) {
@@ -441,13 +425,13 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
bool ret = false;
uint8_t *p;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
if (g_usbd_core.speed == USB_SPEED_HIGH) {
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
} else {
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
}
#else
p = (uint8_t *)usbd_core_cfg.descriptors;
p = (uint8_t *)g_usbd_core.descriptors;
#endif
USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting);
@@ -526,7 +510,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
}
} else if (value == USB_FEATURE_TEST_MODE) {
#ifdef CONFIG_USBDEV_TEST_MODE
usbd_core_cfg.test_mode = true;
g_usbd_core.test_mode = true;
usbd_execute_test_mode(setup);
#endif
}
@@ -547,7 +531,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
break;
case USB_REQUEST_GET_CONFIGURATION:
*data = (uint8_t *)&usbd_core_cfg.configuration;
*data = (uint8_t *)&g_usbd_core.configuration;
*len = 1;
break;
@@ -557,8 +541,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
if (!usbd_set_configuration(value, 0)) {
ret = false;
} else {
usbd_core_cfg.configuration = value;
usbd_core_cfg.configured = true;
g_usbd_core.configuration = value;
usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
usbd_event_handler(USBD_EVENT_CONFIGURED);
}
@@ -609,13 +592,11 @@ static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
case USB_REQUEST_GET_DESCRIPTOR:
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
USB_LOG_INFO("read hid report descriptor\r\n");
usb_slist_t *i;
usb_slist_for_each(i, &usbd_intf_head)
{
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core.intf[i];
if (intf->intf_num == intf_num) {
if (intf && (intf->intf_num == intf_num)) {
//*data = (uint8_t *)intf->hid_report_descriptor;
memcpy(*data, intf->hid_report_descriptor, intf->hid_report_descriptor_len);
*len = intf->hid_report_descriptor_len;
@@ -761,22 +742,19 @@ static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t
*/
static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
usb_slist_t *i;
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
usb_slist_for_each(i, &usbd_intf_head)
{
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core.intf[i];
if (intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
if (intf && intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
return intf->class_interface_handler(setup, data, len);
}
}
} else if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
usb_slist_for_each(i, &usbd_intf_head)
{
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core.intf[i];
if (intf->class_endpoint_handler) {
if (intf && intf->class_endpoint_handler) {
return intf->class_endpoint_handler(setup, data, len);
}
}
@@ -797,45 +775,56 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **
*/
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint32_t desclen;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
if (setup->bRequest == usbd_core_cfg.descriptors->msosv1_descriptor->vendor_code) {
if (g_usbd_core.descriptors->msosv1_descriptor) {
if (setup->bRequest == g_usbd_core.descriptors->msosv1_descriptor->vendor_code) {
switch (setup->wIndex) {
case 0x04:
USB_LOG_INFO("get Compat ID\r\n");
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->compat_id;
*len = usbd_core_cfg.descriptors->msosv1_descriptor->compat_id_len;
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->compat_id;
*len = desclen;
return 0;
case 0x05:
USB_LOG_INFO("get Compat id properties\r\n");
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property;
*len = usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property_len;
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
*len = desclen;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
return -1;
}
}
} else if (usbd_core_cfg.descriptors->msosv2_descriptor) {
if (setup->bRequest == usbd_core_cfg.descriptors->msosv2_descriptor->vendor_code) {
} else if (g_usbd_core.descriptors->msosv2_descriptor) {
if (setup->bRequest == g_usbd_core.descriptors->msosv2_descriptor->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv2_descriptor->compat_id;
*len = usbd_core_cfg.descriptors->msosv2_descriptor->compat_id_len;
*data = (uint8_t *)g_usbd_core.descriptors->msosv2_descriptor->compat_id;
*len = g_usbd_core.descriptors->msosv2_descriptor->compat_id_len;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
return -1;
}
}
} else if (usbd_core_cfg.descriptors->webusb_url_descriptor) {
if (setup->bRequest == usbd_core_cfg.descriptors->webusb_url_descriptor->vendor_code) {
} else if (g_usbd_core.descriptors->webusb_url_descriptor) {
if (setup->bRequest == g_usbd_core.descriptors->webusb_url_descriptor->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET Webusb url Descriptor\r\n");
*data = (uint8_t *)usbd_core_cfg.descriptors->webusb_url_descriptor->string;
*len = usbd_core_cfg.descriptors->webusb_url_descriptor->string_len;
*data = (uint8_t *)g_usbd_core.descriptors->webusb_url_descriptor->string;
*len = g_usbd_core.descriptors->webusb_url_descriptor->string_len;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
@@ -844,36 +833,42 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
}
}
#else
if (msosv1_desc) {
if (setup->bRequest == msosv1_desc->vendor_code) {
if (g_usbd_core.msosv1_desc) {
if (setup->bRequest == g_usbd_core.msosv1_desc->vendor_code) {
switch (setup->wIndex) {
case 0x04:
USB_LOG_INFO("get Compat ID\r\n");
//*data = (uint8_t *)msosv1_desc->compat_id;
memcpy(*data, msosv1_desc->compat_id, msosv1_desc->compat_id_len);
*len = msosv1_desc->compat_id_len;
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
memcpy(*data, g_usbd_core.msosv1_desc->compat_id, desclen);
*len = desclen;
return 0;
case 0x05:
USB_LOG_INFO("get Compat id properties\r\n");
//*data = (uint8_t *)msosv1_desc->comp_id_property;
memcpy(*data, msosv1_desc->comp_id_property, msosv1_desc->comp_id_property_len);
*len = msosv1_desc->comp_id_property_len;
//*data = (uint8_t *)msosv1_desc->comp_id_property[setup->wValue];
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
memcpy(*data, g_usbd_core.msosv1_desc->comp_id_property[setup->wValue], desclen);
*len = desclen;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
return -1;
}
}
} else if (msosv2_desc) {
if (setup->bRequest == msosv2_desc->vendor_code) {
} else if (g_usbd_core.msosv2_desc) {
if (setup->bRequest == g_usbd_core.msosv2_desc->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
//*data = (uint8_t *)msosv2_desc->compat_id;
memcpy(*data, msosv2_desc->compat_id, msosv2_desc->compat_id_len);
*len = msosv2_desc->compat_id_len;
memcpy(*data, g_usbd_core.msosv2_desc->compat_id, g_usbd_core.msosv2_desc->compat_id_len);
*len = g_usbd_core.msosv2_desc->compat_id_len;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
@@ -882,13 +877,10 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
}
}
#endif
usb_slist_t *i;
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core.intf[i];
usb_slist_for_each(i, &usbd_intf_head)
{
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
if (intf->vendor_handler && !intf->vendor_handler(setup, data, len)) {
if (intf && intf->vendor_handler && (intf->vendor_handler(setup, data, len) == 0)) {
return 0;
}
}
@@ -910,11 +902,20 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
case USB_REQUEST_STANDARD:
if (usbd_standard_request_handler(setup, data, len) < 0) {
#ifdef CONFIG_USBDEV_ADVANCE_DESC
if (g_usbd_core.speed == USB_SPEED_FULL) {
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
return false;
}
}
#else
#ifndef CONFIG_USB_HS
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
return false;
}
#endif
#endif
USB_LOG_ERR("standard request error\r\n");
usbd_print_setup(setup);
@@ -945,18 +946,16 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
static void usbd_class_event_notify_handler(uint8_t event, void *arg)
{
usb_slist_t *i;
usb_slist_for_each(i, &usbd_intf_head)
{
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core.intf[i];
if (arg) {
struct usb_interface_descriptor *desc = (struct usb_interface_descriptor *)arg;
if (intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
if (intf && intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
intf->notify_handler(event, arg);
}
} else {
if (intf->notify_handler) {
if (intf && intf->notify_handler) {
intf->notify_handler(event, arg);
}
}
@@ -986,11 +985,10 @@ void usbd_event_suspend_handler(void)
void usbd_event_reset_handler(void)
{
usbd_set_address(0);
usbd_core_cfg.configured = 0;
usbd_core_cfg.configuration = 0;
g_usbd_core.configuration = 0;
#ifdef CONFIG_USBDEV_TEST_MODE
usbd_core_cfg.test_mode = false;
g_usbd_core.test_mode = false;
#endif
struct usbd_endpoint_cfg ep0_cfg;
@@ -1008,7 +1006,7 @@ void usbd_event_reset_handler(void)
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
{
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
struct usb_setup_packet *setup = &g_usbd_core.setup;
memcpy(setup, psetup, 8);
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
@@ -1022,65 +1020,65 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
}
}
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
usbd_core_cfg.ep0_data_buf_residue = setup->wLength;
usbd_core_cfg.ep0_data_buf_len = setup->wLength;
usbd_core_cfg.zlp_flag = false;
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
g_usbd_core.ep0_data_buf_residue = setup->wLength;
g_usbd_core.ep0_data_buf_len = setup->wLength;
g_usbd_core.zlp_flag = false;
/* handle class request when all the data is received */
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, setup->wLength);
return;
}
/* Ask installed handler to process request */
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
return;
}
#ifdef CONFIG_USBDEV_TEST_MODE
/* send status in test mode, so do not execute downward, just return */
if (usbd_core_cfg.test_mode) {
usbd_core_cfg.test_mode = false;
if (g_usbd_core.test_mode) {
g_usbd_core.test_mode = false;
return;
}
#endif
/* Send smallest of requested and offered length */
usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, setup->wLength);
if (usbd_core_cfg.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
g_usbd_core.ep0_data_buf_residue = MIN(g_usbd_core.ep0_data_buf_len, setup->wLength);
if (g_usbd_core.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
USB_LOG_ERR("Request buffer too small\r\n");
return;
}
/* Send data or status to host */
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
/*
* Set ZLP flag when host asks for a bigger length and the data size is
* multiplier of USB_CTRL_EP_MPS, to indicate the transfer done after zlp
* sent.
*/
if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
usbd_core_cfg.zlp_flag = true;
if ((setup->wLength > g_usbd_core.ep0_data_buf_len) && (!(g_usbd_core.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
g_usbd_core.zlp_flag = true;
USB_LOG_DBG("EP0 Set zlp\r\n");
}
}
void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
{
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
struct usb_setup_packet *setup = &g_usbd_core.setup;
usbd_core_cfg.ep0_data_buf += nbytes;
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
g_usbd_core.ep0_data_buf += nbytes;
g_usbd_core.ep0_data_buf_residue -= nbytes;
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
if (usbd_core_cfg.ep0_data_buf_residue != 0) {
if (g_usbd_core.ep0_data_buf_residue != 0) {
/* Start sending the remain data */
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
} else {
if (usbd_core_cfg.zlp_flag == true) {
usbd_core_cfg.zlp_flag = false;
if (g_usbd_core.zlp_flag == true) {
g_usbd_core.zlp_flag = false;
/* Send zlp to host */
USB_LOG_DBG("EP0 Send zlp\r\n");
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
@@ -1100,18 +1098,18 @@ void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
{
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
struct usb_setup_packet *setup = &g_usbd_core.setup;
if (nbytes > 0) {
usbd_core_cfg.ep0_data_buf += nbytes;
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
g_usbd_core.ep0_data_buf += nbytes;
g_usbd_core.ep0_data_buf_residue -= nbytes;
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
if (usbd_core_cfg.ep0_data_buf_residue == 0) {
if (g_usbd_core.ep0_data_buf_residue == 0) {
/* Received all, send data to handler */
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
return;
}
@@ -1120,7 +1118,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
} else {
/* Start reading the remain data */
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
}
} else {
/* Read out status completely, do nothing */
@@ -1130,166 +1128,95 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
{
#ifndef CONFIG_USBDEV_TX_THREAD
if (tx_msg[ep & 0x7f].cb) {
tx_msg[ep & 0x7f].cb(ep, nbytes);
if (g_usbd_core.tx_msg[ep & 0x7f].cb) {
g_usbd_core.tx_msg[ep & 0x7f].cb(ep, nbytes);
}
#else
tx_msg[ep & 0x7f].nbytes = nbytes;
usb_osal_mq_send(usbd_tx_mq, (uintptr_t)&tx_msg[ep & 0x7f]);
#endif
}
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
{
#ifndef CONFIG_USBDEV_RX_THREAD
if (rx_msg[ep & 0x7f].cb) {
rx_msg[ep & 0x7f].cb(ep, nbytes);
}
#else
rx_msg[ep & 0x7f].nbytes = nbytes;
usb_osal_mq_send(usbd_rx_mq, (uintptr_t)&rx_msg[ep & 0x7f]);
#endif
}
#ifdef CONFIG_USBDEV_TX_THREAD
static void usbdev_tx_thread(void *argument)
{
struct usbd_tx_rx_msg *msg;
int ret;
while (1) {
ret = usb_osal_mq_recv(usbd_tx_mq, (uintptr_t *)&msg, 0xffffffff);
if (ret < 0) {
continue;
}
if (msg->cb) {
msg->cb(msg->ep, msg->nbytes);
}
if (g_usbd_core.rx_msg[ep & 0x7f].cb) {
g_usbd_core.rx_msg[ep & 0x7f].cb(ep, nbytes);
}
}
#endif
#ifdef CONFIG_USBDEV_RX_THREAD
static void usbdev_rx_thread(void *argument)
{
struct usbd_tx_rx_msg *msg;
int ret;
while (1) {
ret = usb_osal_mq_recv(usbd_rx_mq, (uintptr_t *)&msg, 0xffffffff);
if (ret < 0) {
continue;
}
if (msg->cb) {
msg->cb(msg->ep, msg->nbytes);
}
}
}
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
void usbd_desc_register(struct usb_descriptor *desc)
{
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
usbd_core_cfg.descriptors = desc;
usbd_core_cfg.intf_offset = 0;
g_usbd_core.descriptors = desc;
g_usbd_core.intf_offset = 0;
tx_msg[0].ep = 0x80;
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
rx_msg[0].ep = 0x00;
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
g_usbd_core.tx_msg[0].ep = 0x80;
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
g_usbd_core.rx_msg[0].ep = 0x00;
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
}
#else
void usbd_desc_register(const uint8_t *desc)
{
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
usbd_core_cfg.descriptors = desc;
usbd_core_cfg.intf_offset = 0;
g_usbd_core.descriptors = desc;
g_usbd_core.intf_offset = 0;
tx_msg[0].ep = 0x80;
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
rx_msg[0].ep = 0x00;
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
g_usbd_core.tx_msg[0].ep = 0x80;
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
g_usbd_core.rx_msg[0].ep = 0x00;
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
}
/* Register MS OS Descriptors version 1 */
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc)
{
msosv1_desc = desc;
g_usbd_core.msosv1_desc = desc;
}
/* Register MS OS Descriptors version 2 */
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc)
{
msosv2_desc = desc;
g_usbd_core.msosv2_desc = desc;
}
void usbd_bos_desc_register(struct usb_bos_descriptor *desc)
{
bos_desc = desc;
g_usbd_core.bos_desc = desc;
}
#endif
void usbd_add_interface(struct usbd_interface *intf)
{
intf->intf_num = usbd_core_cfg.intf_offset;
usb_slist_add_tail(&usbd_intf_head, &intf->list);
usbd_core_cfg.intf_offset++;
intf->intf_num = g_usbd_core.intf_offset;
g_usbd_core.intf[g_usbd_core.intf_offset] = intf;
g_usbd_core.intf_offset++;
}
void usbd_add_endpoint(struct usbd_endpoint *ep)
{
if (ep->ep_addr & 0x80) {
tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
} else {
rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
}
}
bool usb_device_is_configured(void)
{
return usbd_core_cfg.configured;
return g_usbd_core.configuration;
}
int usbd_initialize(void)
{
#ifdef CONFIG_USBDEV_TX_THREAD
usbd_tx_mq = usb_osal_mq_create(16);
if (usbd_tx_mq == NULL) {
return -1;
}
usbd_tx_thread = usb_osal_thread_create("usbd_tx", CONFIG_USBDEV_TX_STACKSIZE, CONFIG_USBDEV_TX_PRIO, usbdev_tx_thread, NULL);
if (usbd_tx_thread == NULL) {
return -1;
}
#endif
#ifdef CONFIG_USBDEV_RX_THREAD
usbd_rx_mq = usb_osal_mq_create(16);
if (usbd_rx_mq == NULL) {
return -1;
}
usbd_rx_thread = usb_osal_thread_create("usbd_rx", CONFIG_USBDEV_RX_STACKSIZE, CONFIG_USBDEV_RX_PRIO, usbdev_rx_thread, NULL);
if (usbd_rx_thread == NULL) {
return -1;
}
#endif
return usb_dc_init();
}
int usbd_deinitialize(void)
{
usbd_core_cfg.intf_offset = 0;
usb_slist_init(&usbd_intf_head);
g_usbd_core.intf_offset = 0;
usb_dc_deinit();
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
#endif
return 0;
}
@@ -1307,7 +1234,6 @@ __WEAK void usbd_event_handler(uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
usbd_configure_done_callback();
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;

View File

@@ -46,15 +46,12 @@ typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **da
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
extern usb_slist_t usbd_intf_head;
struct usbd_endpoint {
uint8_t ep_addr;
usbd_endpoint_callback ep_cb;
};
struct usbd_interface {
usb_slist_t list;
usbd_request_handler class_interface_handler;
usbd_request_handler class_endpoint_handler;
usbd_request_handler vendor_handler;
@@ -91,7 +88,6 @@ void usbd_add_interface(struct usbd_interface *intf);
void usbd_add_endpoint(struct usbd_endpoint *ep);
bool usb_device_is_configured(void);
void usbd_configure_done_callback(void);
int usbd_initialize(void);
int usbd_deinitialize(void);

View File

@@ -13,8 +13,8 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
@@ -270,23 +270,6 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
return 0;
}
#ifdef CONFIG_USBHOST_GET_STRING_DESC
void usbh_print_string(char *lead, uint8_t *str)
{
uint8_t string[64 + 1] = { 0 };
int len, i = 2, j = 0;
len = str[0];
while (i < len) {
string[j] = str[i];
i += 2;
j++;
}
USB_LOG_RAW("%s%s\r\n", lead, string);
}
#endif
static void usbh_print_hubport_info(struct usbh_hubport *hport)
{
USB_LOG_RAW("Device Descriptor:\r\n");
@@ -408,6 +391,54 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
return usbh_pipe_alloc(pipe, &ep_cfg);
}
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
{
struct usb_setup_packet *setup = hport->setup;
int ret;
uint8_t *src;
uint8_t *dst;
uint16_t len;
uint16_t i = 2;
uint16_t j = 0;
/* Get Manufacturer string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
if (ret < 0) {
return ret;
}
src = ep0_request_buffer;
dst = output;
len = src[0];
while (i < len) {
dst[j] = src[i];
i += 2;
j++;
}
return 0;
}
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting)
{
struct usb_setup_packet *setup = hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = intf;
setup->wIndex = altsetting;
setup->wLength = 0;
return usbh_control_transfer(hport->ep0, setup, NULL);
}
int usbh_enumerate(struct usbh_hubport *hport)
{
struct usb_interface_descriptor *intf_desc;
@@ -553,50 +584,37 @@ int usbh_enumerate(struct usbh_hubport *hport)
}
memcpy(hport->raw_config_desc, ep0_request_buffer, wTotalLength);
#ifdef CONFIG_USBHOST_GET_STRING_DESC
/* Get Manufacturer string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_MFC_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
uint8_t string_buffer[128];
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
/* Get Manufacturer string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
goto errout;
}
usbh_print_string("Manufacturer: ", ep0_request_buffer);
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
/* Get Product string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_PRODUCT_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
goto errout;
}
usbh_print_string("Product: ", ep0_request_buffer);
USB_LOG_INFO("Product: %s\r\n", string_buffer);
/* Get SerialNumber string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_SERIAL_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
goto errout;
}
usbh_print_string("SerialNumber: ", ep0_request_buffer);
USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
#endif
/* Select device configuration 1 */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
@@ -611,6 +629,19 @@ int usbh_enumerate(struct usbh_hubport *hport)
goto errout;
}
#ifdef CONFIG_USBHOST_MSOS_ENABLE
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
setup->wValue = 0;
setup->wIndex = 0x0004;
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
if (ret < 0 && (ret != -EPERM)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
#endif
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
/*search supported class driver*/
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
@@ -639,25 +670,6 @@ errout:
return ret;
}
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_for_each(hub_list, &hub_class_head)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
if (hport->dev_addr == dev_addr) {
return &hub->child[port];
}
}
}
}
return NULL;
}
void *usbh_find_class_instance(const char *devname)
{
struct usbh_hubport *hport;

View File

@@ -152,6 +152,7 @@ struct usbh_hubport {
#ifdef CONFIG_USBHOST_XHCI
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
#endif
usb_osal_thread_t thread;
};
struct usbh_hub {
@@ -168,6 +169,16 @@ struct usbh_hub {
struct usbh_hubport *parent;
};
/**
* @brief Activates an endpoint for a USB host pipe on a specific hub port.
*
* This function is responsible for activating the specified endpoint
* described by the given endpoint descriptor on the USB host pipe.
* @param pipe Pointer to the USB host pipe structure.
* @param hport Pointer to the USB hub port structure.
* @param ep_desc Pointer to the USB endpoint descriptor.
* @return On success will return 0, and others indicate fail.
*/
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
/**
@@ -182,8 +193,35 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
*/
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
/**
* @brief Retrieves a USB string descriptor from a specific hub port.
*
* This function is responsible for retrieving the USB string descriptor
* with the specified index from the USB device connected to the given hub port.
* The retrieved descriptor is stored in the output buffer provided.
*
* @param hport Pointer to the USB hub port structure.
* @param index Index of the string descriptor to retrieve.
* @param output Pointer to the buffer where the retrieved descriptor will be stored.
* @return On success will return 0, and others indicate fail.
*/
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output);
/**
* @brief Sets the alternate setting for a USB interface on a specific hub port.
*
* This function is responsible for setting the alternate setting of the
* specified USB interface on the USB device connected to the given hub port.
* The interface and alternate setting are identified by the respective parameters.
*
* @param hport Pointer to the USB hub port structure.
* @param intf Interface number to set the alternate setting for.
* @param altsetting Alternate setting value to set for the interface.
* @return On success will return 0, and others indicate fail.
*/
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
int usbh_initialize(void);
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
void *usbh_find_class_instance(const char *devname);
int lsusb(int argc, char **argv);

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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) {
}
}

View File

@@ -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) {
}
}

View File

@@ -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) {
}
}

View File

@@ -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;
}

View File

@@ -18,12 +18,24 @@
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USB_HS
#define MSC_MAX_MPS 512
#else
#define MSC_MAX_MPS 64
#endif
/*!< global descriptor */
static const uint8_t cdc_msc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x00),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -109,10 +121,31 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)

View File

@@ -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)

View File

@@ -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
View 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();
}

View File

@@ -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));

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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) {
}
}

View File

@@ -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;
}

View File

@@ -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++;
}
}

View File

@@ -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)
{
}

View File

@@ -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);
}

View File

@@ -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
View 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

View File

@@ -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;

View File

@@ -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)

View File

@@ -11,6 +11,7 @@
#define TEST_USBH_MSC_FATFS 0
#define TEST_USBH_AUDIO 0
#define TEST_USBH_VIDEO 0
#define TEST_USBH_CDC_ECM 0
#if TEST_USBH_CDC_ACM
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
@@ -254,6 +255,192 @@ find_class:
}
#endif
#if 0
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
if ((stream->bufoffset == 0) && ((iso_packet[i].transfer_buffer[header_len] != 0xff) || (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8))) {
stream->bufoffset = 0;
continue;
}
data_offset = header_len;
data_len = iso_packet[i].actual_length - header_len;
/** do something here */
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) || (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
stream->bufoffset = 0;
continue;
}
/** do something here */
if (stream->video_one_frame_callback) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
/** do something here */
}
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
data_offset = header_len;
data_len = iso_packet[i].actual_length - header_len;
/** do something here */
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
/** do something here */
if (stream->video_one_frame_callback && (stream->bufoffset == stream->buflen)) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
/** do something here */
}
#endif
#if TEST_USBH_CDC_ECM
#include "usbh_cdc_ecm.h"
#include "netif/etharp.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
#include "lwip/tcpip.h"
#if LWIP_DHCP
#include "lwip/dhcp.h"
#endif
struct netif g_cdc_ecm_netif;
static err_t usbh_cdc_ecm_if_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif->state = NULL;
netif->name[0] = 'E';
netif->name[1] = 'X';
netif->output = etharp_output;
netif->linkoutput = usbh_cdc_ecm_linkoutput;
return ERR_OK;
}
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
struct netif *netif = &g_cdc_ecm_netif;
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, cdc_ecm_class->mac, 6);
IP4_ADDR(&cdc_ecm_class->ipaddr, 0, 0, 0, 0);
IP4_ADDR(&cdc_ecm_class->netmask, 0, 0, 0, 0);
IP4_ADDR(&cdc_ecm_class->gateway, 0, 0, 0, 0);
netif = netif_add(netif, &cdc_ecm_class->ipaddr, &cdc_ecm_class->netmask, &cdc_ecm_class->gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
#if LWIP_DHCP
dhcp_start(netif);
#endif
}
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
struct netif *netif = &g_cdc_ecm_netif;
#if LWIP_DHCP
dhcp_stop(netif);
dhcp_cleanup(netif);
#endif
netif_set_down(netif);
netif_remove(netif);
}
#endif
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
}
@@ -313,4 +500,10 @@ void usbh_class_test(void)
#error "if you want to use iso, please contact with me"
usb_osal_thread_create("usbh_video", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_video_thread, NULL);
#endif
#if TEST_USBH_CDC_ECM
/* Initialize the LwIP stack */
tcpip_init(NULL, NULL);
usbh_cdc_ecm_lwip_thread_init(&g_cdc_ecm_netif);
#endif
}

View File

@@ -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;

View File

@@ -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();
}

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

View File

@@ -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** 要释放的内存地址

View File

@@ -4,8 +4,152 @@ USB CONFIG 宏
通用 CONFIG 宏
---------------------
CONFIG_USB_PRINTF
^^^^^^^^^^^^^^^^^^^^
USB log 功能,默认重定向到 printf需要注意USB log 会在中断中使用,因此重定向的 api 不允许阻塞。举例,如果使用的是 rt-thread请更换成 rt-kprintf
CONFIG_USB_DBG_LEVEL
^^^^^^^^^^^^^^^^^^^^^^
控制 log 的打印级别
CONFIG_USB_PRINTF_COLOR_ENABLE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
控制 log 颜色打印,默认开启
CONFIG_USB_ALIGN_SIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
USB buffer 的对齐大小,默认是 4。IP 在 dma 模式下可能对输入的 buffer有对齐要求一般是4如果是其他对齐方式请修改此值。
USB_NOCACHE_RAM_SECTION
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果芯片没有 cache 功能,此宏无效。如果有,则 USB 的输入输出 buffer 必须放在 nocache ram 中,保证数据一致性。
设备相关 CONFIG 宏
---------------------
CONFIG_USBDEV_REQUEST_BUFFER_LEN
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
控制传输接收和发送的 buffer 最大长度,默认是 256。
CONFIG_USBDEV_SETUP_LOG_PRINT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
使能或者关闭 setup 包的 dump 信息,默认关闭。
CONFIG_USBDEV_DESC_CHECK
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
暂时没有实现
CONFIG_USBDEV_TEST_MODE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
使能或者关闭 usb test mode
CONFIG_USBDEV_MSC_BLOCK_SIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
msc 临时缓存的大小缓存越大msc 的速度越高,默认等于 1个内存介质的扇区大小例如 sd卡 512flash 4K更改时需要是内存介质扇区的倍数。
虽然名字叫 block size但是跟内存介质的 block size不是一个意思。
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_MSC_PRODUCT_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_MSC_VERSION_STRING
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_MSC_THREAD
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
使能或者关闭 msc 线程默认关闭。usbd_msc_sector_read 和 usbd_msc_sector_write 默认是在中断中执行,所以如果开启了 os 建议开启此宏,那么,
usbd_msc_sector_read 和 usbd_msc_sector_write 就会在线程中执行。
CONFIG_USBDEV_MSC_PRIO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MSC 读写线程的优先级,默认是 4数值越小优先级越高
CONFIG_USBDEV_MSC_STACKSIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MSC 读写线程的堆栈大小,默认 2K 字节
CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rndis 控制传输最大接收和发送的长度,根据 RNDIS options list 决定最小长度,默认要大于等于 156
CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rndis 以太网帧的最大长度,默认 1536
CONFIG_USBDEV_RNDIS_VENDOR_ID
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_RNDIS_VENDOR_DESC
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONFIG_USBDEV_RNDIS_USING_LWIP
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rndis 与 lwip 接口的对接
主机相关 CONFIG 宏
---------------------
以下参数决定了支持的最大外部hub数量接口数每个接口的端点数和 altsetting 数量,更改此值会影响 ram 的大小,建议根据实际情况更改。
.. code-block:: C
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 6
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
以下参数决定了支持的 class 数目,更改此值会影响 ram 的大小,建议根据实际情况更改。
.. code-block:: C
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
CONFIG_USBHOST_PSC_PRIO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
主机插拔线程的优先级,默认是 4数值越小优先级越高
CONFIG_USBHOST_PSC_STACKSIZE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
主机插拔线程的堆栈大小,默认 2K 字节
CONFIG_USBHOST_REQUEST_BUFFER_LEN
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
控制传输能够接收或者发送的最大长度
CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
控制传输发送或者接收的超时时间,默认 1s
CONFIG_USBHOST_MSC_TIMEOUT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MSC 读写传输的超时时间,默认 5s

View File

@@ -103,7 +103,7 @@ usbd_bos_desc_register
usbd_add_interface
""""""""""""""""""""""""""""""""""""
``usbd_add_interface`` 添加一个接口驱动。
``usbd_add_interface`` 添加一个接口驱动。 **添加顺序必须按照描述符顺序**
.. code-block:: C
@@ -122,37 +122,24 @@ usbd_add_endpoint
- **ep** 端点句柄
usb_device_is_configured
""""""""""""""""""""""""""""""""""""
``usb_device_is_configured`` 用来检查 USB 设备是否被配置(枚举)。
.. code-block:: C
bool usb_device_is_configured(void);
- **return** 配置状态, 0 表示未配置, 1 表示配置成功
usbd_configure_done_callback
""""""""""""""""""""""""""""""""""""
``usbd_configure_done_callback`` 在执行 set_configuration 命令后触发,表示配置完成,用户需要实现该函数, **此函数一般用作启动第一次数据接收**,如果没有使用到 out 端点,则函数为空即可。
.. code-block:: C
bool usbd_configure_done_callback(void);
.. warning:: msc 端点不需要在该函数中手动启动,协议栈会自动启动第一次接收
usbd_initialize
""""""""""""""""""""""""""""""""""""
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。 **如果使用 os必须放在线程中执行**
.. code-block:: C
int usbd_initialize(void);
usbd_event_handler
""""""""""""""""""""""""""""""""""""
``usbd_event_handler`` 是协议栈中中断或者协议栈一些状态的回调函数。大部分 IP 仅支持 USBD_EVENT_RESET 和 USBD_EVENT_CONFIGURED
.. code-block:: C
void usbd_event_handler(uint8_t event);
CDC ACM
-----------------

View File

@@ -82,11 +82,13 @@ hubport 结构体
const char *iManufacturer;
const char *iProduct;
const char *iSerialNumber;
#if 0
uint8_t* raw_config_desc;
#endif
USB_MEM_ALIGNX struct usb_setup_packet setup;
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
#ifdef CONFIG_USBHOST_XHCI
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
#endif
usb_osal_thread_t thread;
};
hub 结构体
@@ -101,12 +103,11 @@ hub 结构体
uint8_t index;
uint8_t hub_addr;
usbh_pipe_t intin;
USB_MEM_ALIGNX uint8_t int_buffer[1];
uint8_t *int_buffer;
struct usbh_urb intin_urb;
struct usb_hub_descriptor hub_desc;
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_hubport *parent;
usb_slist_t hub_event_list;
};
usbh_initialize

View File

@@ -153,19 +153,19 @@ usbh_roothub_control
- **buf** 接收缓冲区
- **return** 返回 0 表示正确,其他表示错误
usbh_ep0_pipe_reconfigure
usbh_ep_pipe_reconfigure
""""""""""""""""""""""""""""""""""""
``usbh_ep0_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**
``usbh_ep_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**
.. code-block:: C
int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
- **pipe** pipe 句柄
- **dev_addr** 端点所在设备地址
- **ep_mps** 端点最大包长
- **speed** 端点所在设备的速度
- **mult** 端点一次传输个数
- **return** 返回 0 表示正确,其他表示错误
usbh_pipe_alloc

View File

@@ -6,8 +6,8 @@ project = 'CherryUSB'
copyright = '2022, sakumisu'
author = 'sakumisu'
release = '0.9'
version = '0.9.0'
release = '0.10.0'
version = '0.10.0'
# -- General configuration

View File

@@ -8,23 +8,41 @@ CherryUSB 使用指南
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的 USB 主从协议栈。同时 CherryUSB 具有以下优点:
- 代码精简,并且内存占用极小,而且还可进一步的裁剪
- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律
- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类
- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程
- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。
- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制
- 能够达到 USB 硬件理论带宽
**易于学习 USB**
从机协议栈整体执行流程
为了方便用户学习 USB 基本知识、枚举、驱动加载、IP 驱动,因此,编写的代码具备以下优点
- 代码精简,逻辑简单,无复杂 C 语言语法
- 树状化编程,代码层层递进
- Class 驱动和 porting 驱动模板化、精简化
- API 分类清晰(从机:初始化、注册类、命令回调类、数据收发类;主机:初始化、查找类、数据收发类)
**易于使用 USB**
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma因此设计的数据收发类接口具备以下优点
- 等价于使用 uart tx dma/uart rx dma
- 收发长度没有限制,用户不需要关心 USB 分包过程porting 驱动做分包过程)
**易于发挥 USB 性能**
考虑到 USB 性能问题,尽量达到 USB 硬件理论带宽,因此,设计的数据收发类接口具备以下优点:
- Porting 驱动直接对接寄存器,无抽象层封装
- Memory zero copy
- IP 如果带 DMA 则使用 DMA 模式DMA 带硬件分包功能)
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
- 分包功能在中断中处理
**从机协议栈整体执行流程**
.. figure:: usbdev.svg
主机协议栈整体执行流程
**主机协议栈整体执行流程**
.. figure:: usbhost.svg
其他相关链接
**其他相关链接**
- **CherryUSB 大纲** https://www.bilibili.com/video/BV1st4y1H7K2
- **从机协议栈视频教程** https://www.bilibili.com/video/BV1Ef4y1t73d
@@ -35,10 +53,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
:maxdepth: 1
:caption: 快速上手
quick_start/bl702
quick_start/stm32
quick_start/hpm
quick_start/es32
quick_start/index
quick_start/rt-thread/rtthread
quick_start/other_chip
@@ -59,7 +74,6 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
api/api_device
api/api_host
api/api_port
api/api_common
api/api_config
.. toctree::

View File

@@ -1,6 +0,0 @@
基于 BL 系列开发指南
=========================
BL 系列 USB 的开发主要使用 bl_mcu_sdk参考 `bl_mcu_sdk <https://github.com/bouffalolab/bl_mcu_sdk>`_
USB 的相关应用位于 `examples/usbdev``examples/usbhost` 目录下,环境搭建完成后,即可编译使用。

View File

@@ -1,84 +0,0 @@
基于 ES32F369 开发指南
=========================
ES32F3xx 系列单片机中 USB 外设使用标准的 musb ip并且拥有 usb device 和 usb host 功能。本章主要介绍如何在东软载波的 ES32F369x 开发板中使用 CherryUSB。
在使用之前需要从 essemi 官网下载 `keil 芯片支持包 <http://www.essemi.com/index/product/detail?id=796>`_ 并安装,
工程样例试用
-----------------------
在 CherryUSB demo 目录下已经有主机跟从机的样例,在有板子的情况下,可以先跑工程样例,试用一下。
- 进入 MDK-ARM 目录下,双击 `example.uvprojx` 打开工程,选择好调试器后,编译烧录即可。
- 如果是从机,默认提供的是 cdc acm 的示例,代码烧录以后,将 usb 线插到 板子的丝印为 USB-OTG 口,并接上电脑,按下复位键,电脑便会枚举出一个串口。打开串口,勾选 DTR 可以接收数据,在发送缓冲区填入数据并发送,调试器的串口便可以打印出接收的长度和数据。
- 如果是主机,则需要一个 usb 母口转接线,并接入相关 usb 设备就可以进行测试了。比如接上鼠标、U盘、4G 网卡等等。
USB Device 移植要点
-----------------------
针对自定义的工程移植,需要按照以下步骤:
- 准备好可以进行调试打印的工程,并且实现 `printf``malloc``free` 函数(也可以直接勾选 Use microlib 来使用)。
- 拷贝 CherryUSB 源码到工程里
- 添加 CherryUSB 源码和头文件路径,其中 `usbd_core.c``usb_dc_musb.c` 为必须添加项。
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径。所以根目录下的文件仅作为参考,不要添加根目录下的头文件。
.. figure:: img/es322.png
.. figure:: img/es323.png
- 实现 `usb_dc_low_level_init` 函数,该函数主要负责 USB 时钟、引脚、中断的初始化。例如
.. code-block:: C
void usb_dc_low_level_init(void)
{
ald_pmu_perh_power_config(PMU_POWER_USB, ENABLE);
ald_cmu_perh_clock_config(CMU_PERH_USB, ENABLE);
ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE);
ald_cmu_usb_clock_config(CMU_USB_CLOCK_SEL_HOSC, CMU_USB_DIV_1);
ald_rmu_reset_periperal(RMU_PERH_USB);
ald_mcu_irq_config(USB_INT_IRQn, 2, 2, ENABLE);
ald_mcu_irq_config(USB_DMA_IRQn, 2, 2, ENABLE);
usb_pin_init();
}
- 描述符的注册、class的注册、接口的注册、端点中断的注册。不会的参考 demo 下的 template 。
- 调用 `usbd_initialize` 初始化 usb 硬件。
- 正常使用。
USB Host 移植要点
-----------------------
针对自定义的工程移植,需要以下步骤:
- 准备好可以进行调试打印的带 FreeRTOS 或者 RT-Thread 的工程,并且实现 `printf``malloc``free` 函数(也可以直接勾选 Use microlib 来使用)。
- 拷贝 CherryUSB 源码到工程里
- 添加 CherryUSB 源码和头文件路径,其中 `usbh_core.c``usb_hc_musb.c` 、 osal 下的文件为必须添加项,根据不同的 os 添加对应的文件。
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h` ,并添加相应的目录头文件路径。所以根目录下的文件仅作为参考,不要添加根目录下的头文件。
.. figure:: img/es324.png
.. figure:: img/es325.png
- 由于是作为主机,推荐添加所有的 class功能全面。当然如果只用一个 class ,就添加一个。
- 实现 `usb_hc_low_level_init` 函数,该函数主要负责 USB 时钟、引脚、中断的初始化。例如
.. code-block:: C
void usb_hc_low_level_init(void)
{
ald_pmu_perh_power_config(PMU_POWER_USB, ENABLE);
ald_cmu_perh_clock_config(CMU_PERH_USB, ENABLE);
ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE);
ald_cmu_usb_clock_config(CMU_USB_CLOCK_SEL_HOSC, CMU_USB_DIV_1);
ald_rmu_reset_periperal(RMU_PERH_USB);
ald_mcu_irq_config(USB_INT_IRQn, 2, 2, ENABLE);
ald_mcu_irq_config(USB_DMA_IRQn, 2, 2, ENABLE);
usb_pin_init();
}
- 调用 `usbh_initialize` 初始化 usb 硬件。
- 此时编译会报错,因为协议栈中为每个 class 都添加了测试 demo文件在 `usb_host.c` 中,如果不想要,可以直接删除。
- 正常使用。

View File

@@ -1,6 +0,0 @@
基于 HPM 系列开发指南
=========================
HPM 系列 USB 的开发主要使用 hpm_sdk ,参考 `hpm sdk <https://github.com/hpmicro/hpm_sdk>`_
USB 的相关应用位于 `samples/cherryusb` 目录下,环境搭建完成后,即可编译使用。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,13 +1,41 @@
基于 STM32F1/F4/H7 开发指南
=============================
基于现有 demo 快速验证
=========================
本节是基于 STM32 三个系列芯片的使用,涵盖 F1/F4/H7其余芯片基本类似不再赘述具体区别有
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
基于 bouffalolab 系列芯片
---------------------------
仓库参考https://github.com/CherryUSB/cherryusb_bouffalolab
- BL702 是一个 USB2.0 全速芯片,共 8 个端点包含端点0。仅支持从机。
- BL616/BL808 是一个 USB2.0 并且内置高速 PHY 芯片,共 5个端点包含端点0。支持主从机。
- USB 的相关应用位于 `examples/usbdev``examples/usbhost` 目录下,根据官方环境搭建完成后,即可编译使用。
基于 ST 系列芯片
---------------------------
仓库参考https://github.com/CherryUSB/cherryusb_stm32
默认提供以下 demo 工程:
- F103 使用 fsdev ip
- F429 主从使用 hs port,并且均用 dma 模式
- H7 设备使用 fs port主机使用 hs port并且主机带 cache 支持
默认删除 Drivers ,所以需要使用 stm32cubemx 生成一下 Drivers 目录下的文件demo 底下提供了 **stm32xxx.ioc** 文件,双击打开,点击 **Generate Code** 即可。
.. caution:: 生成完以后,请使用 git reset 功能将被覆盖的 `main.c``stm32xxx_it.c` 文件撤回,禁止被 cubemx 覆盖。
涵盖 F1/F4/H7其余芯片基本类似不再赘述具体区别有
- usb ip 区别F1使用 fsdevF4/H7使用 dwc2
- dwc2 ip 区别: fs port(引脚是 PA11/PA12) 和 hs port(引脚是 PB14/PB15), 其中 hs port 默认全速可以接外部PHY 形成高速主机,并且带 dma 功能
- F4 与 H7 cache 区别、USB BASE 区别
如果是 STM32F7/STM32H7 这种带 cache 功能,需要将 usb 使用到的 ram 定位到 no cache ram 区域。举例如下
.. code-block:: C
@@ -36,22 +64,10 @@
.. caution :: 如果使用 STM32F7 或者 STM32H7, 请在 CFLAG 中添加 STM32F7 或者 STM32H7 宏定义,否则无法枚举
工程样例试用
-----------------------
默认提供以下 demo 工程:
- F103 使用 fsdev ip
- F429 主从使用 hs port,并且均用 dma 模式
- H7 设备使用 fs port主机使用 hs port并且主机带 cache 支持
默认删除 Drivers ,所以需要使用 stm32cubemx 生成一下 Drivers 目录下的文件demo 底下提供了 **stm32xxx.ioc** 文件,双击打开,点击 **Generate Code** 即可。
.. caution:: 生成完以后,请使用 git reset 功能将被覆盖的 `main.c``stm32xxx_it.c` 文件撤回,禁止被 cubemx 覆盖。
.. figure:: img/keil.png
USB Device 移植要点
-----------------------
^^^^^^^^^^^^^^^^^^^^^^
- 使用 **stm32cubemx** 创建工程,配置基本的 RCC、UART (作为log使用)
@@ -104,7 +120,7 @@ USB Device 移植要点
.. figure:: img/stm32_15.png
USB Host 移植要点
-----------------------
^^^^^^^^^^^^^^^^^^^^^^
前面 7 步与 Device 一样。需要注意host 驱动只支持带 dma 的 hs port (引脚是 PB14/PB15),所以 fs port (引脚是 PA11/PA12)不做支持(没有 dma 你玩什么主机)。
@@ -129,4 +145,12 @@ USB Host 移植要点
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
.. figure:: img/stm32_21.png
.. figure:: img/stm32_21.png
基于 HPMicro 系列芯片
---------------------------
仓库参考https://github.com/CherryUSB/cherryusb_hpmicro
- HPM 系列芯片均 USB 2.0 并且内置高速 PHY支持主从机
- USB 的相关应用位于 `samples/cherryusb` ,根据官方环境搭建完成后,即可编译使用。

View File

@@ -9,13 +9,19 @@
#include <stdint.h>
#include <string.h>
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
typedef void *usb_osal_thread_t;
typedef void *usb_osal_sem_t;
typedef void *usb_osal_mutex_t;
typedef void *usb_osal_mq_t;
typedef void (*usb_thread_entry_t)(void *argument);
/*
* Task with smaller priority value indicates higher task priority
*/
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
void usb_osal_thread_delete(usb_osal_thread_t thread);
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
void usb_osal_sem_delete(usb_osal_sem_t sem);

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