60 Commits

Author SHA1 Message Date
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
108 changed files with 6355 additions and 8547 deletions

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/)
@@ -150,13 +164,13 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.9.0 |
|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 |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.8.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 |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.9.0 |
|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 |

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/)
@@ -148,13 +162,13 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.9.0 |
|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 |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.8.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 |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.9.0 |
|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 |

View File

@@ -114,6 +114,11 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
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')
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 0x001001
/* ================ 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,13 @@
#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_MAX_RNDIS_CLASS 1
#define CONFIG_USBHOST_DEV_NAMELEN 16
#ifndef CONFIG_USBHOST_PSC_PRIO
@@ -154,7 +142,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

@@ -302,8 +302,7 @@ struct cdc_ecm_descriptor {
/*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,87 +358,20 @@ 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) \
/* 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 */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* 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 */ \
0x02, /* 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
/*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) \
#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 */ \
@@ -495,80 +427,14 @@ 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_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
}

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;

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)
{
@@ -309,21 +309,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 cdc_acm_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 +388,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 +405,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 +430,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 +461,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 +606,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 +627,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);

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, 0xffffffff);
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,34 @@
#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 *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)
@@ -278,14 +279,12 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
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;
@@ -349,8 +348,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 +361,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

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

@@ -7,10 +7,38 @@
#include "usbh_rndis.h"
#include "rndis_protocol.h"
#define DEV_FORMAT "/dev/rndis"
#define DEV_FORMAT "/dev/rndis%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
static struct usbh_rndis g_rndis_class[CONFIG_USBHOST_MAX_RNDIS_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_rndis *usbh_rndis_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_RNDIS_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_rndis_class[devno], 0, sizeof(struct usbh_rndis));
g_rndis_class[devno].minor = devno;
return &g_rndis_class[devno];
}
}
return NULL;
}
static void usbh_rndis_class_free(struct usbh_rndis *rndis_class)
{
int devno = rndis_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(rndis_class, 0, sizeof(struct usbh_rndis));
}
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
@@ -232,7 +260,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,14 +269,12 @@ 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));
struct usbh_rndis *rndis_class = usbh_rndis_class_alloc();
if (rndis_class == NULL) {
USB_LOG_ERR("Fail to alloc rndis_class\r\n");
return -ENOMEM;
}
memset(rndis_class, 0, sizeof(struct usbh_rndis));
rndis_class->hport = hport;
rndis_class->ctrl_intf = intf;
rndis_class->data_intf = intf + 1;
@@ -363,7 +388,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);
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, rndis_class->minor);
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rndis_run(rndis_class);
@@ -393,8 +418,7 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_rndis_stop(rndis_class);
}
memset(rndis_class, 0, sizeof(struct usbh_rndis));
usb_free(rndis_class);
usbh_rndis_class_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

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

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

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(uint8_t busid)
{
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)

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,6 +101,8 @@ static const uint8_t cdc_descriptor[] = {
0x00
};
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
#ifdef RT_USING_LWIP
#include <rtthread.h>
#include <rtdevice.h>
@@ -102,13 +110,6 @@ static const uint8_t cdc_descriptor[] = {
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 +140,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 +156,138 @@ 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"
/*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
static struct netif rndis_netif; //network interface
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);
/* 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 +295,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();
}
void hid_keyboard_test(void)
{
uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
int ret = usbd_ep_start_write(HID_INT_EP, sendbuffer, 8);
void hid_keyboard_test(uint8_t busid)
{
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
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 ------------------------------------------------------------------*/

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

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

@@ -254,6 +254,132 @@ 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
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
}

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

@@ -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
@@ -59,7 +77,6 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
api/api_device
api/api_host
api/api_port
api/api_common
api/api_config
.. toctree::

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -36,6 +36,8 @@
.. caution :: 如果使用 STM32F7 或者 STM32H7, 请在 CFLAG 中添加 STM32F7 或者 STM32H7 宏定义,否则无法枚举
.. figure:: img/keil.png
工程样例试用
-----------------------

View File

@@ -15,7 +15,11 @@ 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);

View File

@@ -14,10 +14,15 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
{
TaskHandle_t htask = NULL;
stack_size /= sizeof(StackType_t);
xTaskCreate(entry, name, stack_size, args, prio, &htask);
xTaskCreate(entry, name, stack_size, args, configMAX_PRIORITIES - 1 - prio, &htask);
return (usb_osal_thread_t)htask;
}
void usb_osal_thread_delete(usb_osal_thread_t thread)
{
vTaskDelete(thread);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
return (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count);
@@ -38,9 +43,13 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
int ret;
ret = xSemaphoreGiveFromISR((SemaphoreHandle_t)sem, &xHigherPriorityTaskWoken);
if (ret == pdPASS) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
if (xPortIsInsideInterrupt()) {
ret = xSemaphoreGiveFromISR((SemaphoreHandle_t)sem, &xHigherPriorityTaskWoken);
if (ret == pdPASS) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
} else {
ret = xSemaphoreGive((SemaphoreHandle_t)sem);
}
return (ret == pdPASS) ? 0 : -ETIMEDOUT;

View File

@@ -16,6 +16,15 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
return (usb_osal_thread_t)htask;
}
void usb_osal_thread_delete(usb_osal_thread_t thread)
{
if (thread == NULL) {
return;
}
rt_thread_delete(thread);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
return (usb_osal_sem_t)rt_sem_create("usbh_sem", initial_count, RT_IPC_FLAG_FIFO);

View File

@@ -17,6 +17,11 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
return task_handle;
}
void usb_osal_thread_delete(usb_osal_thread_t thread)
{
aos_task_exit(0);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
aos_sem_t sem = NULL;

View File

@@ -175,8 +175,6 @@ struct dwc2_ep_state {
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_type; /* Endpoint type */
uint8_t ep_stalled; /* Endpoint stall flag */
uint8_t ep_enable; /* Endpoint enable */
uint8_t ep_busy; /* Endpoint busy */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
@@ -535,11 +533,51 @@ __WEAK void usb_dc_low_level_deinit(void)
int usb_dc_init(void)
{
int ret;
uint8_t fsphy_type;
uint8_t hsphy_type;
uint8_t dma_support;
uint8_t endpoints;
memset(&g_dwc2_udc, 0, sizeof(struct dwc2_udc));
usb_dc_low_level_init();
/*
Full-Speed PHY Interface Type (FSPhyType)
2'b00: Full-speed interface not supported
2'b01: Dedicated full-speed interface
2'b10: FS pins shared with UTMI+ pins
2'b11: FS pins shared with ULPI pins
High-Speed PHY Interface Type (HSPhyType)
2'b00: High-Speed interface not supported
2'b01: UTMI+
2'b10: ULPI
2'b11: UTMI+ and ULPI
Architecture (OtgArch)
2'b00: Slave-Only
2'b01: External DMA
2'b10: Internal DMA
Others: Reserved
*/
fsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 8)) >> 8);
hsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 6)) >> 6);
dma_support = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 3)) >> 3);
endpoints = ((USB_OTG_GLB->GHWCFG2 & (0x0f << 10)) >> 10) + 1;
USB_LOG_INFO("========== dwc2 udc params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n", USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n", USB_OTG_GLB->GSNPSID);
USB_LOG_INFO("GHWCFG1:%08x\r\n", USB_OTG_GLB->GHWCFG1);
USB_LOG_INFO("GHWCFG2:%08x\r\n", USB_OTG_GLB->GHWCFG2);
USB_LOG_INFO("GHWCFG3:%08x\r\n", USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n", USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("dwc2 fsphy type:%d, hsphy type:%d, dma support:%d\r\n", fsphy_type, hsphy_type, dma_support);
USB_LOG_INFO("dwc2 has %d endpoints, default config: %d endpoints\r\n", endpoints, USB_NUM_BIDIR_ENDPOINTS);
USB_LOG_INFO("=================================\r\n");
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
@@ -617,7 +655,9 @@ int usb_dc_init(void)
/* Enable interrupts matching to the Device mode ONLY */
USB_OTG_GLB->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT;
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT |
USB_OTG_GINTMSK_IISOIXFRM | USB_OTG_GINTMSK_PXFRM_IISOOXFRM;
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
if ((USB_OTG_GLB->GHWCFG2 & (0x3U << 3)) == 0U) {
USB_LOG_ERR("This dwc2 version does not support dma, so stop working\r\n");
@@ -705,7 +745,6 @@ uint8_t usbd_get_port_speed(const uint8_t port)
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
uint16_t ep_mps;
if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
USB_LOG_ERR("Ep addr %d overflow\r\n", ep_cfg->ep_addr);
@@ -715,42 +754,28 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
g_dwc2_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
g_dwc2_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
g_dwc2_udc.out_ep[ep_idx].ep_enable = true;
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & (uint32_t)(1UL << (16 + ep_idx));
ep_mps = ep_cfg->ep_mps;
if (ep_idx == 0) {
switch (ep_cfg->ep_mps) {
case 8:
ep_mps = EP_MPS_8;
break;
case 16:
ep_mps = EP_MPS_16;
break;
case 32:
ep_mps = EP_MPS_32;
break;
case 64:
ep_mps = EP_MPS_64;
break;
}
if ((USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP) == 0) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (ep_cfg->ep_mps & USB_OTG_DOEPCTL_MPSIZ) |
((uint32_t)ep_cfg->ep_type << 18) |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
USB_OTG_DOEPCTL_USBAEP;
}
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (ep_mps & USB_OTG_DOEPCTL_MPSIZ) |
((uint32_t)ep_cfg->ep_type << 18) |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
USB_OTG_DOEPCTL_USBAEP;
} else {
g_dwc2_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
g_dwc2_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
g_dwc2_udc.in_ep[ep_idx].ep_enable = true;
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << ep_idx);
USB_OTG_INEP(ep_idx)->DIEPCTL |= (ep_cfg->ep_mps & USB_OTG_DIEPCTL_MPSIZ) |
((uint32_t)ep_cfg->ep_type << 18) | (ep_idx << 22) |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
USB_OTG_DIEPCTL_USBAEP;
if ((USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0) {
USB_OTG_INEP(ep_idx)->DIEPCTL |= (ep_cfg->ep_mps & USB_OTG_DIEPCTL_MPSIZ) |
((uint32_t)ep_cfg->ep_type << 18) | (ep_idx << 22) |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
USB_OTG_DIEPCTL_USBAEP;
}
dwc2_flush_txfifo(ep_idx);
}
return 0;
}
@@ -758,28 +783,48 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
int usbd_ep_close(const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
volatile uint32_t count = 0U;
if (USB_EP_DIR_IS_OUT(ep)) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
//USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
if (USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
/* Wait for endpoint disabled interrupt */
count = 0;
do {
if (++count > 50000) {
break;
}
} while ((USB_OTG_OUTEP(ep_idx)->DOEPINT & USB_OTG_DOEPINT_EPDISD) != USB_OTG_DOEPINT_EPDISD);
/* Clear and unmask endpoint disabled interrupt */
USB_OTG_OUTEP(ep_idx)->DOEPINT |= USB_OTG_DOEPINT_EPDISD;
}
USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep_idx & 0x07)) << 16));
USB_OTG_DEV->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep_idx & 0x07)) << 16));
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~(USB_OTG_DOEPCTL_USBAEP |
USB_OTG_DOEPCTL_MPSIZ |
USB_OTG_DOEPCTL_SD0PID_SEVNFRM |
USB_OTG_DOEPCTL_EPTYP);
USB_OTG_OUTEP(ep_idx)->DOEPCTL = 0;
} else {
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
//USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
if (USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
/* Wait for endpoint disabled interrupt */
count = 0;
do {
if (++count > 50000) {
break;
}
} while ((USB_OTG_INEP(ep_idx)->DIEPINT & USB_OTG_DIEPINT_EPDISD) != USB_OTG_DIEPINT_EPDISD);
/* Clear and unmask endpoint disabled interrupt */
USB_OTG_INEP(ep_idx)->DIEPINT |= USB_OTG_DIEPINT_EPDISD;
}
USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07)));
USB_OTG_DEV->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07)));
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~(USB_OTG_DIEPCTL_USBAEP |
USB_OTG_DIEPCTL_MPSIZ |
USB_OTG_DIEPCTL_TXFNUM |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
USB_OTG_DIEPCTL_EPTYP);
USB_OTG_INEP(ep_idx)->DIEPCTL = 0;
}
return 0;
}
@@ -843,14 +888,15 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
if (!data && data_len) {
return -1;
}
if (!g_dwc2_udc.in_ep[ep_idx].ep_enable) {
if (USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
return -2;
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
if ((uint32_t)data & 0x03) {
if (ep_idx && !(USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_MPSIZ)) {
return -3;
}
#endif
if ((uint32_t)data & 0x03) {
return -4;
}
g_dwc2_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_dwc2_udc.in_ep[ep_idx].xfer_len = data_len;
@@ -879,10 +925,12 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & data_len);
}
if (g_dwc2_udc.in_ep[ep_idx].ep_type == 0x01) {
if (g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
} else {
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SODDFRM;
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
}
USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
@@ -911,14 +959,15 @@ int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
if (!data && data_len) {
return -1;
}
if (!g_dwc2_udc.out_ep[ep_idx].ep_enable) {
if (USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) {
return -2;
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
if (((uint32_t)data) & 0x03) {
if (ep_idx && !(USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_MPSIZ)) {
return -3;
}
#endif
if (((uint32_t)data) & 0x03) {
return -4;
}
g_dwc2_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_dwc2_udc.out_ep[ep_idx].xfer_len = data_len;
@@ -950,10 +999,12 @@ int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
#endif
if (g_dwc2_udc.out_ep[ep_idx].ep_type == 0x01) {
if (g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
} else {
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SODDFRM;
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
}
}
@@ -963,7 +1014,7 @@ int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
void USBD_IRQHandler(void)
{
uint32_t gint_status, temp, ep_idx, ep_intr, epint, read_count;
uint32_t gint_status, temp, ep_idx, ep_intr, epint, read_count, daintmask;
gint_status = dwc2_get_glb_intstatus();
if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_DEVICE) {
@@ -1077,13 +1128,21 @@ void USBD_IRQHandler(void)
USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
} else {
USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
if (USB_OTG_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
USB_OTG_INEP(i)->DIEPCTL = (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK);
} else {
USB_OTG_INEP(i)->DIEPCTL = 0;
}
if (USB_OTG_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) {
USB_OTG_OUTEP(i)->DOEPCTL = (USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK);
} else {
USB_OTG_OUTEP(i)->DOEPCTL = 0;
}
}
USB_OTG_INEP(i)->DIEPTSIZ = 0U;
USB_OTG_INEP(i)->DIEPINT = 0xFB7FU;
USB_OTG_INEP(i)->DIEPINT = 0xFBFFU;
USB_OTG_OUTEP(i)->DOEPTSIZ = 0U;
USB_OTG_OUTEP(i)->DOEPINT = 0xFB7FU;
USB_OTG_OUTEP(i)->DOEPINT = 0xFBFFU;
}
USB_OTG_DEV->DAINTMSK |= 0x10001U;
@@ -1104,6 +1163,50 @@ void USBD_IRQHandler(void)
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK;
}
if (gint_status & USB_OTG_GINTSTS_PXFR_INCOMPISOOUT) {
daintmask = USB_OTG_DEV->DAINTMSK;
daintmask >>= 16;
for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
if ((BIT(ep_idx) & ~daintmask) || (g_dwc2_udc.out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
continue;
if (!(USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP))
continue;
if ((USB_OTG_DEV->DSTS & (1U << 8)) != 0U) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SODDFRM;
} else {
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
}
}
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_PXFR_INCOMPISOOUT;
}
if (gint_status & USB_OTG_GINTSTS_IISOIXFR) {
daintmask = USB_OTG_DEV->DAINTMSK;
daintmask >>= 16;
for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
if (((BIT(ep_idx) & ~daintmask)) || (g_dwc2_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
continue;
if (!(USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP))
continue;
if ((USB_OTG_DEV->DSTS & (1U << 8)) != 0U) {
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SODDFRM;
} else {
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
}
}
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_IISOIXFR;
}
if (gint_status & USB_OTG_GINTSTS_SOF) {
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_SOF;
}

View File

@@ -15,8 +15,8 @@
#define USB_BASE (0x40040000UL)
#endif
#if CONFIG_USBHOST_PIPE_NUM != 12
#error dwc2 ip only supports 12 pipe num.
#ifndef CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USBHOST_PIPE_NUM 12
#endif
#if defined(STM32F7) || defined(STM32H7)
@@ -44,6 +44,7 @@ struct dwc2_pipe {
uint32_t xferlen;
bool inuse;
uint32_t xfrd;
int errorcode;
volatile bool waiter;
usb_osal_sem_t waitsem;
struct usbh_hubport *hport;
@@ -234,29 +235,6 @@ static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
USB_OTG_HC((uint32_t)ch_num)->HCCHAR = regval;
}
static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size)
{
uint16_t num_packets;
num_packets = (uint16_t)((input_size + ep_mps - 1U) / ep_mps);
if (num_packets > 256) {
num_packets = 256;
}
if (input_size == 0) {
num_packets = 1;
}
if (ep_addr & 0x80) {
input_size = num_packets * ep_mps;
} else {
}
*output_size = input_size;
return num_packets;
}
/* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/
static inline void dwc2_pipe_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
{
@@ -284,7 +262,7 @@ static inline void dwc2_pipe_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t
static void dwc2_halt(uint8_t ch_num)
{
uint32_t count = 0U;
volatile uint32_t count = 0U;
uint32_t HcEpType = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
uint32_t ChannelEna = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
@@ -328,6 +306,47 @@ static void dwc2_halt(uint8_t ch_num)
}
}
}
static int usbh_reset_port(const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
hprt0 = USB_OTG_HPRT;
hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
USB_OTG_HPRT = (USB_OTG_HPRT_PRST | hprt0);
usb_osal_msleep(100U); /* See Note #1 */
USB_OTG_HPRT = ((~USB_OTG_HPRT_PRST) & hprt0);
usb_osal_msleep(10U);
while (!(USB_OTG_HPRT & USB_OTG_HPRT_PENA)) {
usb_osal_msleep(10U);
}
return 0;
}
static uint8_t usbh_get_port_speed(const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
uint8_t speed;
hprt0 = USB_OTG_HPRT;
speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17;
if (speed == HPRT0_PRTSPD_HIGH_SPEED) {
return USB_SPEED_HIGH;
} else if (speed == HPRT0_PRTSPD_FULL_SPEED) {
return USB_SPEED_FULL;
} else if (speed == HPRT0_PRTSPD_LOW_SPEED) {
return USB_SPEED_LOW;
} else {
return USB_SPEED_UNKNOWN;
}
}
/**
* @brief dwc2_get_glb_intstatus: return the global USB interrupt status
* @retval status
@@ -361,6 +380,29 @@ static void dwc2_pipe_free(struct dwc2_pipe *pipe)
pipe->inuse = false;
}
static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size)
{
uint16_t num_packets;
num_packets = (uint16_t)((input_size + ep_mps - 1U) / ep_mps);
if (num_packets > 256) {
num_packets = 256;
}
if (input_size == 0) {
num_packets = 1;
}
if (ep_addr & 0x80) {
input_size = num_packets * ep_mps;
} else {
}
*output_size = input_size;
return num_packets;
}
static void dwc2_control_pipe_init(struct dwc2_pipe *chan, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
{
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */
@@ -403,45 +445,6 @@ static void dwc2_iso_pipe_init(struct dwc2_pipe *chan, struct usbh_iso_frame_pac
dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
}
static int usbh_reset_port(const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
hprt0 = USB_OTG_HPRT;
hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
USB_OTG_HPRT = (USB_OTG_HPRT_PRST | hprt0);
usb_osal_msleep(100U); /* See Note #1 */
USB_OTG_HPRT = ((~USB_OTG_HPRT_PRST) & hprt0);
usb_osal_msleep(10U);
while (!(USB_OTG_HPRT & USB_OTG_HPRT_PENA)) {
}
return 0;
}
static uint8_t usbh_get_port_speed(const uint8_t port)
{
__IO uint32_t hprt0 = 0U;
uint8_t speed;
hprt0 = USB_OTG_HPRT;
speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17;
if (speed == HPRT0_PRTSPD_HIGH_SPEED) {
return USB_SPEED_HIGH;
} else if (speed == HPRT0_PRTSPD_FULL_SPEED) {
return USB_SPEED_FULL;
} else if (speed == HPRT0_PRTSPD_LOW_SPEED) {
return USB_SPEED_LOW;
} else {
return USB_SPEED_UNKNOWN;
}
}
__WEAK void usb_hc_low_level_init(void)
{
}
@@ -458,13 +461,15 @@ int usb_hc_init(void)
usb_hc_low_level_init();
USB_LOG_INFO("========== DWC2 params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n",USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n",USB_OTG_GLB->GSNPSID);
USB_LOG_INFO("GHWCFG1:%08x\r\n",USB_OTG_GLB->GHWCFG1);
USB_LOG_INFO("GHWCFG2:%08x\r\n",USB_OTG_GLB->GHWCFG2);
USB_LOG_INFO("GHWCFG3:%08x\r\n",USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n",USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("========== dwc2 hcd params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n", USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n", USB_OTG_GLB->GSNPSID);
USB_LOG_INFO("GHWCFG1:%08x\r\n", USB_OTG_GLB->GHWCFG1);
USB_LOG_INFO("GHWCFG2:%08x\r\n", USB_OTG_GLB->GHWCFG2);
USB_LOG_INFO("GHWCFG3:%08x\r\n", USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n", USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("dwc2 has %d channels\r\n", ((USB_OTG_GLB->GHWCFG2 & (0x0f << 14)) >> 14) + 1);
if ((USB_OTG_GLB->GHWCFG2 & (0x3U << 3)) == 0U) {
USB_LOG_ERR("This dwc2 version does not support dma, so stop working\r\n");
@@ -496,8 +501,6 @@ int usb_hc_init(void)
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
#endif
/*!< FS/LS PHY clock select */
USB_OTG_HOST->HCFG |= USB_OTG_HCFG_FSLSPCS_0;
/* Set default Max speed support */
USB_OTG_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
@@ -720,7 +723,7 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
chan->data_pid = HC_PID_DATA1;
} else {
dwc2_pipe_init(chidx, chan->dev_addr, ep_cfg->ep_addr, ep_cfg->ep_type, chan->ep_mps, chan->speed);
dwc2_pipe_init(chidx, chan->dev_addr, ep_cfg->ep_addr, ep_cfg->ep_type, ep_cfg->ep_mps, chan->speed);
chan->data_pid = HC_PID_DATA0;
}
@@ -747,7 +750,9 @@ int usbh_pipe_free(usbh_pipe_t pipe)
if (!chan) {
return -EINVAL;
}
urb = chan->urb;
if (urb) {
usbh_kill_urb(urb);
}
@@ -758,65 +763,63 @@ int usbh_pipe_free(usbh_pipe_t pipe)
int usbh_submit_urb(struct usbh_urb *urb)
{
struct dwc2_pipe *chan;
struct dwc2_pipe *pipe;
size_t flags;
int ret = 0;
if (!urb) {
if (!urb || !urb->pipe) {
return -EINVAL;
}
chan = urb->pipe;
if (!chan) {
return -EINVAL;
}
pipe = urb->pipe;
/* dma addr must be aligned 4 bytes */
if ((((uint32_t)urb->setup) & 0x03) || (((uint32_t)urb->transfer_buffer) & 0x03)) {
return -EINVAL;
}
if (!chan->hport->connected) {
if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !pipe->hport->connected) {
return -ENODEV;
}
if (chan->urb) {
if (pipe->urb) {
return -EBUSY;
}
flags = usb_osal_enter_critical_section();
chan->waiter = false;
chan->xfrd = 0;
chan->urb = urb;
pipe->waiter = false;
pipe->xfrd = 0;
pipe->urb = urb;
pipe->errorcode = -EBUSY;
urb->errorcode = -EBUSY;
urb->actual_length = 0;
if (urb->timeout > 0) {
chan->waiter = true;
pipe->waiter = true;
}
usb_osal_leave_critical_section(flags);
switch (chan->ep_type) {
switch (pipe->ep_type) {
case USB_ENDPOINT_TYPE_CONTROL:
chan->ep0_state = DWC2_EP0_STATE_SETUP;
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
pipe->ep0_state = DWC2_EP0_STATE_SETUP;
dwc2_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_BULK:
case USB_ENDPOINT_TYPE_INTERRUPT:
dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length);
dwc2_bulk_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
chan->iso_frame_idx = 0;
dwc2_iso_pipe_init(chan, &urb->iso_packet[chan->iso_frame_idx]);
pipe->iso_frame_idx = 0;
dwc2_iso_pipe_init(pipe, &urb->iso_packet[pipe->iso_frame_idx]);
break;
default:
break;
}
if (urb->timeout > 0) {
/* wait until timeout or sem give */
ret = usb_osal_sem_take(chan->waitsem, urb->timeout);
ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
if (ret < 0) {
goto errout_timeout;
}
@@ -825,7 +828,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
}
return ret;
errout_timeout:
chan->waiter = false;
pipe->waiter = false;
usbh_kill_urb(urb);
return ret;
}
@@ -847,6 +850,12 @@ int usbh_kill_urb(struct usbh_urb *urb)
CLEAR_HC_INT(pipe->chidx, USB_OTG_HCINT_CHH);
pipe->urb = NULL;
if (pipe->waiter) {
pipe->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(pipe->waitsem);
}
usb_osal_leave_critical_section(flags);
return 0;
@@ -886,66 +895,71 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
//printf("s1:%08x\r\n", chan_intstatus);
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
urb->errorcode = 0;
chan->errorcode = 0;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
chan->errorcode = -EPERM;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EPERM;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
chan->errorcode = -EAGAIN;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EAGAIN;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
chan->errorcode = -EAGAIN;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EAGAIN;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
chan->errorcode = -EPIPE;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EPIPE;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
if (urb == NULL) {
goto chhout;
}
urb->errorcode = chan->errorcode;
if (urb->errorcode == 0) {
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* size that has received */
uint32_t has_sent_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /*how many packets has sent*/
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */
chan->xfrd += count;
if ((has_sent_packets % 2) == 1) /* Flip in odd numbers */
if ((has_used_packets % 2) == 1) /* toggle in odd numbers */
{
if (chan->data_pid == HC_PID_DATA0) {
chan->data_pid = HC_PID_DATA1;
@@ -985,11 +999,10 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
}
} else {
dwc2_pipe_waitup(chan);
}
chhout:
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
}
}
@@ -1006,65 +1019,71 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
chan = &g_dwc2_hcd.pipe_pool[ch_num];
urb = chan->urb;
//printf("s2:%08x\r\n", chan_intstatus);
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
chan->errorcode = 0;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
dwc2_halt(ch_num);
urb->errorcode = 0;
USB_UNMASK_HALT_HC_INT(ch_num);
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
chan->errorcode = -EPERM;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EPERM;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
chan->errorcode = -EAGAIN;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EAGAIN;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
chan->errorcode = -EAGAIN;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EAGAIN;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
chan->errorcode = -EPIPE;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EPIPE;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
chan->errorcode = -EIO;
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
urb->errorcode = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
if (urb == NULL) {
goto chhout;
}
urb->errorcode = chan->errorcode;
if (urb->errorcode == 0) {
uint32_t count = (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* last send size */
if (count == chan->ep_mps) {
chan->xfrd += chan->num_packets * chan->ep_mps;
} else {
chan->xfrd += (chan->num_packets - 1) * chan->ep_mps + count;
}
if ((chan->num_packets % 2) == 1) /* Flip in odd numbers */
uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* how many size has sent */
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */
chan->xfrd += count;
if (has_used_packets % 2) /* toggle in odd numbers */
{
if (chan->data_pid == HC_PID_DATA0) {
chan->data_pid = HC_PID_DATA1;
@@ -1072,6 +1091,7 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
chan->data_pid = HC_PID_DATA0;
}
}
if (chan->ep_type == 0x00) {
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) {
if (urb->setup->wLength) {
@@ -1114,11 +1134,10 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
}
} else {
dwc2_pipe_waitup(chan);
}
chhout:
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
}
}
@@ -1197,15 +1216,6 @@ void USBH_IRQHandler(void)
}
if (gint_status & USB_OTG_GINTSTS_DISCINT) {
g_dwc2_hcd.port_csc = 1;
for (uint8_t index = 0; index < CONFIG_USBHOST_PIPE_NUM; index++) {
struct dwc2_pipe *chan = &g_dwc2_hcd.pipe_pool[index];
struct usbh_urb *urb = chan->urb;
if (chan->waiter) {
chan->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(chan->waitsem);
}
}
usbh_roothub_thread_wakeup(1);
USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_DISCINT;

View File

@@ -9,13 +9,13 @@
#define USBH_IRQHandler USBH_IRQHandler
#endif
#define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE)
#define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE)
#define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE)
#define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE)
#define EHCI_PTR2ADDR(x) ((uint32_t)x)
#define EHCI_ADDRALIGN32(x) ((uint32_t)(x) & ~0x1F)
#define EHCI_ADDR2QH(x) ((struct ehci_qh_hw *)((uint32_t)(x) & ~0x1F))
#define EHCI_ADDR2ITD(x) ((struct ehci_itd_hw *)((uint32_t)(x) & ~0x1F))
#define EHCI_PTR2ADDR(x) ((uint32_t)(x) & ~0x1F)
#define EHCI_ADDR2QH(x) ((struct ehci_qh_hw *)((uint32_t)(x) & ~0x1F))
#define EHCI_ADDR2QTD(x) ((struct ehci_qtd_hw *)((uint32_t)(x) & ~0x1F))
#define EHCI_ADDR2ITD(x) ((struct ehci_itd_hw *)((uint32_t)(x) & ~0x1F))
#if CONFIG_USB_EHCI_FRAME_LIST_SIZE == 1024
#define EHCI_PERIOIDIC_QH_NUM 11
@@ -49,7 +49,6 @@ struct ehci_pipe {
bool waiter;
usb_osal_sem_t waitsem;
struct usbh_hubport *hport;
struct ehci_qh_hw *qh;
struct usbh_urb *urb;
uint8_t mf_unmask;
uint8_t mf_valid;
@@ -60,11 +59,14 @@ struct ehci_pipe {
struct ehci_qh_hw {
struct ehci_qh hw;
uint32_t first_qtd;
struct ehci_pipe *pipe;
struct usbh_urb *urb;
uint8_t remove_in_iaad;
} __attribute__((aligned(32)));
struct ehci_qtd_hw {
struct ehci_qtd hw;
struct usbh_urb *urb;
uint32_t total_len;
} __attribute__((aligned(32)));
struct ehci_itd_hw {

View File

@@ -0,0 +1,134 @@
#include "bflb_core.h"
#include "usbh_core.h"
#include "hardware/usb_v2_reg.h"
#ifndef CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
#error "usb host must enable CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE"
#endif
#define BLFB_USB_BASE ((uint32_t)0x20072000)
#define BFLB_PDS_BASE ((uint32_t)0x2000e000)
#define PDS_USB_CTL_OFFSET (0x500) /* usb_ctl */
#define PDS_USB_PHY_CTRL_OFFSET (0x504) /* usb_phy_ctrl */
/* 0x500 : usb_ctl */
#define PDS_REG_USB_SW_RST_N (1 << 0U)
#define PDS_REG_USB_EXT_SUSP_N (1 << 1U)
#define PDS_REG_USB_WAKEUP (1 << 2U)
#define PDS_REG_USB_L1_WAKEUP (1 << 3U)
#define PDS_REG_USB_DRVBUS_POL (1 << 4U)
#define PDS_REG_USB_IDDIG (1 << 5U)
/* 0x504 : usb_phy_ctrl */
#define PDS_REG_USB_PHY_PONRST (1 << 0U)
#define PDS_REG_USB_PHY_OSCOUTEN (1 << 1U)
#define PDS_REG_USB_PHY_XTLSEL_SHIFT (2U)
#define PDS_REG_USB_PHY_XTLSEL_MASK (0x3 << PDS_REG_USB_PHY_XTLSEL_SHIFT)
#define PDS_REG_USB_PHY_OUTCLKSEL (1 << 4U)
#define PDS_REG_USB_PHY_PLLALIV (1 << 5U)
#define PDS_REG_PU_USB20_PSW (1 << 6U)
#define USB_SOF_TIMER_MASK_AFTER_RESET_HS (0x44C)
#define USB_SOF_TIMER_MASK_AFTER_RESET_FS (0x2710)
extern void USBH_IRQHandler();
static void bflb_usb_phy_init(void)
{
uint32_t regval;
/* USB_PHY_CTRL[3:2] reg_usb_phy_xtlsel=0 */
/* 2000e504 = 0x40; #100; USB_PHY_CTRL[6] reg_pu_usb20_psw=1 (VCC33A) */
/* 2000e504 = 0x41; #500; USB_PHY_CTRL[0] reg_usb_phy_ponrst=1 */
/* 2000e500 = 0x20; #100; USB_CTL[0] reg_usb_sw_rst_n=0 */
/* 2000e500 = 0x22; #500; USB_CTL[1] reg_usb_ext_susp_n=1 */
/* 2000e500 = 0x23; #100; USB_CTL[0] reg_usb_sw_rst_n=1 */
/* #1.2ms; wait UCLK */
/* wait(soc616_b0.usb_uclk); */
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
regval &= ~PDS_REG_USB_PHY_XTLSEL_MASK;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
regval |= PDS_REG_PU_USB20_PSW;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
regval |= PDS_REG_USB_PHY_PONRST;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET);
/* greater than 5T */
bflb_mtimer_delay_us(1);
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
regval &= ~PDS_REG_USB_SW_RST_N;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
/* greater than 5T */
bflb_mtimer_delay_us(1);
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
regval |= PDS_REG_USB_EXT_SUSP_N;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
/* wait UCLK 1.2ms */
bflb_mtimer_delay_ms(3);
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
regval |= PDS_REG_USB_SW_RST_N;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
bflb_mtimer_delay_ms(2);
}
void usb_hc_low_level_init(void)
{
uint32_t regval;
bflb_usb_phy_init();
bflb_irq_attach(37, USBH_IRQHandler, NULL);
bflb_irq_enable(37);
/* enable device-A for host */
regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
regval &= ~PDS_REG_USB_IDDIG;
putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET);
regval = getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
regval |= USB_A_BUS_DROP_HOV;
regval &= ~USB_A_BUS_REQ_HOV;
putreg32(regval, BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
bflb_mtimer_delay_ms(10);
/* enable vbus and bus control */
regval = getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
regval &= ~USB_A_BUS_DROP_HOV;
regval |= USB_A_BUS_REQ_HOV;
putreg32(regval, BLFB_USB_BASE + USB_OTG_CSR_OFFSET);
regval = getreg32(BLFB_USB_BASE + USB_GLB_INT_OFFSET);
regval |= USB_MDEV_INT;
regval |= USB_MOTG_INT;
regval &= ~USB_MHC_INT;
putreg32(regval, BLFB_USB_BASE + USB_GLB_INT_OFFSET);
}
uint8_t usbh_get_port_speed(const uint8_t port)
{
uint8_t speed = 3;
speed = (getreg32(BLFB_USB_BASE + USB_OTG_CSR_OFFSET) & USB_SPD_TYP_HOV_POV_MASK) >> USB_SPD_TYP_HOV_POV_SHIFT;
if (speed == 0) {
return USB_SPEED_FULL;
} else if (speed == 1) {
return USB_SPEED_LOW;
} else if (speed == 2) {
return USB_SPEED_HIGH;
}
return USB_SPEED_HIGH;
}

View File

@@ -3,39 +3,13 @@
#include "hpm_soc.h"
#include "hpm_usb_drv.h"
#define USB_PHY_INIT_DELAY_COUNT (16U) /**< a delay count for USB phy initialization */
#if !defined(CONFIG_USB_EHCI_HPMICRO) || !CONFIG_USB_EHCI_HPMICRO
#error "hpm ehci must set CONFIG_USB_EHCI_HPMICRO=1"
#endif
/* Initialize USB phy */
static void usb_phy_init(USB_Type *ptr)
{
uint32_t status;
ptr->OTG_CTRL0 |= USB_OTG_CTRL0_OTG_UTMI_RESET_SW_MASK; /* set otg_utmi_reset_sw for naneng usbphy */
ptr->OTG_CTRL0 &= ~USB_OTG_CTRL0_OTG_UTMI_SUSPENDM_SW_MASK; /* clr otg_utmi_suspend_m for naneng usbphy */
ptr->PHY_CTRL1 &= ~USB_PHY_CTRL1_UTMI_CFG_RST_N_MASK; /* clr cfg_rst_n */
do {
status = USB_OTG_CTRL0_OTG_UTMI_RESET_SW_GET(ptr->OTG_CTRL0); /* wait for reset status */
} while (status == 0);
ptr->OTG_CTRL0 |= USB_OTG_CTRL0_OTG_UTMI_SUSPENDM_SW_MASK; /* set otg_utmi_suspend_m for naneng usbphy */
for (int i = 0; i < USB_PHY_INIT_DELAY_COUNT; i++) {
ptr->PHY_CTRL0 = USB_PHY_CTRL0_GPIO_ID_SEL_N_SET(0); /* used for delay */
}
ptr->OTG_CTRL0 &= ~USB_OTG_CTRL0_OTG_UTMI_RESET_SW_MASK; /* clear otg_utmi_reset_sw for naneng usbphy */
/* otg utmi clock detection */
ptr->PHY_STATUS |= USB_PHY_STATUS_UTMI_CLK_VALID_MASK; /* write 1 to clear valid status */
do {
status = USB_PHY_STATUS_UTMI_CLK_VALID_GET(ptr->PHY_STATUS); /* get utmi clock status */
} while (status == 0);
ptr->PHY_CTRL1 |= USB_PHY_CTRL1_UTMI_CFG_RST_N_MASK; /* set cfg_rst_n */
ptr->PHY_CTRL1 |= USB_PHY_CTRL1_UTMI_OTG_SUSPENDM_MASK; /* set otg_suspendm */
}
#if !defined(CONFIG_HPM_USBH_BASE) || !defined(CONFIG_HPM_USBH_IRQn)
#error "hpm ehci must config CONFIG_HPM_USBH_BASE and CONFIG_HPM_USBH_IRQn"
#endif
static void usb_host_mode_init(USB_Type *ptr)
{
@@ -58,20 +32,20 @@ static void usb_host_mode_init(USB_Type *ptr)
void usb_hc_low_level_init()
{
usb_phy_init((USB_Type *)HPM_USB0_BASE);
intc_m_enable_irq(IRQn_USB0);
usb_phy_init((USB_Type *)CONFIG_HPM_USBH_BASE);
intc_m_enable_irq(CONFIG_HPM_USBH_IRQn);
}
void usb_hc_low_level2_init()
{
usb_host_mode_init((USB_Type *)HPM_USB0_BASE);
usb_host_mode_init((USB_Type *)CONFIG_HPM_USBH_BASE);
}
uint8_t usbh_get_port_speed(const uint8_t port)
{
uint8_t speed;
speed = usb_get_port_speed((USB_Type *)HPM_USB0_BASE);
speed = usb_get_port_speed((USB_Type *)CONFIG_HPM_USBH_BASE);
if (speed == 0x00) {
return USB_SPEED_FULL;
@@ -88,15 +62,8 @@ uint8_t usbh_get_port_speed(const uint8_t port)
extern void USBH_IRQHandler(void);
void isr_usb0(void)
void isr_usb(void)
{
USBH_IRQHandler();
}
SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0)
#ifdef HPM_USB1_BASE
void isr_usb1(void)
{
}
SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usb1)
#endif
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBH_IRQn, isr_usb)

View File

@@ -5,6 +5,12 @@
*/
#include "usb_ehci_priv.h"
#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
#define EHCI_TUNE_RL_TT 0
#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
#define EHCI_TUNE_MULT_TT 1
struct ehci_hcd g_ehci_hcd;
USB_NOCACHE_RAM_SECTION struct ehci_qh_hw ehci_qh_pool[CONFIG_USB_EHCI_QH_NUM];
@@ -18,16 +24,17 @@ USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_periodic_qh_head[EHCI_PERIOIDIC_QH_N
/* The frame list */
USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USB_EHCI_FRAME_LIST_SIZE] __attribute__((aligned(4096)));
static const uint8_t g_ehci_speed[4] = {
0, EHCI_LOW_SPEED, EHCI_FULL_SPEED, EHCI_HIGH_SPEED
};
static struct ehci_qh_hw *ehci_qh_alloc(void)
{
struct ehci_qh_hw *qh;
size_t flags;
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
if (!g_ehci_hcd.ehci_qh_used[i]) {
flags = usb_osal_enter_critical_section();
g_ehci_hcd.ehci_qh_used[i] = true;
usb_osal_leave_critical_section(flags);
qh = &ehci_qh_pool[i];
memset(qh, 0, sizeof(struct ehci_qh_hw));
qh->hw.hlp = QTD_LIST_END;
@@ -41,9 +48,15 @@ static struct ehci_qh_hw *ehci_qh_alloc(void)
static void ehci_qh_free(struct ehci_qh_hw *qh)
{
size_t flags;
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
if (&ehci_qh_pool[i] == qh) {
flags = usb_osal_enter_critical_section();
g_ehci_hcd.ehci_qh_used[i] = false;
usb_osal_leave_critical_section(flags);
qh->urb = NULL;
return;
}
}
@@ -52,9 +65,14 @@ static void ehci_qh_free(struct ehci_qh_hw *qh)
static struct ehci_qtd_hw *ehci_qtd_alloc(void)
{
struct ehci_qtd_hw *qtd;
size_t flags;
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
if (!g_ehci_hcd.ehci_qtd_used[i]) {
flags = usb_osal_enter_critical_section();
g_ehci_hcd.ehci_qtd_used[i] = true;
usb_osal_leave_critical_section(flags);
qtd = &ehci_qtd_pool[i];
memset(qtd, 0, sizeof(struct ehci_qtd_hw));
qtd->hw.next_qtd = QTD_LIST_END;
@@ -68,9 +86,15 @@ static struct ehci_qtd_hw *ehci_qtd_alloc(void)
static void ehci_qtd_free(struct ehci_qtd_hw *qtd)
{
size_t flags;
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
if (&ehci_qtd_pool[i] == qtd) {
flags = usb_osal_enter_critical_section();
g_ehci_hcd.ehci_qtd_used[i] = false;
usb_osal_leave_critical_section(flags);
qtd->urb = NULL;
return;
}
}
@@ -149,10 +173,18 @@ static struct ehci_qh_hw *ehci_get_periodic_qhead(uint8_t interval)
}
static void ehci_qh_fill(struct ehci_qh_hw *qh,
struct ehci_pipe *pipe)
uint8_t dev_addr,
uint8_t ep_addr,
uint8_t ep_type,
uint16_t ep_mps,
uint8_t ep_mult,
uint8_t ep_interval,
uint8_t speed,
uint8_t hubaddr,
uint8_t hubport)
{
struct usbh_hub *hub;
uint32_t regval;
uint32_t epchar = 0;
uint32_t epcap = 0;
/* QH endpoint characteristics:
*
@@ -167,17 +199,6 @@ static void ehci_qh_fill(struct ehci_qh_hw *qh,
* C Control endpoint
* RL NAK count reloaded
*/
regval = ((uint32_t)pipe->dev_addr << QH_EPCHAR_DEVADDR_SHIFT) |
((uint32_t)(pipe->ep_addr & 0xf) << QH_EPCHAR_ENDPT_SHIFT) |
((uint32_t)g_ehci_speed[pipe->speed] << QH_EPCHAR_EPS_SHIFT) |
((uint32_t)pipe->ep_mps << QH_EPCHAR_MAXPKT_SHIFT) |
QH_EPCHAR_DTC |
((uint32_t)0 << QH_EPCHAR_RL_SHIFT);
if (pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL && (pipe->speed != USB_SPEED_HIGH)) {
regval |= QH_EPCHAR_C;
}
qh->hw.epchar = regval;
/* QH endpoint capabilities
*
@@ -189,26 +210,59 @@ static void ehci_qh_fill(struct ehci_qh_hw *qh,
* PORT Port number
* MULT High band width multiplier
*/
regval = 0;
hub = pipe->hport->parent;
epchar |= ((ep_addr & 0xf) << QH_EPCHAR_ENDPT_SHIFT);
epchar |= (dev_addr << QH_EPCHAR_DEVADDR_SHIFT);
epchar |= (ep_mps << QH_EPCHAR_MAXPKT_SHIFT);
regval |= QH_EPCAPS_HUBADDR(hub->hub_addr);
regval |= QH_EPCAPS_PORT(pipe->hport->port);
if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
if (pipe->speed == USB_SPEED_HIGH) {
regval |= ehci_caculate_smask(pipe->ep_interval);
} else {
regval |= QH_EPCAPS_SSMASK(2);
regval |= QH_EPCAPS_SCMASK(0x78);
}
regval |= QH_EPCAPS_MULT(1);
if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
epchar |= QH_EPCHAR_DTC; /* toggle from qtd */
}
qh->hw.epcap = regval;
switch (speed) {
case USB_SPEED_LOW:
epchar |= QH_EPCHAR_EPS_LOW;
case USB_SPEED_FULL:
if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
epchar |= QH_EPCHAR_C; /* for TT */
}
qh->pipe = pipe;
if (ep_type != USB_ENDPOINT_TYPE_INTERRUPT) {
epchar |= (EHCI_TUNE_RL_TT << QH_EPCHAR_RL_SHIFT);
}
epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_TT);
epcap |= QH_EPCAPS_HUBADDR(hubaddr);
epcap |= QH_EPCAPS_PORT(hubport);
if (ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
epcap |= QH_EPCAPS_SSMASK(2);
epcap |= QH_EPCAPS_SCMASK(0x78);
}
break;
case USB_SPEED_HIGH:
epchar |= QH_EPCHAR_EPS_HIGH;
if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
epchar |= (EHCI_TUNE_RL_HS << QH_EPCHAR_RL_SHIFT);
epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_HS);
} else if (ep_type == USB_ENDPOINT_TYPE_BULK) {
epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_HS);
} else {
/* only for interrupt ep */
epcap |= QH_EPCAPS_MULT(ep_mult);
epcap |= ehci_caculate_smask(ep_interval);
}
break;
default:
break;
}
qh->hw.epchar = epchar;
qh->hw.epcap = epcap;
}
static void ehci_qtd_bpl_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t buflen)
@@ -237,7 +291,7 @@ static void ehci_qtd_bpl_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t
}
}
static void ehci_qtd_fill(struct ehci_pipe *pipe, struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t buflen, uint32_t token)
static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t buflen, uint32_t token)
{
/* qTD token
*
@@ -255,7 +309,7 @@ static void ehci_qtd_fill(struct ehci_pipe *pipe, struct ehci_qtd_hw *qtd, uint3
qtd->hw.token = token;
ehci_qtd_bpl_fill(qtd, bufaddr, buflen);
pipe->xfrd += buflen;
qtd->total_len = buflen;
}
static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
@@ -289,15 +343,25 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
return NULL;
}
ehci_qh_fill(qh, pipe);
ehci_qh_fill(qh,
pipe->dev_addr,
pipe->ep_addr,
pipe->ep_type,
pipe->ep_mps,
0,
pipe->ep_interval,
pipe->hport->speed,
pipe->hport->parent->hub_addr,
pipe->hport->port);
/* fill setup qtd */
token = QTD_TOKEN_STATUS_ACTIVE |
QTD_TOKEN_PID_SETUP |
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)8 << QTD_TOKEN_NBYTES_SHIFT);
ehci_qtd_fill(pipe, qtd_setup, EHCI_PTR2ADDR(setup), 8, token);
ehci_qtd_fill(qtd_setup, (uintptr_t)setup, 8, token);
qtd_setup->urb = pipe->urb;
/* fill data qtd */
if (setup->wLength > 0) {
@@ -309,10 +373,11 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
token |= QTD_TOKEN_STATUS_ACTIVE |
QTD_TOKEN_PID_OUT |
QTD_TOKEN_TOGGLE |
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)buflen << QTD_TOKEN_NBYTES_SHIFT);
ehci_qtd_fill(pipe, qtd_data, EHCI_PTR2ADDR(buffer), buflen, token);
ehci_qtd_fill(qtd_data, (uintptr_t)buffer, buflen, token);
qtd_data->urb = pipe->urb;
qtd_setup->hw.next_qtd = EHCI_PTR2ADDR(qtd_data);
qtd_data->hw.next_qtd = EHCI_PTR2ADDR(qtd_status);
} else {
@@ -328,13 +393,15 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
token |= QTD_TOKEN_STATUS_ACTIVE |
QTD_TOKEN_TOGGLE |
QTD_TOKEN_IOC |
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)0 << QTD_TOKEN_NBYTES_SHIFT);
ehci_qtd_fill(pipe, qtd_status, 0, 0, token);
ehci_qtd_fill(qtd_status, 0, 0, token);
qtd_status->urb = pipe->urb;
qtd_status->hw.next_qtd = QTD_LIST_END;
/* update qh first qtd */
qh->hw.curr_qtd = EHCI_PTR2ADDR(qtd_setup);
qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(qtd_setup);
/* record qh first qtd */
@@ -342,10 +409,12 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
flags = usb_osal_enter_critical_section();
pipe->qh = qh;
qh->urb = pipe->urb;
/* add qh into async list */
ehci_qh_add_head(&g_async_qh_head, qh);
EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
usb_osal_leave_critical_section(flags);
return qh;
}
@@ -377,7 +446,16 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
return NULL;
}
ehci_qh_fill(qh, pipe);
ehci_qh_fill(qh,
pipe->dev_addr,
pipe->ep_addr,
pipe->ep_type,
pipe->ep_mps,
0,
pipe->ep_interval,
pipe->hport->speed,
pipe->hport->parent->hub_addr,
pipe->hport->port);
while (buflen >= 0) {
qtd = ehci_qtd_alloc();
@@ -390,28 +468,22 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
buflen = 0;
}
/* fill qtd */
if (pipe->toggle) {
token = QTD_TOKEN_TOGGLE;
} else {
token = 0;
}
if (pipe->ep_addr & 0x80) {
token |= QTD_TOKEN_PID_IN;
token = QTD_TOKEN_PID_IN;
} else {
token |= QTD_TOKEN_PID_OUT;
token = QTD_TOKEN_PID_OUT;
}
token |= QTD_TOKEN_STATUS_ACTIVE |
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)xfer_len << QTD_TOKEN_NBYTES_SHIFT);
if (buflen == 0) {
token |= QTD_TOKEN_IOC;
}
ehci_qtd_fill(pipe, qtd, (uint32_t)buffer, xfer_len, token);
ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
qtd->urb = pipe->urb;
qtd->hw.next_qtd = QTD_LIST_END;
buffer += xfer_len;
@@ -428,17 +500,27 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
}
/* update qh first qtd */
qh->hw.curr_qtd = EHCI_PTR2ADDR(first_qtd);
qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
/* update data toggle */
if (pipe->toggle) {
qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
} else {
qh->hw.overlay.token = 0;
}
/* record qh first qtd */
qh->first_qtd = EHCI_PTR2ADDR(first_qtd);
flags = usb_osal_enter_critical_section();
pipe->qh = qh;
qh->urb = pipe->urb;
/* add qh into async list */
ehci_qh_add_head(&g_async_qh_head, qh);
EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
usb_osal_leave_critical_section(flags);
return qh;
}
@@ -470,7 +552,16 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
return NULL;
}
ehci_qh_fill(qh, pipe);
ehci_qh_fill(qh,
pipe->dev_addr,
pipe->ep_addr,
pipe->ep_type,
pipe->ep_mps,
pipe->mult + 1,
pipe->ep_interval,
pipe->hport->speed,
pipe->hport->parent->hub_addr,
pipe->hport->port);
while (buflen >= 0) {
qtd = ehci_qtd_alloc();
@@ -483,28 +574,22 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
buflen = 0;
}
/* fill qtd */
if (pipe->toggle) {
token = QTD_TOKEN_TOGGLE;
} else {
token = 0;
}
if (pipe->ep_addr & 0x80) {
token |= QTD_TOKEN_PID_IN;
token = QTD_TOKEN_PID_IN;
} else {
token |= QTD_TOKEN_PID_OUT;
token = QTD_TOKEN_PID_OUT;
}
token |= QTD_TOKEN_STATUS_ACTIVE |
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
((uint32_t)xfer_len << QTD_TOKEN_NBYTES_SHIFT);
if (buflen == 0) {
token |= QTD_TOKEN_IOC;
}
ehci_qtd_fill(pipe, qtd, (uint32_t)buffer, xfer_len, token);
ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
qtd->urb = pipe->urb;
qtd->hw.next_qtd = QTD_LIST_END;
buffer += xfer_len;
@@ -521,20 +606,31 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
}
/* update qh first qtd */
qh->hw.curr_qtd = EHCI_PTR2ADDR(first_qtd);
qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
/* update data toggle */
if (pipe->toggle) {
qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
} else {
qh->hw.overlay.token = 0;
}
/* record qh first qtd */
qh->first_qtd = EHCI_PTR2ADDR(first_qtd);
flags = usb_osal_enter_critical_section();
pipe->qh = qh;
qh->urb = pipe->urb;
/* add qh into periodic list */
if (pipe->speed == USB_SPEED_HIGH) {
ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval), qh);
} else {
ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
}
EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN;
usb_osal_leave_critical_section(flags);
return qh;
}
@@ -560,46 +656,39 @@ void ehci_pipe_waitup(struct ehci_pipe *pipe)
}
}
static void ehci_qh_scan_qtds(struct ehci_qh_hw *qh, struct ehci_pipe *pipe)
static void ehci_qh_scan_qtds(struct ehci_qh_hw *qh)
{
struct ehci_qtd_hw *qtd;
struct ehci_qtd_hw *next;
if ((qh->first_qtd & QTD_LIST_END) == 0) {
qtd = (struct ehci_qtd_hw *)qh->first_qtd;
while (qtd) {
if (qtd->hw.next_qtd & QTD_LIST_END) {
next = NULL;
} else {
next = (struct ehci_qtd_hw *)qtd->hw.next_qtd;
}
qtd = EHCI_ADDR2QTD(qh->first_qtd);
qh->first_qtd = qtd->hw.next_qtd;
while (qtd) {
// if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
// continue;
// }
if (pipe) {
pipe->xfrd -= (qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >>
QTD_TOKEN_NBYTES_SHIFT;
}
qtd->urb->actual_length += (qtd->total_len - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
ehci_qtd_free(qtd);
qtd = next;
}
ehci_qtd_free(qtd);
qh->first_qtd = qtd->hw.next_qtd;
qtd = EHCI_ADDR2QTD(qh->first_qtd);
}
}
static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh, struct ehci_pipe *pipe)
static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
{
struct usbh_urb *urb;
struct ehci_pipe *pipe;
uint32_t token;
token = qh->hw.overlay.token;
if (token & QTD_TOKEN_STATUS_ACTIVE) {
} else {
urb = pipe->urb;
urb = qh->urb;
pipe = urb->pipe;
ehci_qh_scan_qtds(qh, pipe);
ehci_qh_scan_qtds(qh);
if (qh->first_qtd & QTD_LIST_END) {
/* remove qh from list */
ehci_qh_remove(qhead, qh);
@@ -623,29 +712,37 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh, struc
}
}
urb->actual_length = pipe->xfrd;
ehci_qh_free(qh);
pipe->qh = NULL;
qh->remove_in_iaad = 1;
ehci_pipe_waitup(pipe);
EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
}
}
}
static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
{
struct ehci_qtd_hw *qtd;
ehci_qh_remove(qhead, qh);
ehci_qh_scan_qtds(qh, NULL);
qtd = EHCI_ADDR2QTD(qh->first_qtd);
while (qtd) {
ehci_qtd_free(qtd);
qh->first_qtd = qtd->hw.next_qtd;
qtd = EHCI_ADDR2QTD(qh->first_qtd);
}
ehci_qh_free(qh);
}
static int usbh_reset_port(const uint8_t port)
{
uint32_t timeout = 0;
volatile uint32_t timeout = 0;
uint32_t regval;
#if CONFIG_USB_EHCI_HCOR_BASE == (0xF2020000UL + 0x140)
if ((*(volatile uint32_t *)(0xF2020000UL + 0x224) & 0xc0) == (2 << 6)) { /* Hardcode for hpm */
#if defined(CONFIG_USB_EHCI_HPMICRO) && CONFIG_USB_EHCI_HPMICRO
if ((*(volatile uint32_t *)(CONFIG_HPM_USBH_BASE + 0x224) & 0xc0) == (2 << 6)) { /* Hardcode for hpm */
EHCI_HCOR->portsc[port - 1] |= (1 << 29);
} else {
EHCI_HCOR->portsc[port - 1] &= ~(1 << 29);
@@ -682,7 +779,7 @@ int usb_hc_init(void)
uint32_t interval;
struct ehci_qh_hw *qh;
uint32_t timeout = 0;
volatile uint32_t timeout = 0;
uint32_t regval;
memset(&g_ehci_hcd, 0, sizeof(struct ehci_hcd));
@@ -1023,9 +1120,9 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
int usbh_pipe_free(usbh_pipe_t pipe)
{
struct usbh_urb *urb;
size_t flags;
struct ehci_pipe *ppipe;
struct ehci_pipe *ppipe = (struct ehci_pipe *)pipe;
ppipe = (struct ehci_pipe *)pipe;
if (!ppipe) {
return -EINVAL;
@@ -1037,9 +1134,7 @@ int usbh_pipe_free(usbh_pipe_t pipe)
usbh_kill_urb(urb);
}
flags = usb_osal_enter_critical_section();
ehci_pipe_free(ppipe);
usb_osal_leave_critical_section(flags);
return 0;
}
@@ -1050,17 +1145,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
size_t flags;
int ret = 0;
if (!urb) {
if (!urb || !urb->pipe) {
return -EINVAL;
}
pipe = urb->pipe;
if (!pipe) {
return -EINVAL;
}
if (!pipe->hport->connected) {
if (!pipe->inuse || !(EHCI_HCOR->portsc[0] & EHCI_PORTSC_CCS) || !pipe->hport->connected) {
return -ENODEV;
}
@@ -1072,7 +1163,6 @@ int usbh_submit_urb(struct usbh_urb *urb)
pipe->waiter = false;
pipe->xfrd = 0;
pipe->qh = NULL;
pipe->urb = urb;
urb->errorcode = -EBUSY;
urb->actual_length = 0;
@@ -1081,6 +1171,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
pipe->waiter = true;
}
usb_osal_leave_critical_section(flags);
switch (pipe->ep_type) {
case USB_ENDPOINT_TYPE_CONTROL:
qh = ehci_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
@@ -1149,7 +1240,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
if ((pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) || (pipe->ep_type == USB_ENDPOINT_TYPE_BULK)) {
qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
while ((qh != &g_async_qh_head) && qh) {
if (qh == pipe->qh) {
if (qh->urb == urb) {
ehci_kill_qh(&g_async_qh_head, qh);
}
qh = EHCI_ADDR2QH(qh->hw.hlp);
@@ -1157,7 +1248,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
} else if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
while (qh) {
if (qh == pipe->qh) {
if (qh->urb == urb) {
if (pipe->speed == USB_SPEED_HIGH) {
ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
} else {
@@ -1174,9 +1265,14 @@ int usbh_kill_urb(struct usbh_urb *urb)
EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
pipe->qh = NULL;
pipe->urb = NULL;
if (pipe->waiter) {
pipe->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(pipe->waitsem);
}
usb_osal_leave_critical_section(flags);
return 0;
@@ -1185,13 +1281,11 @@ int usbh_kill_urb(struct usbh_urb *urb)
static void ehci_scan_async_list(void)
{
struct ehci_qh_hw *qh;
struct ehci_pipe *pipe;
qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
while ((qh != &g_async_qh_head) && qh) {
pipe = qh->pipe;
if (pipe) {
ehci_check_qh(&g_async_qh_head, qh, pipe);
if (qh->urb) {
ehci_check_qh(&g_async_qh_head, qh);
}
qh = EHCI_ADDR2QH(qh->hw.hlp);
}
@@ -1204,12 +1298,12 @@ static void ehci_scan_periodic_list(void)
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
while (qh) {
pipe = qh->pipe;
if (pipe) {
if (qh->urb && qh->urb->pipe) {
pipe = (struct ehci_pipe *)qh->urb->pipe;
if (pipe->speed == USB_SPEED_HIGH) {
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh, pipe);
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
} else {
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh, pipe);
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
}
}
qh = EHCI_ADDR2QH(qh->hw.hlp);
@@ -1246,17 +1340,6 @@ void USBH_IRQHandler(void)
if (portsc & EHCI_PORTSC_CSC) {
if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) {
} else {
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
struct ehci_pipe *pipe = &g_ehci_hcd.pipe_pool[index];
struct usbh_urb *urb = pipe->urb;
if (pipe->waiter) {
pipe->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(pipe->waitsem);
}
}
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
g_ehci_hcd.ehci_qh_used[index] = false;
}
@@ -1267,12 +1350,28 @@ void USBH_IRQHandler(void)
g_ehci_hcd.ehci_itd_used[index] = false;
}
}
usbh_roothub_thread_wakeup(port + 1);
}
}
}
if (usbsts & EHCI_USBSTS_IAA) {
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
struct ehci_qh_hw *qh = &ehci_qh_pool[index];
if (g_ehci_hcd.ehci_qh_used[index] && qh->remove_in_iaad) {
struct usbh_urb *urb;
struct ehci_pipe *pipe;
urb = qh->urb;
pipe = urb->pipe;
qh->remove_in_iaad = 0;
ehci_qh_free(qh);
ehci_pipe_waitup(pipe);
}
}
}
if (usbsts & EHCI_USBSTS_FATAL) {

View File

@@ -302,7 +302,7 @@ struct ehci_hcor {
uint32_t ctrldssegment; /* 0x10: 4G Segment Selector */
uint32_t periodiclistbase; /* 0x14: Frame List Base Address */
uint32_t asynclistaddr; /* 0x18: Next Asynchronous List Address */
#ifndef CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
#ifndef CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
uint32_t reserved[9];
#endif
uint32_t configflag; /* 0x40: Configured Flag Register */

View File

@@ -10,6 +10,10 @@
#define USB_NUM_BIDIR_ENDPOINTS USB_SOC_DCD_MAX_ENDPOINT_COUNT
#endif
#if !defined(CONFIG_HPM_USBD_BASE) || !defined(CONFIG_HPM_USBD_IRQn)
#error "hpm dcd must config CONFIG_HPM_USBD_BASE and CONFIG_HPM_USBD_IRQn"
#endif
/* USBSTS, USBINTR */
enum {
intr_usb = HPM_BITSMASK(1, 0),
@@ -62,7 +66,7 @@ int usb_dc_init(void)
memset(&g_hpm_udc, 0, sizeof(struct hpm_udc));
g_hpm_udc.handle = &usb_device_handle[0];
g_hpm_udc.handle->regs = (USB_Type *)HPM_USB0_BASE;
g_hpm_udc.handle->regs = (USB_Type *)CONFIG_HPM_USBD_BASE;
g_hpm_udc.handle->dcd_data = &_dcd_data;
uint32_t int_mask;
@@ -71,7 +75,7 @@ int usb_dc_init(void)
usb_device_init(g_hpm_udc.handle, int_mask);
intc_m_enable_irq(IRQn_USB0);
intc_m_enable_irq(CONFIG_HPM_USBD_IRQn);
return 0;
}
@@ -279,8 +283,8 @@ void USBD_IRQHandler(void)
}
}
void isr_usb0(void)
void isr_usb(void)
{
USBD_IRQHandler();
}
SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0)
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBD_IRQn, isr_usb)

View File

@@ -630,6 +630,21 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
int usbh_pipe_free(usbh_pipe_t pipe)
{
struct musb_pipe *ppipe;
struct usbh_urb *urb;
ppipe = (struct musb_pipe *)pipe;
if (!ppipe) {
return -EINVAL;
}
urb = ppipe->urb;
if (urb) {
usbh_kill_urb(urb);
}
return 0;
}
@@ -704,6 +719,20 @@ errout_timeout:
int usbh_kill_urb(struct usbh_urb *urb)
{
struct musb_pipe *pipe;
pipe = urb->pipe;
if (!urb || !pipe) {
return -EINVAL;
}
if (pipe->waiter) {
pipe->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(pipe->waitsem);
}
return 0;
}
@@ -877,17 +906,6 @@ void USBH_IRQHandler(void)
g_musb_hcd.port_csc = 1;
g_musb_hcd.port_pec = 1;
g_musb_hcd.port_pe = 0;
for (uint8_t index = 0; index < CONFIG_USBHOST_PIPE_NUM; index++) {
for (uint8_t j = 0; j < 2; j++) {
struct musb_pipe *pipe = &g_musb_hcd.pipe_pool[index][j];
struct usbh_urb *urb = pipe->urb;
if (pipe->waiter) {
pipe->waiter = false;
urb->errorcode = -ESHUTDOWN;
usb_osal_sem_give(pipe->waitsem);
}
}
}
usbh_roothub_thread_wakeup(1);
}

View File

@@ -1,562 +0,0 @@
/*
* Copyright (c) 2013-2021 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 16. June 2021
* $Revision: V2.1.0
*
* Project: CMSIS-DAP Configuration
* Title: DAP_config.h CMSIS-DAP Configuration File (Template)
*
*---------------------------------------------------------------------------*/
#ifndef __DAP_CONFIG_H__
#define __DAP_CONFIG_H__
//**************************************************************************************************
/**
\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information
\ingroup DAP_ConfigIO_gr
@{
Provides definitions about the hardware and configuration of the Debug Unit.
This information includes:
- Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit.
- Debug Unit Identification strings (Vendor, Product, Serial Number).
- Debug Unit communication packet size.
- Debug Access Port supported modes and settings (JTAG/SWD and SWO).
- Optional information about a connected Target Device (for Evaluation Boards).
*/
#include <stdint.h>
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
/// Processor Clock of the Cortex-M MCU used in the Debug Unit.
/// This value is used to calculate the SWD/JTAG clock speed.
#define CPU_CLOCK 100000000U ///< Specifies the CPU Clock in Hz.
/// Number of processor cycles for I/O Port write operations.
/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O
/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors
/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses
/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be
/// required.
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0.
/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available.
/// Indicate that JTAG communication mode is available at the Debug Port.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available.
/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port.
/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255.
#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain.
/// Default communication mode on the Debug Access Port.
/// Used for the command \ref DAP_Connect when Port Default mode is selected.
#define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.
/// Default communication speed on the Debug Access Port for SWD and JTAG mode.
/// Used to initialize the default SWD/JTAG clock frequency.
/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting.
#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz.
/// Maximum Package Size for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB,
/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB.
#define DAP_PACKET_SIZE 512U ///< Specifies Packet Size in bytes.
/// Maximum Package Buffers for Command and Response data.
/// This configuration settings is used to optimize the communication performance with the
/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the
/// setting can be reduced (valid range is 1 .. 255).
#define DAP_PACKET_COUNT 8U ///< Specifies number of packets buffered.
/// Indicate that UART Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available.
/// USART Driver instance number for the UART SWO.
#define SWO_UART_DRIVER 0 ///< USART Driver instance number (Driver_USART#).
/// Maximum SWO UART Baudrate.
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz.
/// Indicate that Manchester Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
/// SWO Trace Buffer Size.
#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n).
/// SWO Streaming Trace.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.
/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET.
#define TIMESTAMP_CLOCK 100000000U ///< Timestamp clock in Hz (0 = timestamps not supported).
/// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available.
/// USART Driver instance number for the UART Communication Port.
#define DAP_UART_DRIVER 0 ///< USART Driver instance number (Driver_USART#).
/// UART Receive Buffer Size.
#define DAP_UART_RX_BUFFER_SIZE 1024U ///< Uart Receive Buffer Size in bytes (must be 2^n).
/// UART Transmit Buffer Size.
#define DAP_UART_TX_BUFFER_SIZE 1024U ///< Uart Transmit Buffer Size in bytes (must be 2^n).
/// Indicate that UART Communication via USB COM Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART_USB_COM_PORT 0 ///< USB COM Port: 1 = available, 0 = not available.
/// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed
/// known device. In this case a Device Vendor, Device Name, Board Vendor and Board Name strings
/// are stored and may be used by the debugger or IDE to configure device parameters.
#define TARGET_FIXED 0 ///< Target: 1 = known, 0 = unknown;
#define TARGET_DEVICE_VENDOR "Arm" ///< String indicating the Silicon Vendor
#define TARGET_DEVICE_NAME "Cortex-M" ///< String indicating the Target Device
#define TARGET_BOARD_VENDOR "Arm" ///< String indicating the Board Vendor
#define TARGET_BOARD_NAME "Arm board" ///< String indicating the Board Name
#if TARGET_FIXED != 0
#include <string.h>
static const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR;
static const char TargetDeviceName [] = TARGET_DEVICE_NAME;
static const char TargetBoardVendor [] = TARGET_BOARD_VENDOR;
static const char TargetBoardName [] = TARGET_BOARD_NAME;
#endif
/** Get Vendor Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetVendorString (char *str) {
(void)str;
return (0U);
}
/** Get Product Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetProductString (char *str) {
(void)str;
return (0U);
}
/** Get Serial Number string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) {
(void)str;
return (0U);
}
/** Get Target Device Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;
strcpy(str, TargetDeviceVendor);
len = (uint8_t)(strlen(TargetDeviceVendor) + 1U);
return (len);
#else
(void)str;
return (0U);
#endif
}
/** Get Target Device Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;
strcpy(str, TargetDeviceName);
len = (uint8_t)(strlen(TargetDeviceName) + 1U);
return (len);
#else
(void)str;
return (0U);
#endif
}
/** Get Target Board Vendor string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;
strcpy(str, TargetBoardVendor);
len = (uint8_t)(strlen(TargetBoardVendor) + 1U);
return (len);
#else
(void)str;
return (0U);
#endif
}
/** Get Target Board Name string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetTargetBoardNameString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;
strcpy(str, TargetBoardName);
len = (uint8_t)(strlen(TargetBoardName) + 1U);
return (len);
#else
(void)str;
return (0U);
#endif
}
/** Get Product Firmware Version string.
\param str Pointer to buffer to store the string (max 60 characters).
\return String length (including terminating NULL character) or 0 (no string).
*/
__STATIC_INLINE uint8_t DAP_GetProductFirmwareVersionString (char *str) {
(void)str;
return (0U);
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access
\ingroup DAP_ConfigIO_gr
@{
Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
interface of a device. The following I/O Pins are provided:
JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode
---------------------------- | -------------------- | ---------------------------------------------
TCK: Test Clock | SWCLK: Clock | Output Push/Pull
TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input | | Output Push/Pull
TDO: Test Data Output | | Input
nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor
nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor
DAP Hardware I/O Pin Access Functions
-------------------------------------
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.
For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only.
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
of the same I/O port. The following SWDIO I/O Pin functions are provided:
- \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware.
- \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware.
- \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed.
- \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/
// Configure DAP I/O pins ------------------------------
/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET.
Configures the DAP Hardware I/O pins for JTAG mode:
- TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
- TDO to input mode.
*/
__STATIC_INLINE void PORT_JTAG_SETUP (void) {
;
}
/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
- SWCLK, SWDIO, nRESET to output mode and set to default high level.
- TDI, nTRST to HighZ mode (pins are unused in SWD mode).
*/
__STATIC_INLINE void PORT_SWD_SETUP (void) {
;
}
/** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures:
- TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode.
*/
__STATIC_INLINE void PORT_OFF (void) {
;
}
// SWCLK/TCK I/O pin -------------------------------------
/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) {
return (0U);
}
/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) {
;
}
/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) {
;
}
// SWDIO/TMS Pin I/O --------------------------------------
/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) {
return (0U);
}
/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) {
;
}
/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) {
;
}
/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) {
return (0U);
}
/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) {
;
}
/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) {
;
}
/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) {
;
}
// TDI Pin I/O ---------------------------------------------
/** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) {
return (0U);
}
/** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) {
;
}
// TDO Pin I/O ---------------------------------------------
/** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) {
return (0U);
}
// nTRST Pin I/O -------------------------------------------
/** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) {
return (0U);
}
/** nTRST I/O pin: Set Output.
\param bit JTAG TRST Test Reset pin status:
- 0: issue a JTAG TRST Test Reset.
- 1: release JTAG TRST Test Reset.
*/
__STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) {
;
}
// nRESET Pin I/O------------------------------------------
/** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) {
return (0U);
}
/** nRESET I/O pin: Set Output.
\param bit target device hardware reset pin status:
- 0: issue a device hardware reset.
- 1: release device hardware reset.
*/
__STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) {
;
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr
@{
CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit.
It is recommended to provide the following LEDs for status indication:
- Connect LED: is active when the DAP hardware is connected to a debugger.
- Running LED: is active when the debugger has put the target device into running state.
*/
/** Debug Unit: Set status of Connected LED.
\param bit status of the Connect LED.
- 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
- 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
*/
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {}
/** Debug Unit: Set status Target Running LED.
\param bit status of the Target Running LED.
- 1: Target Running LED ON: program execution in target started.
- 0: Target Running LED OFF: program execution in target stopped.
*/
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp
\ingroup DAP_ConfigIO_gr
@{
Access function for Test Domain Timer.
The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By
default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK.
*/
/** Get timestamp of Test Domain Timer.
\return Current timestamp value.
*/
__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
return (0);
}
///@}
//**************************************************************************************************
/**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization
\ingroup DAP_ConfigIO_gr
@{
CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP.
*/
/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized).
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
- I/O clock system enabled.
- all I/O pins: input buffer enabled, output pins are set to HighZ mode.
- for nTRST, nRESET a weak pull-up (if available) is enabled.
- LED output pins are enabled and LEDs are turned off.
*/
__STATIC_INLINE void DAP_SETUP (void) {
;
}
/** Reset Target Device with custom specific I/O pin or command sequence.
This function allows the optional implementation of a device specific reset sequence.
It is called when the command \ref DAP_ResetTarget and is for example required
when a device needs a time-critical unlock sequence that enables the debug port.
\return 0 = no device specific reset sequence is implemented.\n
1 = a device specific reset sequence is implemented.
*/
__STATIC_INLINE uint8_t RESET_TARGET (void) {
return (0U); // change to '1' when a device reset sequence is implemented
}
///@}
#endif /* __DAP_CONFIG_H__ */

View File

@@ -1,367 +0,0 @@
/*
* Copyright (c) 2013-2022 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 26. April 2022
* $Revision: V2.1.1
*
* Project: CMSIS-DAP Include
* Title: DAP.h Definitions
*
*---------------------------------------------------------------------------*/
#ifndef __DAP_H__
#define __DAP_H__
// DAP Firmware Version
#ifdef DAP_FW_V1
#define DAP_FW_VER "1.3.0"
#else
#define DAP_FW_VER "2.1.1"
#endif
// DAP Command IDs
#define ID_DAP_Info 0x00U
#define ID_DAP_HostStatus 0x01U
#define ID_DAP_Connect 0x02U
#define ID_DAP_Disconnect 0x03U
#define ID_DAP_TransferConfigure 0x04U
#define ID_DAP_Transfer 0x05U
#define ID_DAP_TransferBlock 0x06U
#define ID_DAP_TransferAbort 0x07U
#define ID_DAP_WriteABORT 0x08U
#define ID_DAP_Delay 0x09U
#define ID_DAP_ResetTarget 0x0AU
#define ID_DAP_SWJ_Pins 0x10U
#define ID_DAP_SWJ_Clock 0x11U
#define ID_DAP_SWJ_Sequence 0x12U
#define ID_DAP_SWD_Configure 0x13U
#define ID_DAP_SWD_Sequence 0x1DU
#define ID_DAP_JTAG_Sequence 0x14U
#define ID_DAP_JTAG_Configure 0x15U
#define ID_DAP_JTAG_IDCODE 0x16U
#define ID_DAP_SWO_Transport 0x17U
#define ID_DAP_SWO_Mode 0x18U
#define ID_DAP_SWO_Baudrate 0x19U
#define ID_DAP_SWO_Control 0x1AU
#define ID_DAP_SWO_Status 0x1BU
#define ID_DAP_SWO_ExtendedStatus 0x1EU
#define ID_DAP_SWO_Data 0x1CU
#define ID_DAP_UART_Transport 0x1FU
#define ID_DAP_UART_Configure 0x20U
#define ID_DAP_UART_Control 0x22U
#define ID_DAP_UART_Status 0x23U
#define ID_DAP_UART_Transfer 0x21U
#define ID_DAP_QueueCommands 0x7EU
#define ID_DAP_ExecuteCommands 0x7FU
// DAP Vendor Command IDs
#define ID_DAP_Vendor0 0x80U
#define ID_DAP_Vendor1 0x81U
#define ID_DAP_Vendor2 0x82U
#define ID_DAP_Vendor3 0x83U
#define ID_DAP_Vendor4 0x84U
#define ID_DAP_Vendor5 0x85U
#define ID_DAP_Vendor6 0x86U
#define ID_DAP_Vendor7 0x87U
#define ID_DAP_Vendor8 0x88U
#define ID_DAP_Vendor9 0x89U
#define ID_DAP_Vendor10 0x8AU
#define ID_DAP_Vendor11 0x8BU
#define ID_DAP_Vendor12 0x8CU
#define ID_DAP_Vendor13 0x8DU
#define ID_DAP_Vendor14 0x8EU
#define ID_DAP_Vendor15 0x8FU
#define ID_DAP_Vendor16 0x90U
#define ID_DAP_Vendor17 0x91U
#define ID_DAP_Vendor18 0x92U
#define ID_DAP_Vendor19 0x93U
#define ID_DAP_Vendor20 0x94U
#define ID_DAP_Vendor21 0x95U
#define ID_DAP_Vendor22 0x96U
#define ID_DAP_Vendor23 0x97U
#define ID_DAP_Vendor24 0x98U
#define ID_DAP_Vendor25 0x99U
#define ID_DAP_Vendor26 0x9AU
#define ID_DAP_Vendor27 0x9BU
#define ID_DAP_Vendor28 0x9CU
#define ID_DAP_Vendor29 0x9DU
#define ID_DAP_Vendor30 0x9EU
#define ID_DAP_Vendor31 0x9FU
#define ID_DAP_Invalid 0xFFU
// DAP Status Code
#define DAP_OK 0U
#define DAP_ERROR 0xFFU
// DAP ID
#define DAP_ID_VENDOR 1U
#define DAP_ID_PRODUCT 2U
#define DAP_ID_SER_NUM 3U
#define DAP_ID_DAP_FW_VER 4U
#define DAP_ID_DEVICE_VENDOR 5U
#define DAP_ID_DEVICE_NAME 6U
#define DAP_ID_BOARD_VENDOR 7U
#define DAP_ID_BOARD_NAME 8U
#define DAP_ID_PRODUCT_FW_VER 9U
#define DAP_ID_CAPABILITIES 0xF0U
#define DAP_ID_TIMESTAMP_CLOCK 0xF1U
#define DAP_ID_UART_RX_BUFFER_SIZE 0xFBU
#define DAP_ID_UART_TX_BUFFER_SIZE 0xFCU
#define DAP_ID_SWO_BUFFER_SIZE 0xFDU
#define DAP_ID_PACKET_COUNT 0xFEU
#define DAP_ID_PACKET_SIZE 0xFFU
// DAP Host Status
#define DAP_DEBUGGER_CONNECTED 0U
#define DAP_TARGET_RUNNING 1U
// DAP Port
#define DAP_PORT_AUTODETECT 0U // Autodetect Port
#define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z)
#define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET
#define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET
// DAP SWJ Pins
#define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK
#define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS
#define DAP_SWJ_TDI 2 // TDI
#define DAP_SWJ_TDO 3 // TDO
#define DAP_SWJ_nTRST 5 // nTRST
#define DAP_SWJ_nRESET 7 // nRESET
// DAP Transfer Request
#define DAP_TRANSFER_APnDP (1U<<0)
#define DAP_TRANSFER_RnW (1U<<1)
#define DAP_TRANSFER_A2 (1U<<2)
#define DAP_TRANSFER_A3 (1U<<3)
#define DAP_TRANSFER_MATCH_VALUE (1U<<4)
#define DAP_TRANSFER_MATCH_MASK (1U<<5)
#define DAP_TRANSFER_TIMESTAMP (1U<<7)
// DAP Transfer Response
#define DAP_TRANSFER_OK (1U<<0)
#define DAP_TRANSFER_WAIT (1U<<1)
#define DAP_TRANSFER_FAULT (1U<<2)
#define DAP_TRANSFER_ERROR (1U<<3)
#define DAP_TRANSFER_MISMATCH (1U<<4)
// DAP SWO Trace Mode
#define DAP_SWO_OFF 0U
#define DAP_SWO_UART 1U
#define DAP_SWO_MANCHESTER 2U
// DAP SWO Trace Status
#define DAP_SWO_CAPTURE_ACTIVE (1U<<0)
#define DAP_SWO_CAPTURE_PAUSED (1U<<1)
#define DAP_SWO_STREAM_ERROR (1U<<6)
#define DAP_SWO_BUFFER_OVERRUN (1U<<7)
// DAP UART Transport
#define DAP_UART_TRANSPORT_NONE 0U
#define DAP_UART_TRANSPORT_USB_COM_PORT 1U
#define DAP_UART_TRANSPORT_DAP_COMMAND 2U
// DAP UART Control
#define DAP_UART_CONTROL_RX_ENABLE (1U<<0)
#define DAP_UART_CONTROL_RX_DISABLE (1U<<1)
#define DAP_UART_CONTROL_RX_BUF_FLUSH (1U<<2)
#define DAP_UART_CONTROL_TX_ENABLE (1U<<4)
#define DAP_UART_CONTROL_TX_DISABLE (1U<<5)
#define DAP_UART_CONTROL_TX_BUF_FLUSH (1U<<6)
// DAP UART Status
#define DAP_UART_STATUS_RX_ENABLED (1U<<0)
#define DAP_UART_STATUS_RX_DATA_LOST (1U<<1)
#define DAP_UART_STATUS_FRAMING_ERROR (1U<<2)
#define DAP_UART_STATUS_PARITY_ERROR (1U<<3)
#define DAP_UART_STATUS_TX_ENABLED (1U<<4)
// DAP UART Configure Error
#define DAP_UART_CFG_ERROR_DATA_BITS (1U<<0)
#define DAP_UART_CFG_ERROR_PARITY (1U<<1)
#define DAP_UART_CFG_ERROR_STOP_BITS (1U<<2)
// Debug Port Register Addresses
#define DP_IDCODE 0x00U // IDCODE Register (SW Read only)
#define DP_ABORT 0x00U // Abort Register (SW Write only)
#define DP_CTRL_STAT 0x04U // Control & Status
#define DP_WCR 0x04U // Wire Control Register (SW Only)
#define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W)
#define DP_RESEND 0x08U // Resend (SW Read Only)
#define DP_RDBUFF 0x0CU // Read Buffer (Read Only)
// JTAG IR Codes
#define JTAG_ABORT 0x08U
#define JTAG_DPACC 0x0AU
#define JTAG_APACC 0x0BU
#define JTAG_IDCODE 0x0EU
#define JTAG_BYPASS 0x0FU
// JTAG Sequence Info
#define JTAG_SEQUENCE_TCK 0x3FU // TCK count
#define JTAG_SEQUENCE_TMS 0x40U // TMS value
#define JTAG_SEQUENCE_TDO 0x80U // TDO capture
// SWD Sequence Info
#define SWD_SEQUENCE_CLK 0x3FU // SWCLK count
#define SWD_SEQUENCE_DIN 0x80U // SWDIO capture
#include <stddef.h>
#include <stdint.h>
#include "cmsis_compiler.h"
// DAP Data structure
typedef struct {
uint8_t debug_port; // Debug Port
uint8_t fast_clock; // Fast Clock Flag
uint8_t padding[2];
uint32_t clock_delay; // Clock Delay
uint32_t timestamp; // Last captured Timestamp
struct { // Transfer Configuration
uint8_t idle_cycles; // Idle cycles after transfer
uint8_t padding[3];
uint16_t retry_count; // Number of retries after WAIT response
uint16_t match_retry; // Number of retries if read value does not match
uint32_t match_mask; // Match Mask
} transfer;
#if (DAP_SWD != 0)
struct { // SWD Configuration
uint8_t turnaround; // Turnaround period
uint8_t data_phase; // Always generate Data Phase
} swd_conf;
#endif
#if (DAP_JTAG != 0)
struct { // JTAG Device Chain
uint8_t count; // Number of devices
uint8_t index; // Device index (device at TDO has index 0)
#if (DAP_JTAG_DEV_CNT != 0)
uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits
uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR
uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR
#endif
} jtag_dev;
#endif
} DAP_Data_t;
extern DAP_Data_t DAP_Data; // DAP Data
extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag
#ifdef __cplusplus
extern "C"
{
#endif
// Functions
extern void SWJ_Sequence (uint32_t count, const uint8_t *data);
extern void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
extern void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo);
extern void JTAG_IR (uint32_t ir);
extern uint32_t JTAG_ReadIDCode (void);
extern void JTAG_WriteAbort (uint32_t data);
extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data);
extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data);
extern void Delayms (uint32_t delay);
extern uint32_t SWO_Transport (const uint8_t *request, uint8_t *response);
extern uint32_t SWO_Mode (const uint8_t *request, uint8_t *response);
extern uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response);
extern uint32_t SWO_Control (const uint8_t *request, uint8_t *response);
extern uint32_t SWO_Status (uint8_t *response);
extern uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response);
extern uint32_t SWO_Data (const uint8_t *request, uint8_t *response);
extern void SWO_QueueTransfer (uint8_t *buf, uint32_t num);
extern void SWO_AbortTransfer (void);
extern void SWO_TransferComplete (void);
extern uint32_t SWO_Mode_UART (uint32_t enable);
extern uint32_t SWO_Baudrate_UART (uint32_t baudrate);
extern uint32_t SWO_Control_UART (uint32_t active);
extern void SWO_Capture_UART (uint8_t *buf, uint32_t num);
extern uint32_t SWO_GetCount_UART (void);
extern uint32_t SWO_Mode_Manchester (uint32_t enable);
extern uint32_t SWO_Baudrate_Manchester (uint32_t baudrate);
extern uint32_t SWO_Control_Manchester (uint32_t active);
extern void SWO_Capture_Manchester (uint8_t *buf, uint32_t num);
extern uint32_t SWO_GetCount_Manchester (void);
extern uint32_t UART_Transport (const uint8_t *request, uint8_t *response);
extern uint32_t UART_Configure (const uint8_t *request, uint8_t *response);
extern uint32_t UART_Control (const uint8_t *request, uint8_t *response);
extern uint32_t UART_Status (uint8_t *response);
extern uint32_t UART_Transfer (const uint8_t *request, uint8_t *response);
extern uint8_t USB_COM_PORT_Activate (uint32_t cmd);
extern uint32_t DAP_ProcessVendorCommand (const uint8_t *request, uint8_t *response);
extern uint32_t DAP_ProcessCommand (const uint8_t *request, uint8_t *response);
extern uint32_t DAP_ExecuteCommand (const uint8_t *request, uint8_t *response);
extern void DAP_Setup (void);
// Configurable delay for clock generation
#ifndef DELAY_SLOW_CYCLES
#define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration
#endif
#if defined(__CC_ARM)
__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) {
uint32_t count = delay;
while (--count);
}
#else
__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) {
__ASM volatile (
".syntax unified\n"
"0:\n\t"
"subs %0,%0,#1\n\t"
"bne 0b\n"
: "+l" (delay) : : "cc"
);
}
#endif
// Fixed delay for fast clock generation
#ifndef DELAY_FAST_CYCLES
#define DELAY_FAST_CYCLES 0U // Number of cycles: 0..3
#endif
__STATIC_FORCEINLINE void PIN_DELAY_FAST (void) {
#if (DELAY_FAST_CYCLES >= 1U)
__NOP();
#endif
#if (DELAY_FAST_CYCLES >= 2U)
__NOP();
#endif
#if (DELAY_FAST_CYCLES >= 3U)
__NOP();
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* __DAP_H__ */

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File diff suppressed because it is too large Load Diff

View File

@@ -1,100 +0,0 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 1. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: DAP_vendor.c CMSIS-DAP Vendor Commands
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
//**************************************************************************************************
/**
\defgroup DAP_Vendor_Adapt_gr Adapt Vendor Commands
\ingroup DAP_Vendor_gr
@{
The file DAP_vendor.c provides template source code for extension of a Debug Unit with
Vendor Commands. Copy this file to the project folder of the Debug Unit and add the
file to the MDK-ARM project under the file group Configuration.
*/
/** Process DAP Vendor Command and prepare Response Data
\param request pointer to request data
\param response pointer to response data
\return number of bytes in response (lower 16 bits)
number of bytes in request (upper 16 bits)
*/
uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) {
uint32_t num = (1U << 16) | 1U;
*response++ = *request; // copy Command ID
switch (*request++) { // first byte in request is Command ID
case ID_DAP_Vendor0:
#if 0 // example user command
num += 1U << 16; // increment request count
if (*request == 1U) { // when first command data byte is 1
*response++ = 'X'; // send 'X' as response
num++; // increment response count
}
#endif
break;
case ID_DAP_Vendor1: break;
case ID_DAP_Vendor2: break;
case ID_DAP_Vendor3: break;
case ID_DAP_Vendor4: break;
case ID_DAP_Vendor5: break;
case ID_DAP_Vendor6: break;
case ID_DAP_Vendor7: break;
case ID_DAP_Vendor8: break;
case ID_DAP_Vendor9: break;
case ID_DAP_Vendor10: break;
case ID_DAP_Vendor11: break;
case ID_DAP_Vendor12: break;
case ID_DAP_Vendor13: break;
case ID_DAP_Vendor14: break;
case ID_DAP_Vendor15: break;
case ID_DAP_Vendor16: break;
case ID_DAP_Vendor17: break;
case ID_DAP_Vendor18: break;
case ID_DAP_Vendor19: break;
case ID_DAP_Vendor20: break;
case ID_DAP_Vendor21: break;
case ID_DAP_Vendor22: break;
case ID_DAP_Vendor23: break;
case ID_DAP_Vendor24: break;
case ID_DAP_Vendor25: break;
case ID_DAP_Vendor26: break;
case ID_DAP_Vendor27: break;
case ID_DAP_Vendor28: break;
case ID_DAP_Vendor29: break;
case ID_DAP_Vendor30: break;
case ID_DAP_Vendor31: break;
}
return (num);
}
///@}

View File

@@ -1,370 +0,0 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 1. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: JTAG_DP.c CMSIS-DAP JTAG DP I/O
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
// JTAG Macros
#define PIN_TCK_SET PIN_SWCLK_TCK_SET
#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR
#define PIN_TMS_SET PIN_SWDIO_TMS_SET
#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR
#define JTAG_CYCLE_TCK() \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDI(tdi) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDO(tdo) \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDIO(tdi,tdo) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#if (DAP_JTAG != 0)
// Generate JTAG Sequence
// info: sequence information
// tdi: pointer to TDI generated data
// tdo: pointer to TDO captured data
// return: none
void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo) {
uint32_t i_val;
uint32_t o_val;
uint32_t bit;
uint32_t n, k;
n = info & JTAG_SEQUENCE_TCK;
if (n == 0U) {
n = 64U;
}
if (info & JTAG_SEQUENCE_TMS) {
PIN_TMS_SET();
} else {
PIN_TMS_CLR();
}
while (n) {
i_val = *tdi++;
o_val = 0U;
for (k = 8U; k && n; k--, n--) {
JTAG_CYCLE_TDIO(i_val, bit);
i_val >>= 1;
o_val >>= 1;
o_val |= bit << 7;
}
o_val >>= k;
if (info & JTAG_SEQUENCE_TDO) {
*tdo++ = (uint8_t)o_val;
}
}
}
// JTAG Set IR
// ir: IR value
// return: none
#define JTAG_IR_Function(speed) /**/ \
static void JTAG_IR_##speed (uint32_t ir) { \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-IR */ \
JTAG_CYCLE_TCK(); /* Shift-IR */ \
\
PIN_TDI_OUT(1U); \
for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1U; n; n--) { \
JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \
ir >>= 1; \
} \
n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \
if (n) { \
JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \
PIN_TDI_OUT(1U); \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \
} \
\
JTAG_CYCLE_TCK(); /* Update-IR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(1U); \
}
// JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define JTAG_TransferFunction(speed) /**/ \
static uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \
uint32_t ack; \
uint32_t bit; \
uint32_t val; \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-DR */ \
JTAG_CYCLE_TCK(); /* Shift-DR */ \
\
for (n = DAP_Data.jtag_dev.index; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
\
JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \
ack = bit << 1; \
JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \
ack |= bit << 0; \
JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \
ack |= bit << 2; \
\
if (ack != DAP_TRANSFER_OK) { \
/* Exit on error */ \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Exit1-DR */ \
goto exit; \
} \
\
if (request & DAP_TRANSFER_RnW) { \
/* Read Transfer */ \
val = 0U; \
for (n = 31U; n; n--) { \
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \
val |= bit << 31; \
val >>= 1; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \
if (n) { \
JTAG_CYCLE_TDO(bit); /* Get D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \
} \
val |= bit << 31; \
if (data) { *data = val; } \
} else { \
/* Write Transfer */ \
val = *data; \
for (n = 31U; n; n--) { \
JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \
val >>= 1; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \
if (n) { \
JTAG_CYCLE_TDI(val); /* Set D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \
} \
} \
\
exit: \
JTAG_CYCLE_TCK(); /* Update-DR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(1U); \
\
/* Capture Timestamp */ \
if (request & DAP_TRANSFER_TIMESTAMP) { \
DAP_Data.timestamp = TIMESTAMP_GET(); \
} \
\
/* Idle cycles */ \
n = DAP_Data.transfer.idle_cycles; \
while (n--) { \
JTAG_CYCLE_TCK(); /* Idle */ \
} \
\
return ((uint8_t)ack); \
}
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
JTAG_IR_Function(Fast)
JTAG_TransferFunction(Fast)
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
JTAG_IR_Function(Slow)
JTAG_TransferFunction(Slow)
// JTAG Read IDCODE register
// return: value read
uint32_t JTAG_ReadIDCode (void) {
uint32_t bit;
uint32_t val;
uint32_t n;
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */
for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
}
val = 0U;
for (n = 31U; n; n--) {
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */
val |= bit << 31;
val >>= 1;
}
PIN_TMS_SET();
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */
val |= bit << 31;
JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */
return (val);
}
// JTAG Write ABORT register
// data: value to write
// return: none
void JTAG_WriteAbort (uint32_t data) {
uint32_t n;
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */
for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
}
PIN_TDI_OUT(0U);
JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */
JTAG_CYCLE_TCK(); /* Set A2=0 */
JTAG_CYCLE_TCK(); /* Set A3=0 */
for (n = 31U; n; n--) {
JTAG_CYCLE_TDI(data); /* Set D0..D30 */
data >>= 1;
}
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U;
if (n) {
JTAG_CYCLE_TDI(data); /* Set D31 */
for (--n; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass after data */
}
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */
} else {
PIN_TMS_SET();
JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */
}
JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */
PIN_TDI_OUT(1U);
}
// JTAG Set IR
// ir: IR value
// return: none
void JTAG_IR (uint32_t ir) {
if (DAP_Data.fast_clock) {
JTAG_IR_Fast(ir);
} else {
JTAG_IR_Slow(ir);
}
}
// JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return JTAG_TransferFast(request, data);
} else {
return JTAG_TransferSlow(request, data);
}
}
#endif /* (DAP_JTAG != 0) */

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