Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c0ef50bb3 | ||
|
|
0f2cb9f900 | ||
|
|
7c1fae04b2 | ||
|
|
14f5dd2dd3 | ||
|
|
9029f8c5b1 | ||
|
|
b9915e0e1b | ||
|
|
1387790744 | ||
|
|
c5fc9f338e | ||
|
|
4d61e5e053 | ||
|
|
1a7259649b | ||
|
|
628e4ee928 | ||
|
|
749369b6fc | ||
|
|
89cd77374c | ||
|
|
3792ad4905 | ||
|
|
2789633b50 | ||
|
|
94505f9e41 | ||
|
|
c8b832e1a0 | ||
|
|
d3aa9449e1 | ||
|
|
4d7938e349 | ||
|
|
4777a65f54 | ||
|
|
96c0b655fd | ||
|
|
61da3794cf | ||
|
|
45ea9928bc | ||
|
|
64e2b8d480 | ||
|
|
fed6f26ebd | ||
|
|
513772a534 | ||
|
|
e45a2857df | ||
|
|
c8ecf31c99 | ||
|
|
4395c7f039 | ||
|
|
3057f41020 | ||
|
|
47c0255cdc | ||
|
|
d53e8a2adf | ||
|
|
3bdb3bbf84 | ||
|
|
3c1168d58c | ||
|
|
f672591d58 | ||
|
|
84598eed7c | ||
|
|
7574063e94 | ||
|
|
0d916af297 | ||
|
|
b90d6a727e | ||
|
|
d0d6f99c90 | ||
|
|
9673b2cf67 | ||
|
|
7061367484 | ||
|
|
faf90663a9 | ||
|
|
bb58348510 | ||
|
|
8253f074ce | ||
|
|
8a93ca4bce | ||
|
|
8968b7b3c9 | ||
|
|
2ca22deaad | ||
|
|
340fa4e024 | ||
|
|
822cd9d679 | ||
|
|
e061b8e784 | ||
|
|
8856361be0 | ||
|
|
1c7110bd86 | ||
|
|
48efbfe521 | ||
|
|
c540080c96 | ||
|
|
d970f88f06 | ||
|
|
2d1b4b8b82 | ||
|
|
9bac9537db | ||
|
|
f35b345680 | ||
|
|
56868b513a |
@@ -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()
|
||||
48
README.md
48
README.md
@@ -4,7 +4,7 @@
|
||||
|
||||
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
|
||||
|
||||

|
||||

|
||||
|
||||
## Why choose
|
||||
|
||||
@@ -85,12 +85,13 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3263 | 384 | 17 | 0 |
|
||||
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 501 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|
||||
|usbd_video.c | 2272 | 0 | 82 | 0 |
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|
||||
|usbd_video.c | 2494 | 0 | 84 | 0 |
|
||||
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|
||||
|
||||
## Host Stack Overview
|
||||
|
||||
@@ -116,13 +117,14 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|
||||
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|
||||
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|
||||
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|
||||
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|
||||
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
|
||||
@@ -134,6 +136,18 @@ Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affe
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
x is affected by the following macros:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## Documentation Tutorial
|
||||
|
||||
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
||||
@@ -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 |
|
||||
|
||||
48
README_zh.md
48
README_zh.md
@@ -4,7 +4,7 @@
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
||||
|
||||

|
||||

|
||||
|
||||
## 为什么选择
|
||||
|
||||
@@ -83,12 +83,13 @@ CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3263 | 384 | 17 | 0 |
|
||||
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 501 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|
||||
|usbd_video.c | 2272 | 0 | 82 | 0 |
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|
||||
|usbd_video.c | 2494 | 0 | 84 | 0 |
|
||||
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|
||||
|
||||
## Host 协议栈简介
|
||||
|
||||
@@ -114,13 +115,14 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 4895 | 32 + 4* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|
||||
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|
||||
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|
||||
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|
||||
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|
||||
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
|
||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||
|
||||
@@ -132,6 +134,18 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
x 受以下宏影响:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## 文档教程
|
||||
|
||||
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
|
||||
@@ -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 |
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -812,6 +812,19 @@ struct audio_cs_ep_ep_general_descriptor {
|
||||
|
||||
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
|
||||
|
||||
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
bNumEndpoints, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_MIDISTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
|
||||
0x00 /* iInterface */
|
||||
|
||||
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT_LEN 0x09
|
||||
|
||||
struct audio_v2_channel_cluster_descriptor {
|
||||
uint8_t bNrChannels;
|
||||
uint32_t bmChannelConfig;
|
||||
@@ -1072,7 +1085,7 @@ struct audio_v2_control_range3_param_block {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
|
||||
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
|
||||
bInterval, /* bInterval */ \
|
||||
0x08, /* bLength */ \
|
||||
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
|
||||
@@ -6,109 +6,71 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_audio.h"
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
struct usbd_audio_volume_info {
|
||||
uint16_t vol_min;
|
||||
uint16_t vol_max;
|
||||
uint16_t vol_res;
|
||||
uint16_t vol_current;
|
||||
struct audio_entity_param {
|
||||
uint32_t wCur;
|
||||
uint32_t wMin;
|
||||
uint32_t wMax;
|
||||
uint32_t wRes;
|
||||
};
|
||||
|
||||
struct usbd_audio_attribute_control {
|
||||
struct usbd_audio_volume_info volume[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
uint8_t automatic_gain[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
};
|
||||
#else
|
||||
struct audio_v2_control_range2_param_block_default {
|
||||
uint16_t wNumSubRanges;
|
||||
struct
|
||||
{
|
||||
uint16_t wMin;
|
||||
uint16_t wMax;
|
||||
uint16_t wRes;
|
||||
} subrange[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
} __PACKED;
|
||||
struct usbd_audio_priv {
|
||||
struct audio_entity_info *table;
|
||||
uint8_t num;
|
||||
uint16_t uac_version;
|
||||
} g_usbd_audio;
|
||||
|
||||
struct usbd_audio_attribute_control {
|
||||
uint32_t volume_bCUR;
|
||||
uint32_t mute_bCUR;
|
||||
struct audio_v2_control_range2_param_block_default volume;
|
||||
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||
};
|
||||
#endif
|
||||
struct audio_entity_info {
|
||||
usb_slist_t list;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bEntityId;
|
||||
void *priv[2];
|
||||
};
|
||||
|
||||
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t control_selector;
|
||||
uint32_t sampling_freq = 0;
|
||||
uint8_t pitch_enable;
|
||||
uint8_t ep;
|
||||
|
||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
|
||||
control_selector = HI_BYTE(setup->wValue);
|
||||
ep = LO_BYTE(setup->wIndex);
|
||||
control_selector = HI_BYTE(setup->wValue);
|
||||
ep = LO_BYTE(setup->wIndex);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
|
||||
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
||||
USB_LOG_DBG("Set ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(0, ep, sampling_freq);
|
||||
break;
|
||||
case AUDIO_EP_CONTROL_PITCH:
|
||||
pitch_enable = (*data)[0];
|
||||
usbd_audio_set_pitch(ep, pitch_enable);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
sampling_freq = 16000;
|
||||
memcpy(*data, &sampling_freq, 4);
|
||||
*len = 4;
|
||||
USB_LOG_DBG("Get ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
switch (control_selector) {
|
||||
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
||||
memcpy(*data, &sampling_freq, 3);
|
||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
*len = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("AUDIO Class request: "
|
||||
USB_LOG_DBG("Audio Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
struct audio_entity_info *current_entity_info = NULL;
|
||||
struct usbd_audio_attribute_control *current_feature_control = NULL;
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
uint32_t *sampling_freq;
|
||||
#endif
|
||||
usb_slist_t *i;
|
||||
uint8_t entity_id;
|
||||
uint8_t ep;
|
||||
uint8_t subtype = 0x01;
|
||||
uint8_t control_selector;
|
||||
uint8_t ch;
|
||||
uint8_t mute;
|
||||
uint16_t volume;
|
||||
int volume_db = 0;
|
||||
uint32_t sampling_freq = 0;
|
||||
|
||||
const char *mute_string[2] = { "off", "on" };
|
||||
|
||||
entity_id = HI_BYTE(setup->wIndex);
|
||||
@@ -116,211 +78,189 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
||||
ch = LO_BYTE(setup->wValue);
|
||||
|
||||
ARG_UNUSED(mute_string);
|
||||
if (ch > (CONFIG_USBDEV_AUDIO_MAX_CHANNEL - 1)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
usb_slist_for_each(i, &usbd_audio_entity_info_head)
|
||||
{
|
||||
struct audio_entity_info *tmp_entity_info = usb_slist_entry(i, struct audio_entity_info, list);
|
||||
if (tmp_entity_info->bEntityId == entity_id) {
|
||||
current_entity_info = tmp_entity_info;
|
||||
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
|
||||
if (g_usbd_audio.table[i].bEntityId == entity_id) {
|
||||
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
|
||||
ep = g_usbd_audio.table[i].ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_entity_info == NULL) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
sampling_freq = (uint32_t *)current_entity_info->priv[1];
|
||||
#endif
|
||||
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
float volume2db = 0.0;
|
||||
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
mute = (*data)[0];
|
||||
current_feature_control->mute[ch] = mute;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
|
||||
usbd_audio_set_mute(entity_id, ch, mute);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
(*data)[0] = current_feature_control->mute[ch];
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
|
||||
current_feature_control->volume[ch].vol_current = volume;
|
||||
|
||||
if (volume < 0x8000) {
|
||||
volume2db = 0.00390625 * volume;
|
||||
} else if (volume > 0x8000) {
|
||||
volume2db = -0.00390625 * (0xffff - volume + 1);
|
||||
}
|
||||
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] %0.4f dB\r\n", entity_id, ch, volume2db);
|
||||
usbd_audio_set_volume(entity_id, ch, volume2db);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_current, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_min, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_max, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
memcpy(*data, ¤t_feature_control->volume[ch].vol_res, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_REQUEST_SET_RES:
|
||||
memcpy(¤t_feature_control->volume[ch].vol_res, *data, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = current_feature_control->mute_bCUR;
|
||||
*len = 1;
|
||||
} else {
|
||||
mute = (*data)[0];
|
||||
current_feature_control->mute_bCUR = mute;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
|
||||
usbd_audio_set_mute(entity_id, ch, mute);
|
||||
}
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = current_feature_control->volume_bCUR & 0XFF;
|
||||
(*data)[1] = (current_feature_control->volume_bCUR >> 8) & 0xff;
|
||||
*len = 2;
|
||||
} else {
|
||||
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
|
||||
current_feature_control->volume_bCUR = volume;
|
||||
USB_LOG_DBG("Set UnitId:%d ch[%d] %d dB\r\n", entity_id, ch, volume);
|
||||
usbd_audio_set_volume(entity_id, ch, volume);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
*((uint16_t *)(*data + 0)) = current_feature_control->volume.wNumSubRanges;
|
||||
*((uint16_t *)(*data + 2)) = current_feature_control->volume.subrange[ch].wMin;
|
||||
*((uint16_t *)(*data + 4)) = current_feature_control->volume.subrange[ch].wMax;
|
||||
*((uint16_t *)(*data + 6)) = current_feature_control->volume.subrange[ch].wRes;
|
||||
*len = 8;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
else if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
memcpy(*data, &sampling_freq[ch], sizeof(uint32_t));
|
||||
USB_LOG_DBG("Get ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
|
||||
*len = 4;
|
||||
} else {
|
||||
memcpy(&sampling_freq[ch], *data, setup->wLength);
|
||||
USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
|
||||
usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq[ch]);
|
||||
}
|
||||
break;
|
||||
case AUDIO_CS_CONTROL_CLOCK_VALID:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = 1;
|
||||
*len = 1;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
uint8_t *sampling_freq_table = NULL;
|
||||
uint16_t num;
|
||||
|
||||
usbd_audio_get_sampling_freq_table(entity_id, &sampling_freq_table);
|
||||
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
||||
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
||||
*len = (12 * num + 2);
|
||||
USB_LOG_DBG("Get sampling_freq_table entity_id:%d ch[%d] addr:%x\r\n", entity_id, ch, (uint32_t)sampling_freq_table);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (subtype == 0x01) {
|
||||
USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
|
||||
|
||||
switch (subtype) {
|
||||
case AUDIO_CONTROL_FEATURE_UNIT:
|
||||
switch (control_selector) {
|
||||
case AUDIO_FU_CONTROL_MUTE:
|
||||
if (g_usbd_audio.uac_version < 0x0200) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
mute = (*data)[0];
|
||||
usbd_audio_set_mute(ep, ch, mute);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
||||
*len = 1;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
||||
*len = 1;
|
||||
} else {
|
||||
mute = (*data)[0];
|
||||
usbd_audio_set_mute(ep, ch, mute);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AUDIO_FU_CONTROL_VOLUME:
|
||||
if (g_usbd_audio.uac_version < 0x0200) {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
memcpy(&volume, *data, *len);
|
||||
if (volume < 0x8000) {
|
||||
volume_db = volume / 256;
|
||||
} else if (volume > 0x8000) {
|
||||
volume_db = (0xffff - volume + 1) / -256;
|
||||
}
|
||||
volume_db += 128; /* 0 ~ 255 */
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
|
||||
usbd_audio_set_volume(ep, ch, volume_db);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
volume_db = usbd_audio_get_volume(ep, ch);
|
||||
volume_db -= 128;
|
||||
if (volume_db >= 0) {
|
||||
volume = volume_db * 256;
|
||||
} else {
|
||||
volume = volume_db * 256 + 0xffff + 1;
|
||||
}
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
(*data)[0] = 0x00; /* -2560/256 dB */
|
||||
(*data)[1] = 0xdb;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
(*data)[0] = 0x00; /* 0 dB */
|
||||
(*data)[1] = 0x00;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
(*data)[0] = 0x00; /* -256/256 dB */
|
||||
(*data)[1] = 0x01;
|
||||
*len = 2;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
volume_db = usbd_audio_get_volume(ep, ch);
|
||||
volume = volume_db;
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
} else {
|
||||
memcpy(&volume, *data, *len);
|
||||
volume_db = volume;
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
|
||||
usbd_audio_set_volume(ep, ch, volume_db);
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
*((uint16_t *)(*data + 0)) = 1;
|
||||
*((uint16_t *)(*data + 2)) = 0;
|
||||
*((uint16_t *)(*data + 4)) = 100;
|
||||
*((uint16_t *)(*data + 6)) = 1;
|
||||
*len = 8;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_CONTROL_CLOCK_SOURCE:
|
||||
switch (control_selector) {
|
||||
case AUDIO_CS_CONTROL_SAM_FREQ:
|
||||
switch (setup->bRequest) {
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
||||
memcpy(*data, &sampling_freq, 4);
|
||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
*len = 4;
|
||||
} else {
|
||||
memcpy(&sampling_freq, *data, setup->wLength);
|
||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
uint8_t *sampling_freq_table = NULL;
|
||||
uint16_t num;
|
||||
|
||||
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
|
||||
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
||||
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
||||
*len = (12 * num + 2);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_CS_CONTROL_CLOCK_VALID:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
(*data)[0] = 1;
|
||||
*len = 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -333,7 +273,7 @@ static void audio_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
case USBD_EVENT_SET_INTERFACE: {
|
||||
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
||||
if (intf->bAlternateSetting == 1) {
|
||||
if (intf->bAlternateSetting) {
|
||||
usbd_audio_open(intf->bInterfaceNumber);
|
||||
} else {
|
||||
usbd_audio_close(intf->bInterfaceNumber);
|
||||
@@ -347,86 +287,57 @@ static void audio_notify_handler(uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf)
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
||||
uint16_t uac_version,
|
||||
struct audio_entity_info *table,
|
||||
uint8_t num)
|
||||
{
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
|
||||
#else
|
||||
intf->class_endpoint_handler = NULL;
|
||||
#endif
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
if (uac_version < 0x0200) {
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
} else {
|
||||
intf->class_interface_handler = audio_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
}
|
||||
|
||||
g_usbd_audio.uac_version = uac_version;
|
||||
g_usbd_audio.table = table;
|
||||
g_usbd_audio.num = num;
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
|
||||
{
|
||||
struct audio_entity_info *entity_info = usb_malloc(sizeof(struct audio_entity_info));
|
||||
memset(entity_info, 0, sizeof(struct audio_entity_info));
|
||||
entity_info->bEntityId = entity_id;
|
||||
entity_info->bDescriptorSubtype = bDescriptorSubtype;
|
||||
|
||||
if (bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
|
||||
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
|
||||
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
control->volume[ch].vol_min = 0xdb00;
|
||||
control->volume[ch].vol_max = 0x0000;
|
||||
control->volume[ch].vol_res = 0x0100;
|
||||
control->volume[ch].vol_current = 0xf600;
|
||||
control->mute[ch] = 0;
|
||||
control->automatic_gain[ch] = 0;
|
||||
}
|
||||
#else
|
||||
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
|
||||
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
|
||||
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
control->volume.wNumSubRanges = 1;
|
||||
control->volume.subrange[ch].wMin = 0;
|
||||
control->volume.subrange[ch].wMax = 100;
|
||||
control->volume.subrange[ch].wRes = 1;
|
||||
control->mute[ch] = 0;
|
||||
control->volume_bCUR = 0;
|
||||
control->mute_bCUR = 0;
|
||||
}
|
||||
#endif
|
||||
entity_info->priv[0] = control;
|
||||
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
|
||||
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
|
||||
sampling_freq[ch] = 16000;
|
||||
}
|
||||
entity_info->priv[1] = sampling_freq;
|
||||
#else
|
||||
entity_info->priv[1] = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB)
|
||||
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
|
||||
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
}
|
||||
|
||||
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
|
||||
{
|
||||
}
|
||||
@@ -12,17 +12,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct audio_entity_info {
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bEntityId;
|
||||
uint8_t ep;
|
||||
};
|
||||
|
||||
/* Init audio interface driver */
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf);
|
||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
||||
uint16_t uac_version,
|
||||
struct audio_entity_info *table,
|
||||
uint8_t num);
|
||||
|
||||
void usbd_audio_open(uint8_t intf);
|
||||
void usbd_audio_close(uint8_t intf);
|
||||
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
|
||||
void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB);
|
||||
void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable);
|
||||
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq);
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table);
|
||||
void usbd_audio_set_pitch(uint8_t ep, bool enable);
|
||||
|
||||
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
|
||||
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
|
||||
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
|
||||
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
|
||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
|
||||
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -17,33 +17,38 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
|
||||
|
||||
static int usbh_audio_devno_alloc(struct usbh_audio *audio_class)
|
||||
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_audio *usbh_audio_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
audio_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
|
||||
g_audio_class[devno].minor = devno;
|
||||
return &g_audio_class[devno];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_audio_devno_free(struct usbh_audio *audio_class)
|
||||
static void usbh_audio_class_free(struct usbh_audio *audio_class)
|
||||
{
|
||||
int devno = audio_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
}
|
||||
|
||||
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
|
||||
@@ -269,14 +274,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
uint8_t format_offset = 0;
|
||||
uint8_t *p;
|
||||
|
||||
struct usbh_audio *audio_class = usb_malloc(sizeof(struct usbh_audio));
|
||||
struct usbh_audio *audio_class = usbh_audio_class_alloc();
|
||||
if (audio_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc audio_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
usbh_audio_devno_alloc(audio_class);
|
||||
audio_class->hport = hport;
|
||||
audio_class->ctrl_intf = intf;
|
||||
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
|
||||
@@ -412,8 +415,6 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_audio *audio_class = (struct usbh_audio *)hport->config.intf[intf].priv;
|
||||
|
||||
if (audio_class) {
|
||||
usbh_audio_devno_free(audio_class);
|
||||
|
||||
if (audio_class->isoin) {
|
||||
usbh_pipe_free(audio_class->isoin);
|
||||
}
|
||||
@@ -427,8 +428,7 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_audio_stop(audio_class);
|
||||
}
|
||||
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
usb_free(audio_class);
|
||||
usbh_audio_class_free(audio_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -16,7 +16,6 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
setup->bRequest);
|
||||
|
||||
struct cdc_line_coding line_coding;
|
||||
struct cdc_line_coding line_coding_last;
|
||||
bool dtr, rts;
|
||||
uint8_t intf_num = LO_BYTE(setup->wIndex);
|
||||
|
||||
@@ -48,15 +47,10 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
parity_name[line_coding.bParityType],
|
||||
stop_name[line_coding.bCharFormat]);
|
||||
|
||||
/* check if current line coding is the same with last, if they are the same, do not set line coding */
|
||||
usbd_cdc_acm_get_line_coding(intf_num, &line_coding_last);
|
||||
if (memcmp(&line_coding_last, &line_coding, sizeof(struct cdc_line_coding))) {
|
||||
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
|
||||
}
|
||||
|
||||
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE: {
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||
dtr = (setup->wValue & 0x0001);
|
||||
rts = (setup->wValue & 0x0002);
|
||||
USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
|
||||
@@ -65,7 +59,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
rts);
|
||||
usbd_cdc_acm_set_dtr(intf_num, dtr);
|
||||
usbd_cdc_acm_set_rts(intf_num, rts);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_GET_LINE_CODING:
|
||||
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
|
||||
@@ -78,7 +72,9 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
line_coding.bParityType,
|
||||
line_coding.bDataBits);
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SEND_BREAK:
|
||||
usbd_cdc_acm_send_break(intf_num);
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
@@ -115,4 +111,8 @@ __WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_cod
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define FLASH_ERASE_TIME 50
|
||||
#endif
|
||||
|
||||
struct dfu_cfg_priv {
|
||||
struct usbd_dfu_priv {
|
||||
struct dfu_info info;
|
||||
union {
|
||||
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
|
||||
@@ -40,26 +40,26 @@ struct dfu_cfg_priv {
|
||||
uint8_t dev_state;
|
||||
uint8_t manif_state;
|
||||
uint8_t firmwar_flag;
|
||||
} usbd_dfu_cfg;
|
||||
} g_usbd_dfu;
|
||||
|
||||
static void dfu_reset(void)
|
||||
{
|
||||
memset(&usbd_dfu_cfg, 0, sizeof(usbd_dfu_cfg));
|
||||
memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
|
||||
|
||||
usbd_dfu_cfg.alt_setting = 0U;
|
||||
usbd_dfu_cfg.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
g_usbd_dfu.alt_setting = 0U;
|
||||
g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[5] = 0U;
|
||||
}
|
||||
|
||||
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
|
||||
@@ -84,21 +84,21 @@ static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
|
||||
|
||||
static void dfu_request_detach(void)
|
||||
{
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /*iString*/
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
g_usbd_dfu.dev_status[5] = 0U; /*iString*/
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,62 +109,62 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
uint8_t *phaddr;
|
||||
/* Data setup request */
|
||||
if (req->wLength > 0U) {
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
/* Update the global length and block number */
|
||||
usbd_dfu_cfg.wblock_num = req->wValue;
|
||||
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
g_usbd_dfu.wblock_num = req->wValue;
|
||||
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
|
||||
/* DFU Get Command */
|
||||
if (usbd_dfu_cfg.wblock_num == 0U) {
|
||||
if (g_usbd_dfu.wblock_num == 0U) {
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = (usbd_dfu_cfg.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/* Store the values of all supported commands */
|
||||
usbd_dfu_cfg.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
|
||||
usbd_dfu_cfg.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
|
||||
usbd_dfu_cfg.buffer.d8[2] = DFU_CMD_ERASE;
|
||||
g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
|
||||
g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
|
||||
g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.buffer.d8, 3);
|
||||
memcpy(*data, g_usbd_dfu.buffer.d8, 3);
|
||||
*len = 3;
|
||||
} else if (usbd_dfu_cfg.wblock_num > 1U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
} else if (g_usbd_dfu.wblock_num > 1U) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
|
||||
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
|
||||
|
||||
/* Return the physical address where data are stored */
|
||||
phaddr = dfu_read_flash((uint8_t *)addr, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
|
||||
phaddr = dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
|
||||
*len = usbd_dfu_cfg.wlength;
|
||||
} else /* unsupported usbd_dfu_cfg.wblock_num */
|
||||
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
*len = g_usbd_dfu.wlength;
|
||||
} else /* unsupported g_usbd_dfu.wblock_num */
|
||||
{
|
||||
usbd_dfu_cfg.dev_state = DFU_STATUS_ERR_STALLEDPKT;
|
||||
g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported usbd_dfu_cfg.wblock_num\r\n");
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
|
||||
}
|
||||
}
|
||||
/* Unsupported state */
|
||||
else {
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
|
||||
@@ -172,12 +172,12 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
}
|
||||
/* No Data setup request */
|
||||
else {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,19 +186,19 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
/* Data setup request */
|
||||
struct usb_setup_packet *req = setup;
|
||||
if (req->wLength > 0U) {
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
|
||||
/* Update the global length and block number */
|
||||
usbd_dfu_cfg.wblock_num = req->wValue;
|
||||
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
g_usbd_dfu.wblock_num = req->wValue;
|
||||
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
|
||||
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
/*!< Data has received complete */
|
||||
memcpy((uint8_t *)usbd_dfu_cfg.buffer.d8, (uint8_t *)*data, usbd_dfu_cfg.wlength);
|
||||
memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
|
||||
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
|
||||
usbd_dfu_cfg.firmwar_flag = 1;
|
||||
g_usbd_dfu.firmwar_flag = 1;
|
||||
}
|
||||
/* Unsupported state */
|
||||
else {
|
||||
@@ -208,16 +208,16 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
/* 0 Data DNLOAD request */
|
||||
else {
|
||||
/* End of DNLOAD operation*/
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE)) {
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_IN_PROGRESS;
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
} else {
|
||||
/* Call the error management function (command will be NAKed */
|
||||
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", usbd_dfu_cfg.dev_state);
|
||||
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,63 +225,63 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
static int8_t dfu_getstatus_special_handler(void)
|
||||
{
|
||||
uint32_t addr;
|
||||
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
|
||||
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
|
||||
/* Decode the Special Command */
|
||||
if (usbd_dfu_cfg.wblock_num == 0U) {
|
||||
if (usbd_dfu_cfg.wlength == 1U) {
|
||||
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
|
||||
if (g_usbd_dfu.wblock_num == 0U) {
|
||||
if (g_usbd_dfu.wlength == 1U) {
|
||||
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
|
||||
/* Nothing to do */
|
||||
}
|
||||
} else if (usbd_dfu_cfg.wlength == 5U) {
|
||||
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
|
||||
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
|
||||
} else if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE) {
|
||||
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
|
||||
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
|
||||
} else if (g_usbd_dfu.wlength == 5U) {
|
||||
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
|
||||
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
|
||||
} else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
|
||||
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
|
||||
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
|
||||
|
||||
USB_LOG_DBG("Erase start add %08x \r\n", usbd_dfu_cfg.data_ptr);
|
||||
USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
|
||||
/*!< Erase */
|
||||
dfu_erase_flash(usbd_dfu_cfg.data_ptr);
|
||||
dfu_erase_flash(g_usbd_dfu.data_ptr);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Reset the global length and block number */
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
/* Call the error management function (command will be NAKed) */
|
||||
USB_LOG_ERR("Reset the global length and block number\r\n");
|
||||
}
|
||||
}
|
||||
/* Regular Download Command */
|
||||
else {
|
||||
if (usbd_dfu_cfg.wblock_num > 1U) {
|
||||
if (g_usbd_dfu.wblock_num > 1U) {
|
||||
/* Decode the required address */
|
||||
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
|
||||
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
|
||||
|
||||
/* Perform the write operation */
|
||||
/* Write flash */
|
||||
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, usbd_dfu_cfg.wlength);
|
||||
dfu_write_flash(usbd_dfu_cfg.buffer.d8, (uint8_t *)addr, usbd_dfu_cfg.wlength);
|
||||
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
|
||||
dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the global length and block number */
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
|
||||
/* Update the state machine */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -289,77 +289,77 @@ static int8_t dfu_getstatus_special_handler(void)
|
||||
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
/*!< Determine whether to leave DFU mode */
|
||||
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS &&
|
||||
usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
|
||||
usbd_dfu_cfg.dev_status[1] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[2] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[3] == 0U &&
|
||||
usbd_dfu_cfg.dev_status[4] == usbd_dfu_cfg.dev_state) {
|
||||
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
|
||||
g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
|
||||
g_usbd_dfu.dev_status[1] == 0U &&
|
||||
g_usbd_dfu.dev_status[2] == 0U &&
|
||||
g_usbd_dfu.dev_status[3] == 0U &&
|
||||
g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
|
||||
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
|
||||
|
||||
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
return;
|
||||
} else {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
/* Generate system reset to allow jumping to the user code */
|
||||
dfu_leave();
|
||||
}
|
||||
}
|
||||
|
||||
switch (usbd_dfu_cfg.dev_state) {
|
||||
switch (g_usbd_dfu.dev_state) {
|
||||
case DFU_STATE_DFU_DNLOAD_SYNC:
|
||||
if (usbd_dfu_cfg.wlength != 0U) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
|
||||
if (g_usbd_dfu.wlength != 0U) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
|
||||
if ((usbd_dfu_cfg.wblock_num == 0U) && (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE)) {
|
||||
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_ERASE, usbd_dfu_cfg.dev_status);
|
||||
if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
|
||||
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
|
||||
} else {
|
||||
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_PROGRAM, usbd_dfu_cfg.dev_status);
|
||||
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
|
||||
}
|
||||
} else /* (usbd_dfu_cfg.wlength==0)*/
|
||||
} else /* (g_usbd_dfu.wlength==0)*/
|
||||
{
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case DFU_STATE_DFU_MANIFEST_SYNC:
|
||||
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST;
|
||||
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
} else {
|
||||
if ((usbd_dfu_cfg.manif_state == DFU_MANIFEST_COMPLETE) &&
|
||||
if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
|
||||
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U;
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U;
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -369,62 +369,62 @@ static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data
|
||||
}
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, usbd_dfu_cfg.dev_status, 6);
|
||||
memcpy(*data, g_usbd_dfu.dev_status, 6);
|
||||
*len = 6;
|
||||
|
||||
if (usbd_dfu_cfg.firmwar_flag == 1) {
|
||||
if (g_usbd_dfu.firmwar_flag == 1) {
|
||||
if (dfu_getstatus_special_handler() != 0) {
|
||||
USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
|
||||
}
|
||||
usbd_dfu_cfg.firmwar_flag = 0;
|
||||
g_usbd_dfu.firmwar_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dfu_request_clrstatus(void)
|
||||
{
|
||||
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_ERROR) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK; /* bStatus */
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
} else {
|
||||
/* State Error */
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_ERROR;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
}
|
||||
}
|
||||
|
||||
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
/* Return the current state of the DFU interface */
|
||||
(*data)[0] = usbd_dfu_cfg.dev_state;
|
||||
(*data)[0] = g_usbd_dfu.dev_state;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
void dfu_request_abort(void)
|
||||
{
|
||||
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
|
||||
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
|
||||
usbd_dfu_cfg.dev_status[1] = 0U;
|
||||
usbd_dfu_cfg.dev_status[2] = 0U;
|
||||
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
|
||||
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
|
||||
usbd_dfu_cfg.wblock_num = 0U;
|
||||
usbd_dfu_cfg.wlength = 0U;
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
|
||||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
|
||||
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
|
||||
g_usbd_dfu.dev_status[1] = 0U;
|
||||
g_usbd_dfu.dev_status[2] = 0U;
|
||||
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
|
||||
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
|
||||
g_usbd_dfu.dev_status[5] = 0U; /* iString */
|
||||
g_usbd_dfu.wblock_num = 0U;
|
||||
g_usbd_dfu.wlength = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,27 +17,27 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
|
||||
switch (setup->bRequest) {
|
||||
case HID_REQUEST_GET_REPORT:
|
||||
/* report id ,report type */
|
||||
usbh_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
||||
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
||||
break;
|
||||
case HID_REQUEST_GET_IDLE:
|
||||
(*data)[0] = usbh_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
|
||||
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_GET_PROTOCOL:
|
||||
(*data)[0] = usbh_hid_get_protocol(intf_num);
|
||||
(*data)[0] = usbd_hid_get_protocol(intf_num);
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_SET_REPORT:
|
||||
/* report id ,report type, report, report len */
|
||||
usbh_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
||||
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
||||
break;
|
||||
case HID_REQUEST_SET_IDLE:
|
||||
/* report id, duration */
|
||||
usbh_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
||||
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
||||
break;
|
||||
case HID_REQUEST_SET_PROTOCOL:
|
||||
/* protocol */
|
||||
usbh_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
|
||||
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -60,30 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
|
||||
return intf;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
__WEAK void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(*data[0]) = 0;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id)
|
||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbh_hid_get_protocol(uint8_t intf)
|
||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
__WEAK void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
|
||||
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
|
||||
{
|
||||
}
|
||||
@@ -20,12 +20,12 @@ void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
|
||||
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
||||
uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id);
|
||||
uint8_t usbh_hid_get_protocol(uint8_t intf);
|
||||
void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
|
||||
void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
|
||||
void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol);
|
||||
void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
||||
uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id);
|
||||
uint8_t usbd_hid_get_protocol(uint8_t intf);
|
||||
void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
|
||||
void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
|
||||
void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -8,33 +8,34 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/input%d"
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
||||
|
||||
static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
|
||||
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_hid *usbh_hid_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
hid_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
|
||||
g_hid_class[devno].minor = devno;
|
||||
return &g_hid_class[devno];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_hid_devno_free(struct usbh_hid *hid_class)
|
||||
static void usbh_hid_class_free(struct usbh_hid *hid_class)
|
||||
{
|
||||
int devno = hid_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
}
|
||||
|
||||
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
@@ -106,14 +107,12 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid));
|
||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||
if (hid_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hid_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usbh_hid_devno_alloc(hid_class);
|
||||
hid_class->hport = hport;
|
||||
hid_class->intf = intf;
|
||||
|
||||
@@ -159,8 +158,6 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
|
||||
|
||||
if (hid_class) {
|
||||
usbh_hid_devno_free(hid_class);
|
||||
|
||||
if (hid_class->intin) {
|
||||
usbh_pipe_free(hid_class->intin);
|
||||
}
|
||||
@@ -174,8 +171,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_hid_stop(hid_class);
|
||||
}
|
||||
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
usb_free(hid_class);
|
||||
usbh_hid_class_free(hid_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static uint32_t g_devinuse = 0;
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
|
||||
|
||||
@@ -28,9 +24,6 @@ usb_osal_mq_t hub_mq;
|
||||
|
||||
struct usbh_hub roothub;
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
#endif
|
||||
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
@@ -46,26 +39,32 @@ struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int usbh_hub_devno_alloc(void)
|
||||
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_hub *usbh_hub_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
return devno;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
|
||||
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
|
||||
return &g_hub_class[devno];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_hub_devno_free(uint8_t devno)
|
||||
static void usbh_hub_class_free(struct usbh_hub *hub_class)
|
||||
{
|
||||
if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
|
||||
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(hub_class, 0, sizeof(struct usbh_hub));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -109,7 +108,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -131,6 +130,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -23,6 +23,26 @@
|
||||
#define MIDI_PITCHBEND_MIN -8192
|
||||
#define MIDI_PITCHBEND_MAX 8191
|
||||
|
||||
/*! Enumeration of MIDI code index number */
|
||||
enum MidiCodeIndexNumber {
|
||||
MIDI_CIN_MISC = 0,
|
||||
MIDI_CIN_CABLE_EVENT = 1,
|
||||
MIDI_CIN_SYSCOM_2BYTE = 2, ///< 2 byte system common message e.g MTC, SongSelect
|
||||
MIDI_CIN_SYSCOM_3BYTE = 3, ///< 3 byte system common message e.g SPP
|
||||
MIDI_CIN_SYSEX_START = 4, ///< SysEx starts or continue
|
||||
MIDI_CIN_SYSEX_END_1BYTE = 5, ///< SysEx ends with 1 data, or 1 byte system common message
|
||||
MIDI_CIN_SYSEX_END_2BYTE = 6, ///< SysEx ends with 2 data
|
||||
MIDI_CIN_SYSEX_END_3BYTE = 7, ///< SysEx ends with 3 data
|
||||
MIDI_CIN_NOTE_OFF = 8,
|
||||
MIDI_CIN_NOTE_ON = 9,
|
||||
MIDI_CIN_POLY_KEYPRESS = 10,
|
||||
MIDI_CIN_CONTROL_CHANGE = 11,
|
||||
MIDI_CIN_PROGRAM_CHANGE = 12,
|
||||
MIDI_CIN_CHANNEL_PRESSURE = 13,
|
||||
MIDI_CIN_PITCH_BEND_CHANGE = 14,
|
||||
MIDI_CIN_1BYTE_DATA = 15
|
||||
};
|
||||
|
||||
/*! Enumeration of MIDI types */
|
||||
enum MidiType {
|
||||
InvalidType = 0x00, ///< For notifying errors
|
||||
@@ -181,6 +201,13 @@ struct midi_cs_ep_ms_general_descriptor {
|
||||
#define MIDI_SIZEOF_MS_GENERAL_DESC(n) (4 + n)
|
||||
|
||||
// clang-format off
|
||||
#define MIDI_CS_HEADER_DESCRIPTOR_INIT(wTotalLength) \
|
||||
0x07, /* bLength */ \
|
||||
USB_CS_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubtype */ \
|
||||
WBVAL(0x0100), /* bcdMSC */ \
|
||||
WBVAL(wTotalLength) /* wTotalLength */
|
||||
|
||||
#define MIDI_IN_JACK_DESCRIPTOR_INIT(bJackType, bJackID) \
|
||||
0x06, \
|
||||
0x24, \
|
||||
|
||||
@@ -61,8 +61,7 @@ struct CSW {
|
||||
/*Length of template descriptor: 23 bytes*/
|
||||
#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -77,39 +76,14 @@ struct CSW {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#else
|
||||
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
|
||||
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
|
||||
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_MSC_H */
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usb_scsi.h"
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
#define MSD_OUT_EP_IDX 0
|
||||
#define MSD_IN_EP_IDX 1
|
||||
@@ -23,13 +26,14 @@ enum Stage {
|
||||
};
|
||||
|
||||
/* Device data structure */
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
|
||||
/* state of the bulk-only state machine */
|
||||
enum Stage stage;
|
||||
USB_MEM_ALIGNX struct CBW cbw;
|
||||
USB_MEM_ALIGNX struct CSW csw;
|
||||
|
||||
bool readonly;
|
||||
bool popup;
|
||||
uint8_t sKey; /* Sense key */
|
||||
uint8_t ASC; /* Additional Sense Code */
|
||||
uint8_t ASQ; /* Additional Sense Qualifier */
|
||||
@@ -39,13 +43,19 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
|
||||
uint16_t scsi_blk_size;
|
||||
uint32_t scsi_blk_nbr;
|
||||
|
||||
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||
} usbd_msc_cfg;
|
||||
USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
|
||||
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_t usbd_msc_mq;
|
||||
usb_osal_thread_t usbd_msc_thread;
|
||||
uint32_t nbytes;
|
||||
#endif
|
||||
} g_usbd_msc;
|
||||
|
||||
static void usbd_msc_reset(void)
|
||||
{
|
||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||
usbd_msc_cfg.readonly = false;
|
||||
g_usbd_msc.stage = MSC_READ_CBW;
|
||||
g_usbd_msc.readonly = false;
|
||||
}
|
||||
|
||||
static int msc_storage_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
@@ -60,7 +70,7 @@ static int msc_storage_class_interface_request_handler(struct usb_setup_packet *
|
||||
break;
|
||||
|
||||
case MSC_REQUEST_GET_MAX_LUN:
|
||||
(*data)[0] = usbd_msc_cfg.max_lun;
|
||||
(*data)[0] = g_usbd_msc.max_lun;
|
||||
*len = 1;
|
||||
break;
|
||||
|
||||
@@ -80,7 +90,7 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
USB_LOG_DBG("Start reading cbw\r\n");
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -90,40 +100,40 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
static void usbd_msc_bot_abort(void)
|
||||
{
|
||||
if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) {
|
||||
if ((g_usbd_msc.cbw.bmFlags == 0) && (g_usbd_msc.cbw.dDataLength != 0)) {
|
||||
usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
|
||||
}
|
||||
usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
|
||||
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
}
|
||||
|
||||
static void usbd_msc_send_csw(uint8_t CSW_Status)
|
||||
{
|
||||
usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature;
|
||||
usbd_msc_cfg.csw.bStatus = CSW_Status;
|
||||
g_usbd_msc.csw.dSignature = MSC_CSW_Signature;
|
||||
g_usbd_msc.csw.bStatus = CSW_Status;
|
||||
|
||||
/* updating the State Machine , so that we wait CSW when this
|
||||
* transfer is complete, ie when we get a bulk in callback
|
||||
*/
|
||||
usbd_msc_cfg.stage = MSC_WAIT_CSW;
|
||||
g_usbd_msc.stage = MSC_WAIT_CSW;
|
||||
|
||||
USB_LOG_DBG("Send csw\r\n");
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, sizeof(struct CSW));
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.csw, sizeof(struct CSW));
|
||||
}
|
||||
|
||||
static void usbd_msc_send_info(uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
size = MIN(size, usbd_msc_cfg.cbw.dDataLength);
|
||||
size = MIN(size, g_usbd_msc.cbw.dDataLength);
|
||||
|
||||
/* updating the State Machine , so that we send CSW when this
|
||||
* transfer is complete, ie when we get a bulk in callback
|
||||
*/
|
||||
usbd_msc_cfg.stage = MSC_SEND_CSW;
|
||||
g_usbd_msc.stage = MSC_SEND_CSW;
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size);
|
||||
|
||||
usbd_msc_cfg.csw.dDataResidue -= size;
|
||||
usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED;
|
||||
g_usbd_msc.csw.dDataResidue -= size;
|
||||
g_usbd_msc.csw.bStatus = CSW_STATUS_CMD_PASSED;
|
||||
}
|
||||
|
||||
static bool SCSI_processWrite(uint32_t nbytes);
|
||||
@@ -139,9 +149,9 @@ static bool SCSI_processRead(void);
|
||||
*/
|
||||
static void SCSI_SetSenseData(uint32_t KCQ)
|
||||
{
|
||||
usbd_msc_cfg.sKey = (uint8_t)(KCQ >> 16);
|
||||
usbd_msc_cfg.ASC = (uint8_t)(KCQ >> 8);
|
||||
usbd_msc_cfg.ASQ = (uint8_t)(KCQ);
|
||||
g_usbd_msc.sKey = (uint8_t)(KCQ >> 16);
|
||||
g_usbd_msc.ASC = (uint8_t)(KCQ >> 8);
|
||||
g_usbd_msc.ASQ = (uint8_t)(KCQ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +161,7 @@ static void SCSI_SetSenseData(uint32_t KCQ)
|
||||
|
||||
static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
@@ -163,13 +173,13 @@ static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
|
||||
uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
|
||||
@@ -193,9 +203,9 @@ static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
|
||||
0x00,
|
||||
};
|
||||
|
||||
request_sense[2] = usbd_msc_cfg.sKey;
|
||||
request_sense[12] = usbd_msc_cfg.ASC;
|
||||
request_sense[13] = usbd_msc_cfg.ASQ;
|
||||
request_sense[2] = g_usbd_msc.sKey;
|
||||
request_sense[12] = g_usbd_msc.ASC;
|
||||
request_sense[13] = g_usbd_msc.ASQ;
|
||||
#if 0
|
||||
request_sense[ 2] = 0x06; /* UNIT ATTENTION */
|
||||
request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
|
||||
@@ -269,16 +279,16 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
|
||||
memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
|
||||
if (usbd_msc_cfg.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
|
||||
if (g_usbd_msc.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
|
||||
data_len = 0x06;
|
||||
memcpy(*data, (uint8_t *)inquiry00, data_len);
|
||||
} else if (usbd_msc_cfg.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
|
||||
} else if (g_usbd_msc.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
|
||||
data_len = 0x08;
|
||||
memcpy(*data, (uint8_t *)inquiry80, data_len);
|
||||
} else { /* Request Not supported */
|
||||
@@ -286,8 +296,8 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
memcpy(*data, (uint8_t *)inquiry, data_len);
|
||||
}
|
||||
@@ -298,18 +308,19 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
|
||||
if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
|
||||
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_EJECTED;
|
||||
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
|
||||
g_usbd_msc.popup = true;
|
||||
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
|
||||
{
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else {
|
||||
@@ -322,11 +333,11 @@ static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength != 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
if (usbd_msc_cfg.cbw.CB[4] == 0U) {
|
||||
if (g_usbd_msc.cbw.CB[4] == 0U) {
|
||||
//SCSI_MEDIUM_UNLOCKED;
|
||||
} else {
|
||||
//SCSI_MEDIUM_LOCKED;
|
||||
@@ -339,17 +350,17 @@ static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = 4;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[4];
|
||||
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
|
||||
data_len = g_usbd_msc.cbw.CB[4];
|
||||
}
|
||||
|
||||
uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (usbd_msc_cfg.readonly) {
|
||||
if (g_usbd_msc.readonly) {
|
||||
sense6[2] = 0x80;
|
||||
}
|
||||
memcpy(*data, (uint8_t *)sense6, data_len);
|
||||
@@ -360,13 +371,13 @@ static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t data_len = 27;
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.CB[8] < 27) {
|
||||
data_len = usbd_msc_cfg.cbw.CB[8];
|
||||
if (g_usbd_msc.cbw.CB[8] < 27) {
|
||||
data_len = g_usbd_msc.cbw.CB[8];
|
||||
}
|
||||
|
||||
uint8_t sense10[27] = {
|
||||
@@ -406,7 +417,7 @@ static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
@@ -415,15 +426,15 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
0x00,
|
||||
0x00,
|
||||
0x08, /* Capacity List Length */
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 24) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 16) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 24) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 16) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 0) & 0xff),
|
||||
|
||||
0x02, /* Descriptor Code: Formatted Media */
|
||||
0x00,
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
|
||||
};
|
||||
|
||||
memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
|
||||
@@ -433,21 +444,21 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
|
||||
if (g_usbd_msc.cbw.dDataLength == 0U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 24) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 16) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 8) & 0xff),
|
||||
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 0) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 24) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 16) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 8) & 0xff),
|
||||
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 0) & 0xff),
|
||||
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 24) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 16) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 24) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 16) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
|
||||
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
|
||||
};
|
||||
|
||||
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
|
||||
@@ -457,113 +468,123 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_read10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
|
||||
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
|
||||
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_IN;
|
||||
g_usbd_msc.stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool SCSI_read12(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
|
||||
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
|
||||
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_IN;
|
||||
g_usbd_msc.stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool SCSI_write10(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != data_len) {
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SCSI_write12(uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
|
||||
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
|
||||
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
|
||||
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
|
||||
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
|
||||
|
||||
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
|
||||
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
|
||||
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != data_len) {
|
||||
return false;
|
||||
}
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
return true;
|
||||
}
|
||||
/* do not use verify to reduce code size */
|
||||
@@ -574,41 +595,41 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
|
||||
uint32_t lba = 0;
|
||||
uint32_t blk_num = 0;
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x00U) {
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x00U) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
|
||||
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x02U) {
|
||||
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x02U) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA);
|
||||
return false; /* Error, Verify Mode Not supported*/
|
||||
}
|
||||
|
||||
lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]);
|
||||
lba = GET_BE32(&g_usbd_msc.cbw.CB[2]);
|
||||
USB_LOG_DBG("lba: 0x%x\r\n", lba);
|
||||
|
||||
usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size;
|
||||
g_usbd_msc.scsi_blk_addr = lba * g_usbd_msc.scsi_blk_size;
|
||||
|
||||
/* Number of Blocks to transfer */
|
||||
blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]);
|
||||
blk_num = GET_BE16(&g_usbd_msc.cbw.CB[7]);
|
||||
|
||||
USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
|
||||
usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size;
|
||||
g_usbd_msc.scsi_blk_len = blk_num * g_usbd_msc.scsi_blk_size;
|
||||
|
||||
if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) {
|
||||
if ((lba + blk_num) > g_usbd_msc.scsi_blk_nbr) {
|
||||
USB_LOG_ERR("LBA out of range\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) {
|
||||
if (g_usbd_msc.cbw.dDataLength != g_usbd_msc.scsi_blk_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.stage = MSC_DATA_OUT;
|
||||
g_usbd_msc.stage = MSC_DATA_OUT;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -617,23 +638,23 @@ static bool SCSI_processRead(void)
|
||||
{
|
||||
uint32_t transfer_len;
|
||||
|
||||
USB_LOG_DBG("read lba:%d\r\n", usbd_msc_cfg.start_sector);
|
||||
USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
transfer_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
|
||||
if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) {
|
||||
if (usbd_msc_sector_read(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, transfer_len) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len);
|
||||
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, g_usbd_msc.block_buffer, transfer_len);
|
||||
|
||||
usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
|
||||
g_usbd_msc.start_sector += (transfer_len / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.nsectors -= (transfer_len / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.csw.dDataResidue -= transfer_len;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
usbd_msc_cfg.stage = MSC_SEND_CSW;
|
||||
if (g_usbd_msc.nsectors == 0) {
|
||||
g_usbd_msc.stage = MSC_SEND_CSW;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -642,22 +663,22 @@ static bool SCSI_processRead(void)
|
||||
static bool SCSI_processWrite(uint32_t nbytes)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector);
|
||||
USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc.start_sector);
|
||||
|
||||
if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) {
|
||||
if (usbd_msc_sector_write(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, nbytes) != 0) {
|
||||
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size);
|
||||
usbd_msc_cfg.csw.dDataResidue -= nbytes;
|
||||
g_usbd_msc.start_sector += (nbytes / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.nsectors -= (nbytes / g_usbd_msc.scsi_blk_size);
|
||||
g_usbd_msc.csw.dDataResidue -= nbytes;
|
||||
|
||||
if (usbd_msc_cfg.nsectors == 0) {
|
||||
if (g_usbd_msc.nsectors == 0) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
|
||||
} else {
|
||||
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
|
||||
data_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -665,7 +686,7 @@ static bool SCSI_processWrite(uint32_t nbytes)
|
||||
|
||||
static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
{
|
||||
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
|
||||
uint8_t *buf2send = g_usbd_msc.block_buffer;
|
||||
uint32_t len2send = 0;
|
||||
bool ret = false;
|
||||
|
||||
@@ -675,15 +696,15 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
|
||||
usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
|
||||
g_usbd_msc.csw.dTag = g_usbd_msc.cbw.dTag;
|
||||
g_usbd_msc.csw.dDataResidue = g_usbd_msc.cbw.dDataLength;
|
||||
|
||||
if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
|
||||
if ((g_usbd_msc.cbw.bLUN > 1) || (g_usbd_msc.cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc.cbw.bCBLength < 1) || (g_usbd_msc.cbw.bCBLength > 16)) {
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
} else {
|
||||
USB_LOG_DBG("Decode CB:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_TESTUNITREADY:
|
||||
ret = SCSI_testUnitReady(&buf2send, &len2send);
|
||||
break;
|
||||
@@ -730,13 +751,13 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
|
||||
default:
|
||||
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
|
||||
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
if (usbd_msc_cfg.stage == MSC_READ_CBW) {
|
||||
if (g_usbd_msc.stage == MSC_READ_CBW) {
|
||||
if (len2send) {
|
||||
USB_LOG_DBG("Send info len:%d\r\n", len2send);
|
||||
usbd_msc_send_info(buf2send, len2send);
|
||||
@@ -750,21 +771,26 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (usbd_msc_cfg.stage) {
|
||||
switch (g_usbd_msc.stage) {
|
||||
case MSC_READ_CBW:
|
||||
if (SCSI_CBWDecode(nbytes) == false) {
|
||||
USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]);
|
||||
USB_LOG_ERR("Command:0x%02x decode err\r\n", g_usbd_msc.cbw.CB[0]);
|
||||
usbd_msc_bot_abort();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MSC_DATA_OUT:
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_WRITE10:
|
||||
case SCSI_CMD_WRITE12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
g_usbd_msc.nbytes = nbytes;
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_OUT);
|
||||
#else
|
||||
if (SCSI_processWrite(nbytes) == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -777,15 +803,19 @@ void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (usbd_msc_cfg.stage) {
|
||||
switch (g_usbd_msc.stage) {
|
||||
case MSC_DATA_IN:
|
||||
switch (usbd_msc_cfg.cbw.CB[0]) {
|
||||
switch (g_usbd_msc.cbw.CB[0]) {
|
||||
case SCSI_CMD_READ10:
|
||||
case SCSI_CMD_READ12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
|
||||
#else
|
||||
if (SCSI_processRead() == false) {
|
||||
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -798,9 +828,9 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
/*the host has received the CSW*/
|
||||
case MSC_WAIT_CSW:
|
||||
usbd_msc_cfg.stage = MSC_READ_CBW;
|
||||
g_usbd_msc.stage = MSC_READ_CBW;
|
||||
USB_LOG_DBG("Start reading cbw\r\n");
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
|
||||
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -808,6 +838,32 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbdev_msc_thread(void *argument)
|
||||
{
|
||||
uintptr_t event;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(g_usbd_msc.usbd_msc_mq, (uintptr_t *)&event, 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;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
|
||||
void usbd_msc_set_readonly(bool readonly);
|
||||
bool usbd_msc_set_popup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -9,33 +9,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;
|
||||
|
||||
@@ -437,9 +437,8 @@ struct mtp_container_response {
|
||||
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
|
||||
|
||||
// clang-format off
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
|
||||
/* Interface */ \
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
@@ -453,13 +452,13 @@ struct mtp_container_response {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x40, 0x00, /* wMaxPacketSize */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
@@ -467,37 +466,6 @@ struct mtp_container_response {
|
||||
0x03, /* bmAttributes */ \
|
||||
0x1c, 0x00, /* wMaxPacketSize */ \
|
||||
0x06 /* bInterval */
|
||||
#else
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x03, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
|
||||
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
|
||||
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
0x00, 0x02, /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x1c, 0x00, /* wMaxPacketSize */ \
|
||||
0x06 /* bInterval */
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_MTP_H */
|
||||
|
||||
@@ -16,7 +16,7 @@ enum Stage {
|
||||
MTP_WAIT_RESPONSE = 4,
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp_priv {
|
||||
USB_MEM_ALIGNX struct mtp_container_command con_command;
|
||||
USB_MEM_ALIGNX struct mtp_container_data con_data;
|
||||
USB_MEM_ALIGNX struct mtp_container_response con_response;
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_printer.h"
|
||||
|
||||
struct printer_cfg_priv {
|
||||
struct usbd_printer_priv {
|
||||
const uint8_t *device_id;
|
||||
uint8_t device_id_len;
|
||||
uint8_t port_status;
|
||||
} usbd_printer_cfg;
|
||||
} g_usbd_printer;
|
||||
|
||||
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
@@ -20,8 +20,8 @@ static int printer_class_interface_request_handler(struct usb_setup_packet *setu
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case PRINTER_REQUEST_GET_DEVICE_ID:
|
||||
memcpy(*data, usbd_printer_cfg.device_id, usbd_printer_cfg.device_id_len);
|
||||
*len = usbd_printer_cfg.device_id_len;
|
||||
memcpy(*data, g_usbd_printer.device_id, g_usbd_printer.device_id_len);
|
||||
*len = g_usbd_printer.device_id_len;
|
||||
break;
|
||||
case PRINTER_REQUEST_GET_PORT_SATTUS:
|
||||
|
||||
@@ -55,7 +55,7 @@ struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = printer_notify_handler;
|
||||
|
||||
usbd_printer_cfg.device_id = device_id;
|
||||
usbd_printer_cfg.device_id_len = device_id_len;
|
||||
g_usbd_printer.device_id = device_id;
|
||||
g_usbd_printer.device_id_len = device_id_len;
|
||||
return intf;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,34 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/printer"
|
||||
|
||||
static struct usbh_printer g_printer_class[CONFIG_USBHOST_MAX_PRINTER_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_printer *usbh_printer_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_PRINTER_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_printer_class[devno], 0, sizeof(struct usbh_printer));
|
||||
g_printer_class[devno].minor = devno;
|
||||
return &g_printer_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_printer_class_free(struct usbh_printer *printer_class)
|
||||
{
|
||||
int devno = printer_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
}
|
||||
|
||||
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
@@ -56,14 +84,12 @@ static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_printer *printer_class = usb_malloc(sizeof(struct usbh_printer));
|
||||
struct usbh_printer *printer_class = usbh_printer_class_alloc();
|
||||
if (printer_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc printer_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
|
||||
printer_class->hport = hport;
|
||||
printer_class->intf = intf;
|
||||
|
||||
@@ -107,8 +133,7 @@ static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
usb_free(printer_class);
|
||||
usbh_printer_class_free(printer_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -12,6 +12,7 @@ struct usbh_printer {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
};
|
||||
|
||||
@@ -3,43 +3,47 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/xxx"
|
||||
|
||||
static struct usbh_xxx g_xxx_class[CONFIG_USBHOST_MAX_CUSTOM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_xxx *usbh_xxx_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
|
||||
g_xxx_class[devno].minor = devno;
|
||||
return &g_xxx_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
int devno = xxx_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(xxx_class, 0, sizeof(struct usbh_xxx));
|
||||
}
|
||||
|
||||
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_xxx *xxx_class = usb_malloc(sizeof(struct usbh_xxx));
|
||||
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
|
||||
if (xxx_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(xxx_class, 0, sizeof(struct usbh_xxx));
|
||||
|
||||
xxx_class->hport = hport;
|
||||
xxx_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = xxx_class;
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
|
||||
|
||||
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
|
||||
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||
ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
|
||||
ep_cfg.ep_interval = ep_desc->bInterval;
|
||||
ep_cfg.hport = hport;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
|
||||
} else {
|
||||
usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +62,24 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_pipe_free(xxx_class->bulkout);
|
||||
}
|
||||
|
||||
usb_free(xxx_class);
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_xxx_stop(xxx_class);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
hport->config.intf[intf].priv = NULL;
|
||||
usbh_xxx_class_free(xxx_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_xxx_run(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_xxx_stop(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver xxx_class_driver = {
|
||||
.driver_name = "xxx",
|
||||
|
||||
@@ -7,8 +7,9 @@ struct usbh_xxx {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t intin; /* INTR IN endpoint */
|
||||
usbh_pipe_t intout; /* INTR OUT endpoint */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* bulk OUT endpoint */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,8 @@ struct usbh_cdc_custom_air724 {
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_air724_buf[32];
|
||||
|
||||
static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
@@ -30,12 +32,26 @@ static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *c
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int usbh_air724_bulk_in_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_custom_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
/* interface 3 is AT command */
|
||||
if (intf != 3) {
|
||||
USB_LOG_WRN("ignore intf:%d\r\n", intf);
|
||||
return 0;
|
||||
@@ -65,20 +81,22 @@ int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
uint8_t cdc_buffer[32] = { 0x41, 0x54, 0x0d, 0x0a };
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkout, cdc_buffer, 4, 3000);
|
||||
const uint8_t AT[4] = { 0x41, 0x54, 0x0d, 0x0a };
|
||||
|
||||
memcpy(g_air724_buf, AT, 4);
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class, g_air724_buf, 4, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", ret);
|
||||
}
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkin, cdc_buffer, 10, 3000);
|
||||
ret = usbh_air724_bulk_in_transfer(cdc_custom_class, g_air724_buf, 10, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||
for (size_t i = 0; i < ret; i++) {
|
||||
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||
USB_LOG_RAW("0x%02x ", g_air724_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
1763
class/vendor/cp201x/usbh_cp210x.c
vendored
Normal file
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
99
class/vendor/cp201x/usbh_cp210x.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#ifndef USBH_CP210X_H
|
||||
#define USBH_CP210X_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "usbh_core.h"
|
||||
|
||||
typedef int32_t speed_t;
|
||||
typedef int32_t tcflag_t;
|
||||
|
||||
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
|
||||
|
||||
struct usb_serial_port{
|
||||
uint8_t partnum;
|
||||
uint8_t ctrlpipe_rx;
|
||||
uint8_t ctrlpipe_tx;
|
||||
int32_t max_speed;
|
||||
speed_t use_actual_rate;
|
||||
uint8_t bInterfaceNumber;
|
||||
int has_swapped_line_ctl;
|
||||
};
|
||||
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
|
||||
#define NCCS 19
|
||||
struct termios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has identical termios and termios2 */
|
||||
|
||||
struct termios2 {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has matching termios and ktermios */
|
||||
|
||||
struct ktermios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
|
||||
struct tty_struct{
|
||||
struct usb_serial_port driver_data;
|
||||
struct termios termios;
|
||||
};
|
||||
|
||||
int cp210x_attach(struct usb_serial_port *port);
|
||||
int cp210x_port_probe(struct usb_serial_port *port);
|
||||
void cp210x_break_ctl(struct tty_struct *tty, int break_state);
|
||||
int cp210x_open(struct tty_struct *tty);
|
||||
int cp210x_tiocmget(struct tty_struct *tty);
|
||||
void cp210x_set_termios(struct tty_struct *tty);
|
||||
void cp210x_change_speed(struct tty_struct *tty);
|
||||
void cp210x_dtr_rts(struct usb_serial_port *port, int on);
|
||||
|
||||
struct usbh_cp210x
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf;
|
||||
usbh_pipe_t bulkin;
|
||||
usbh_pipe_t bulkout;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb bulkout_urb;
|
||||
|
||||
struct tty_struct drv_data;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
/* weak defined function */
|
||||
void drv_usbh_cp210x_run(struct usbh_cp210x *p_device);
|
||||
void drv_usbh_cp210x_stop(struct usbh_cp210x *p_device);
|
||||
|
||||
#endif
|
||||
@@ -12,17 +12,13 @@ struct video_entity_info {
|
||||
uint16_t wTerminalType;
|
||||
};
|
||||
|
||||
struct usbd_video_cfg_priv {
|
||||
struct usbd_video_priv {
|
||||
struct video_probe_and_commit_controls probe;
|
||||
struct video_probe_and_commit_controls commit;
|
||||
uint8_t power_mode;
|
||||
uint8_t error_code;
|
||||
struct video_entity_info info[3];
|
||||
} usbd_video_cfg = {
|
||||
.info[0] = { .bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x01, .wTerminalType = VIDEO_ITT_CAMERA },
|
||||
.info[1] = { .bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x03, .wTerminalType = 0x00 },
|
||||
.info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
|
||||
};
|
||||
} g_usbd_video;
|
||||
|
||||
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
@@ -70,7 +66,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
struct video_entity_info *entity_info = &usbd_video_cfg.info[i];
|
||||
struct video_entity_info *entity_info = &g_usbd_video.info[i];
|
||||
if (entity_info->bEntityId == entity_id) {
|
||||
switch (entity_info->bDescriptorSubtype) {
|
||||
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
|
||||
@@ -550,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usbd_video_cfg.error_code = 0x06;
|
||||
g_usbd_video.error_code = 0x06;
|
||||
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
|
||||
return -1;
|
||||
}
|
||||
@@ -576,10 +572,10 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_PROBE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_SET_CUR:
|
||||
//memcpy((uint8_t *)&usbd_video_cfg.probe, *data, setup->wLength);
|
||||
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.probe, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
|
||||
@@ -587,7 +583,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_REQUEST_GET_MAX:
|
||||
case VIDEO_REQUEST_GET_RES:
|
||||
case VIDEO_REQUEST_GET_DEF:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.probe, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_LEN:
|
||||
@@ -608,17 +604,17 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_COMMIT_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_SET_CUR:
|
||||
//memcpy((uint8_t *)&usbd_video_cfg.commit, *data, setup->wLength);
|
||||
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.commit, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_MIN:
|
||||
case VIDEO_REQUEST_GET_MAX:
|
||||
case VIDEO_REQUEST_GET_RES:
|
||||
case VIDEO_REQUEST_GET_DEF:
|
||||
memcpy(*data, (uint8_t *)&usbd_video_cfg.commit, setup->wLength);
|
||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
||||
*len = sizeof(struct video_probe_and_commit_controls);
|
||||
break;
|
||||
|
||||
@@ -640,7 +636,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
||||
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_GET_CUR:
|
||||
(*data)[0] = usbd_video_cfg.error_code;
|
||||
(*data)[0] = g_usbd_video.error_code;
|
||||
*len = 1;
|
||||
break;
|
||||
case VIDEO_REQUEST_GET_INFO:
|
||||
@@ -684,8 +680,8 @@ static void video_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
usbd_video_cfg.error_code = 0;
|
||||
usbd_video_cfg.power_mode = 0;
|
||||
g_usbd_video.error_code = 0;
|
||||
g_usbd_video.power_mode = 0;
|
||||
break;
|
||||
|
||||
case USBD_EVENT_SET_INTERFACE: {
|
||||
@@ -705,41 +701,41 @@ static void video_notify_handler(uint8_t event, void *arg)
|
||||
|
||||
void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
{
|
||||
usbd_video_cfg.probe.hintUnion.bmHint = 0x01;
|
||||
usbd_video_cfg.probe.hintUnion1.bmHint = 0;
|
||||
usbd_video_cfg.probe.bFormatIndex = 1;
|
||||
usbd_video_cfg.probe.bFrameIndex = 1;
|
||||
usbd_video_cfg.probe.dwFrameInterval = dwFrameInterval;
|
||||
usbd_video_cfg.probe.wKeyFrameRate = 0;
|
||||
usbd_video_cfg.probe.wPFrameRate = 0;
|
||||
usbd_video_cfg.probe.wCompQuality = 0;
|
||||
usbd_video_cfg.probe.wCompWindowSize = 0;
|
||||
usbd_video_cfg.probe.wDelay = 0;
|
||||
usbd_video_cfg.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
usbd_video_cfg.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
usbd_video_cfg.probe.dwClockFrequency = 0;
|
||||
usbd_video_cfg.probe.bmFramingInfo = 0;
|
||||
usbd_video_cfg.probe.bPreferedVersion = 0;
|
||||
usbd_video_cfg.probe.bMinVersion = 0;
|
||||
usbd_video_cfg.probe.bMaxVersion = 0;
|
||||
g_usbd_video.probe.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video.probe.hintUnion1.bmHint = 0;
|
||||
g_usbd_video.probe.bFormatIndex = 1;
|
||||
g_usbd_video.probe.bFrameIndex = 1;
|
||||
g_usbd_video.probe.dwFrameInterval = dwFrameInterval;
|
||||
g_usbd_video.probe.wKeyFrameRate = 0;
|
||||
g_usbd_video.probe.wPFrameRate = 0;
|
||||
g_usbd_video.probe.wCompQuality = 0;
|
||||
g_usbd_video.probe.wCompWindowSize = 0;
|
||||
g_usbd_video.probe.wDelay = 0;
|
||||
g_usbd_video.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
g_usbd_video.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
g_usbd_video.probe.dwClockFrequency = 0;
|
||||
g_usbd_video.probe.bmFramingInfo = 0;
|
||||
g_usbd_video.probe.bPreferedVersion = 0;
|
||||
g_usbd_video.probe.bMinVersion = 0;
|
||||
g_usbd_video.probe.bMaxVersion = 0;
|
||||
|
||||
usbd_video_cfg.commit.hintUnion.bmHint = 0x01;
|
||||
usbd_video_cfg.commit.hintUnion1.bmHint = 0;
|
||||
usbd_video_cfg.commit.bFormatIndex = 1;
|
||||
usbd_video_cfg.commit.bFrameIndex = 1;
|
||||
usbd_video_cfg.commit.dwFrameInterval = dwFrameInterval;
|
||||
usbd_video_cfg.commit.wKeyFrameRate = 0;
|
||||
usbd_video_cfg.commit.wPFrameRate = 0;
|
||||
usbd_video_cfg.commit.wCompQuality = 0;
|
||||
usbd_video_cfg.commit.wCompWindowSize = 0;
|
||||
usbd_video_cfg.commit.wDelay = 0;
|
||||
usbd_video_cfg.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
usbd_video_cfg.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
usbd_video_cfg.commit.dwClockFrequency = 0;
|
||||
usbd_video_cfg.commit.bmFramingInfo = 0;
|
||||
usbd_video_cfg.commit.bPreferedVersion = 0;
|
||||
usbd_video_cfg.commit.bMinVersion = 0;
|
||||
usbd_video_cfg.commit.bMaxVersion = 0;
|
||||
g_usbd_video.commit.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video.commit.hintUnion1.bmHint = 0;
|
||||
g_usbd_video.commit.bFormatIndex = 1;
|
||||
g_usbd_video.commit.bFrameIndex = 1;
|
||||
g_usbd_video.commit.dwFrameInterval = dwFrameInterval;
|
||||
g_usbd_video.commit.wKeyFrameRate = 0;
|
||||
g_usbd_video.commit.wPFrameRate = 0;
|
||||
g_usbd_video.commit.wCompQuality = 0;
|
||||
g_usbd_video.commit.wCompWindowSize = 0;
|
||||
g_usbd_video.commit.wDelay = 0;
|
||||
g_usbd_video.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||
g_usbd_video.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||
g_usbd_video.commit.dwClockFrequency = 0;
|
||||
g_usbd_video.commit.bmFramingInfo = 0;
|
||||
g_usbd_video.commit.bPreferedVersion = 0;
|
||||
g_usbd_video.commit.bMinVersion = 0;
|
||||
g_usbd_video.commit.bMaxVersion = 0;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
||||
@@ -752,6 +748,16 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = video_notify_handler;
|
||||
|
||||
g_usbd_video.info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[0].bEntityId = 0x01;
|
||||
g_usbd_video.info[0].wTerminalType = VIDEO_ITT_CAMERA;
|
||||
g_usbd_video.info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[1].bEntityId = 0x03;
|
||||
g_usbd_video.info[1].wTerminalType = 0x00;
|
||||
g_usbd_video.info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
|
||||
g_usbd_video.info[2].bEntityId = 0x02;
|
||||
g_usbd_video.info[2].wTerminalType = 0x00;
|
||||
|
||||
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
|
||||
return intf;
|
||||
}
|
||||
@@ -763,18 +769,18 @@ uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8
|
||||
uint32_t picture_pos = 0;
|
||||
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||
|
||||
packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
|
||||
last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
|
||||
packets = (input_len + (g_usbd_video.probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
||||
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2));
|
||||
|
||||
for (size_t i = 0; i < packets; i++) {
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
if (i == (packets - 1)) {
|
||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
|
||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
} else {
|
||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
|
||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += g_usbd_video.probe.dwMaxPayloadTransferSize - 2;
|
||||
}
|
||||
}
|
||||
uvc_header[1] ^= 1;
|
||||
|
||||
@@ -21,63 +21,77 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
|
||||
|
||||
static const char *format_type[] = { "uncompressed", "mjpeg" };
|
||||
|
||||
static int usbh_video_devno_alloc(struct usbh_video *video_class)
|
||||
static struct usbh_video g_video_class[CONFIG_USBHOST_MAX_VIDEO_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_video *usbh_video_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
video_class->minor = devno;
|
||||
return 0;
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
|
||||
g_video_class[devno].minor = devno;
|
||||
return &g_video_class[devno];
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_video_devno_free(struct usbh_video *video_class)
|
||||
static void usbh_video_class_free(struct usbh_video *video_class)
|
||||
{
|
||||
int devno = video_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
}
|
||||
|
||||
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
int ret;
|
||||
uint8_t retry;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = VIDEO_REQUEST_GET_CUR;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
setup->wIndex = (entity_id << 8) | intf;
|
||||
setup->wLength = len;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
retry = 0;
|
||||
while (1) {
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
if (ret > 0) {
|
||||
break;
|
||||
}
|
||||
retry++;
|
||||
|
||||
if (retry == 3) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
memcpy(buf, g_video_buf, len);
|
||||
|
||||
if (buf) {
|
||||
memcpy(buf, g_video_buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = VIDEO_REQUEST_SET_CUR;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
setup->wIndex = (entity_id << 8) | intf;
|
||||
setup->wLength = len;
|
||||
@@ -85,13 +99,13 @@ int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t ent
|
||||
memcpy(g_video_buf, buf, len);
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
usb_osal_msleep(5);
|
||||
usb_osal_msleep(50);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
|
||||
{
|
||||
return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
@@ -99,7 +113,8 @@ int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t fo
|
||||
video_class->probe.bFormatIndex = formatindex;
|
||||
video_class->probe.bFrameIndex = frameindex;
|
||||
video_class->probe.dwMaxPayloadTransferSize = 0;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
video_class->probe.dwFrameInterval = 333333;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
@@ -107,7 +122,8 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
|
||||
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
|
||||
video_class->commit.bFormatIndex = formatindex;
|
||||
video_class->commit.bFrameIndex = frameindex;
|
||||
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
video_class->commit.dwFrameInterval = 333333;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
}
|
||||
|
||||
int usbh_video_open(struct usbh_video *video_class,
|
||||
@@ -124,6 +140,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
bool found = false;
|
||||
uint8_t formatidx = 0;
|
||||
uint8_t frameidx = 0;
|
||||
uint8_t step;
|
||||
|
||||
if (video_class->is_opened) {
|
||||
return -EMFILE;
|
||||
@@ -151,31 +168,65 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Open video step:
|
||||
* Get CUR request (probe)
|
||||
* Set CUR request (probe)
|
||||
* Get CUR request (probe)
|
||||
* Get MAX request (probe)
|
||||
* Get MIN request (probe)
|
||||
* Get CUR request (probe)
|
||||
* Set CUR request (commit)
|
||||
*
|
||||
*/
|
||||
step = 0;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 1;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 2;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 3;
|
||||
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MAX, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 4;
|
||||
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MIN, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 5;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 6;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 7;
|
||||
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
step = 8;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
@@ -184,7 +235,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
@@ -202,6 +253,10 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
video_class->is_opened = true;
|
||||
video_class->current_format = format_type;
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
USB_LOG_ERR("Fail to open video in step %u\r\n", step);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_video_close(struct usbh_video *video_class)
|
||||
@@ -292,14 +347,12 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
uint8_t num_of_frames = 0xff;
|
||||
uint8_t *p;
|
||||
|
||||
struct usbh_video *video_class = usb_malloc(sizeof(struct usbh_video));
|
||||
struct usbh_video *video_class = usbh_video_class_alloc();
|
||||
if (video_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc video_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
usbh_video_devno_alloc(video_class);
|
||||
video_class->hport = hport;
|
||||
video_class->ctrl_intf = intf;
|
||||
video_class->data_intf = intf + 1;
|
||||
@@ -401,8 +454,6 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
|
||||
|
||||
if (video_class) {
|
||||
usbh_video_devno_free(video_class);
|
||||
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
}
|
||||
@@ -416,8 +467,7 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_video_stop(video_class);
|
||||
}
|
||||
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
usb_free(video_class);
|
||||
usbh_video_class_free(video_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -433,132 +483,6 @@ static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t i
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stream->bufoffset == 0) && ((iso_packet[i].transfer_buffer[header_len] != 0xff) || (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8))) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) || (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
/** do something here */
|
||||
}
|
||||
|
||||
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
|
||||
{
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint8_t data_offset;
|
||||
uint32_t data_len;
|
||||
uint8_t header_len = 0;
|
||||
|
||||
num_of_iso_packets = urb->num_of_iso_packets;
|
||||
iso_packet = urb->iso_packet;
|
||||
|
||||
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
|
||||
/*
|
||||
uint8_t frameIdentifier : 1U;
|
||||
uint8_t endOfFrame : 1U;
|
||||
uint8_t presentationTimeStamp : 1U;
|
||||
uint8_t sourceClockReference : 1U;
|
||||
uint8_t reserved : 1U;
|
||||
uint8_t stillImage : 1U;
|
||||
uint8_t errorBit : 1U;
|
||||
uint8_t endOfHeader : 1U;
|
||||
*/
|
||||
|
||||
if (iso_packet[i].actual_length == 0) { /* skip no data */
|
||||
continue;
|
||||
}
|
||||
|
||||
header_len = iso_packet[i].transfer_buffer[0];
|
||||
|
||||
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
|
||||
stream->bufoffset = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
data_offset = header_len;
|
||||
data_len = iso_packet[i].actual_length - header_len;
|
||||
|
||||
/** do something here */
|
||||
|
||||
stream->bufoffset += data_len;
|
||||
|
||||
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
|
||||
/** do something here */
|
||||
|
||||
if (stream->video_one_frame_callback && (stream->bufoffset == stream->buflen)) {
|
||||
stream->video_one_frame_callback(stream);
|
||||
}
|
||||
stream->bufoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** do something here */
|
||||
}
|
||||
#endif
|
||||
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
@@ -567,10 +491,6 @@ __WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
.driver_name = "video_ctrl",
|
||||
.connect = usbh_video_ctrl_connect,
|
||||
|
||||
@@ -25,6 +25,8 @@ struct usbh_video_format {
|
||||
struct usbh_videostreaming {
|
||||
uint32_t bufoffset;
|
||||
uint32_t buflen;
|
||||
uint16_t width;
|
||||
uint16_t heigth;
|
||||
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
|
||||
};
|
||||
|
||||
@@ -52,14 +54,8 @@ struct usbh_video {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_video_inityuyv2rgb_table(void);
|
||||
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len);
|
||||
|
||||
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
|
||||
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
|
||||
int usbh_video_get_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);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ static struct usbd_endpoint rndis_ep_data[3];
|
||||
#endif
|
||||
|
||||
/* Device data structure */
|
||||
struct usbd_rndis_cfg_priv {
|
||||
struct usbd_rndis_priv {
|
||||
uint32_t drv_version;
|
||||
uint32_t link_status;
|
||||
uint32_t speed;
|
||||
@@ -38,11 +38,12 @@ struct usbd_rndis_cfg_priv {
|
||||
usb_eth_stat_t eth_state;
|
||||
rndis_state_t init_state;
|
||||
uint8_t mac[6];
|
||||
} usbd_rndis_cfg = { .drv_version = 0x0001,
|
||||
.link_status = NDIS_MEDIA_STATE_DISCONNECTED,
|
||||
.speed = RNDIS_LINK_SPEED,
|
||||
.init_state = rndis_uninitialized,
|
||||
.mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
|
||||
} g_usbd_rndis;
|
||||
|
||||
#if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
|
||||
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
@@ -174,7 +175,7 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp->AfListOffset = 0;
|
||||
resp->AfListSize = 0;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_initialized;
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
return 0;
|
||||
@@ -187,7 +188,7 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageLength = 0;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_uninitialized;
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -241,7 +242,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
break;
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
|
||||
RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
|
||||
infomation_len = 6;
|
||||
break;
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
@@ -253,7 +254,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
@@ -261,7 +262,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
@@ -301,19 +302,19 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
@@ -354,7 +355,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
param->ParameterValueOffset, param->ParameterValueLength);
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
|
||||
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
|
||||
USB_LOG_WRN("PACKET_FILTER!\r\n");
|
||||
resp->Status = RNDIS_STATUS_INVALID_DATA;
|
||||
} else {
|
||||
@@ -362,12 +363,12 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
/* Parameter starts at offset buf_offset of the req_id field */
|
||||
filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
|
||||
|
||||
//usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
|
||||
usbd_rndis_cfg.net_filter = *(uint32_t *)filter;
|
||||
if (usbd_rndis_cfg.net_filter) {
|
||||
usbd_rndis_cfg.init_state = rndis_data_initialized;
|
||||
//g_usbd_rndis.net_filter = param->ParameterNameOffset;
|
||||
g_usbd_rndis.net_filter = *(uint32_t *)filter;
|
||||
if (g_usbd_rndis.net_filter) {
|
||||
g_usbd_rndis.init_state = rndis_data_initialized;
|
||||
} else {
|
||||
usbd_rndis_cfg.init_state = rndis_initialized;
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -393,7 +394,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
|
||||
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
rndis_reset_cmplt_t *resp;
|
||||
|
||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
@@ -402,7 +403,7 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
resp->AddressingReset = 1;
|
||||
|
||||
usbd_rndis_cfg.init_state = rndis_uninitialized;
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
@@ -429,12 +430,12 @@ static void rndis_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
g_rndis_rx_data_length = 0;
|
||||
g_rndis_tx_data_length = 0;
|
||||
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
break;
|
||||
|
||||
@@ -458,7 +459,7 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
|
||||
g_rndis_rx_data_length = hdr->DataLength;
|
||||
|
||||
usbd_rndis_data_recv((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
|
||||
usbd_rndis_data_recv_done();
|
||||
}
|
||||
|
||||
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
@@ -506,7 +507,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -543,7 +544,11 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep, uint8_t mac[6])
|
||||
{
|
||||
memcpy(usbd_rndis_cfg.mac, mac, 6);
|
||||
memcpy(g_usbd_rndis.mac, mac, 6);
|
||||
|
||||
g_usbd_rndis.drv_version = 0x0001;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
|
||||
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
|
||||
|
||||
@@ -18,6 +18,8 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep, uint8_t mac[6]);
|
||||
|
||||
void usbd_rndis_data_recv_done(void);
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
struct pbuf *usbd_rndis_eth_rx(void);
|
||||
int usbd_rndis_eth_tx(struct pbuf *p);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,7 +13,7 @@ struct usbh_rndis {
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Notify endpoint */
|
||||
|
||||
@@ -484,13 +484,10 @@ struct usb_msosv1_comp_id_function_descriptor {
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor {
|
||||
uint8_t *string;
|
||||
uint8_t string_len;
|
||||
const uint8_t *string;
|
||||
uint8_t vendor_code;
|
||||
uint8_t *compat_id;
|
||||
uint16_t compat_id_len;
|
||||
uint8_t *comp_id_property;
|
||||
uint16_t comp_id_property_len;
|
||||
const uint8_t *compat_id;
|
||||
const uint8_t **comp_id_property;
|
||||
};
|
||||
|
||||
/* MS OS 2.0 Header descriptor */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2022-2023, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -44,9 +44,9 @@
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||
#ifndef __USED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __USED __attribute__((used))
|
||||
#else
|
||||
#define __USED __root
|
||||
@@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __WEAK
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __WEAK __attribute__((weak))
|
||||
#else
|
||||
#define __WEAK _Pragma("__weak")
|
||||
@@ -62,7 +62,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -71,7 +71,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_STRUCT
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -80,7 +80,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_UNION
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
@@ -89,7 +89,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGNED
|
||||
#if __ICCARM_V8
|
||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#elif (__VER__ >= 7080000)
|
||||
/* Needs IAR language extensions */
|
||||
|
||||
458
core/usbd_core.c
458
core/usbd_core.c
@@ -6,9 +6,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
|
||||
#include "usb_osal.h"
|
||||
#endif
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
@@ -32,7 +29,7 @@ struct usbd_tx_rx_msg {
|
||||
usbd_endpoint_callback cb;
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
|
||||
/** Setup packet */
|
||||
USB_MEM_ALIGNX struct usb_setup_packet setup;
|
||||
/** Pointer to data buffer */
|
||||
@@ -45,41 +42,28 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
|
||||
bool zlp_flag;
|
||||
/** Pointer to registered descriptors */
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
struct usb_descriptor *descriptors;
|
||||
const struct usb_descriptor *descriptors;
|
||||
#else
|
||||
const uint8_t *descriptors;
|
||||
#endif
|
||||
struct usb_msosv1_descriptor *msosv1_desc;
|
||||
struct usb_msosv2_descriptor *msosv2_desc;
|
||||
struct usb_bos_descriptor *bos_desc;
|
||||
/* Buffer used for storing standard, class and vendor request data */
|
||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||
|
||||
/** Variable to check whether the usb has been configured */
|
||||
bool configured;
|
||||
/** Currently selected configuration */
|
||||
uint8_t configuration;
|
||||
uint8_t speed;
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
bool test_mode;
|
||||
#endif
|
||||
struct usbd_interface *intf[8];
|
||||
uint8_t intf_offset;
|
||||
} usbd_core_cfg;
|
||||
|
||||
usb_slist_t usbd_intf_head = USB_SLIST_OBJECT_INIT(usbd_intf_head);
|
||||
|
||||
static struct usb_msosv1_descriptor *msosv1_desc;
|
||||
static struct usb_msosv2_descriptor *msosv2_desc;
|
||||
static struct usb_bos_descriptor *bos_desc;
|
||||
|
||||
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
|
||||
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
|
||||
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD)
|
||||
usb_osal_mq_t usbd_tx_mq;
|
||||
usb_osal_thread_t usbd_tx_thread;
|
||||
#endif
|
||||
#if defined(CONFIG_USBDEV_RX_THREAD)
|
||||
usb_osal_mq_t usbd_rx_mq;
|
||||
usb_osal_thread_t usbd_rx_thread;
|
||||
#endif
|
||||
struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM];
|
||||
struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM];
|
||||
} g_usbd_core;
|
||||
|
||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg);
|
||||
|
||||
@@ -96,7 +80,7 @@ static void usbd_print_setup(struct usb_setup_packet *setup)
|
||||
|
||||
static bool is_device_configured(void)
|
||||
{
|
||||
return (usbd_core_cfg.configuration != 0);
|
||||
return (g_usbd_core.configuration != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,24 +155,24 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
|
||||
switch (type) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_descriptor[0];
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_descriptor[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
usbd_core_cfg.speed = usbd_get_port_speed(0);
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->hs_config_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
g_usbd_core.speed = usbd_get_port_speed(0);
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->hs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->fs_config_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
if (g_usbd_core.descriptors->fs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
@@ -203,20 +187,20 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
(*data)[3] = 0x04;
|
||||
*len = 4;
|
||||
} else if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
if (g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n");
|
||||
*data = usbd_core_cfg.descriptors->msosv1_descriptor->string;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->string_len;
|
||||
*data = g_usbd_core.descriptors->msosv1_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->msosv1_descriptor->string_len;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)usbd_core_cfg.descriptors->string_descriptor[index - 1]);
|
||||
if (g_usbd_core.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)g_usbd_core.descriptors->string_descriptor[index - 1]);
|
||||
|
||||
(*data)[0] = str_len * 2 + 2;
|
||||
(*data)[1] = 0x03;
|
||||
for (uint16_t i = 0; i < str_len; i++) {
|
||||
(*data)[i * 2 + 2] = usbd_core_cfg.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 2] = g_usbd_core.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 3] = 0;
|
||||
}
|
||||
|
||||
@@ -227,28 +211,28 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
}
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
if (usbd_core_cfg.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->device_quality_descriptor;
|
||||
*len = usbd_core_cfg.descriptors->device_quality_descriptor[0];
|
||||
if (g_usbd_core.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_quality_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_quality_descriptor[0];
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
if (usbd_core_cfg.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->fs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (usbd_core_cfg.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->hs_other_speed_descriptor;
|
||||
*len = (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
if (g_usbd_core.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
@@ -285,25 +269,25 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
|
||||
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
|
||||
|
||||
if (!msosv1_desc) {
|
||||
if (!g_usbd_core.msosv1_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//*data = (uint8_t *)msosv1_desc->string;
|
||||
memcpy(*data, (uint8_t *)msosv1_desc->string, msosv1_desc->string_len);
|
||||
*len = msosv1_desc->string_len;
|
||||
//*data = (uint8_t *)g_usbd_core.msosv1_desc->string;
|
||||
memcpy(*data, (uint8_t *)g_usbd_core.msosv1_desc->string, g_usbd_core.msosv1_desc->string[0]);
|
||||
*len = g_usbd_core.msosv1_desc->string[0];
|
||||
|
||||
return true;
|
||||
} else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) {
|
||||
USB_LOG_INFO("read BOS descriptor string\r\n");
|
||||
|
||||
if (!bos_desc) {
|
||||
if (!g_usbd_core.bos_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//*data = bos_desc->string;
|
||||
memcpy(*data, (uint8_t *)bos_desc->string, bos_desc->string_len);
|
||||
*len = bos_desc->string_len;
|
||||
//*data = g_usbd_core.bos_desc->string;
|
||||
memcpy(*data, (uint8_t *)g_usbd_core.bos_desc->string, g_usbd_core.bos_desc->string_len);
|
||||
*len = g_usbd_core.bos_desc->string_len;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
@@ -319,7 +303,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
return false;
|
||||
}
|
||||
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
|
||||
cur_index = 0U;
|
||||
|
||||
@@ -351,7 +335,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
memcpy(*data, p, *len);
|
||||
} else {
|
||||
/* nothing found */
|
||||
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
|
||||
USB_LOG_ERR("descriptor <type:0x%02x,index:0x%02x> not found!\r\n", type, index);
|
||||
}
|
||||
|
||||
return found;
|
||||
@@ -377,13 +361,13 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
bool found = false;
|
||||
uint8_t *p;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
/* configure endpoints for this configuration/altsetting */
|
||||
while (p[DESC_bLength] != 0U) {
|
||||
@@ -441,13 +425,13 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
bool ret = false;
|
||||
uint8_t *p;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor;
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor;
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
#else
|
||||
p = (uint8_t *)usbd_core_cfg.descriptors;
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting);
|
||||
|
||||
@@ -526,7 +510,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
}
|
||||
} else if (value == USB_FEATURE_TEST_MODE) {
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
usbd_core_cfg.test_mode = true;
|
||||
g_usbd_core.test_mode = true;
|
||||
usbd_execute_test_mode(setup);
|
||||
#endif
|
||||
}
|
||||
@@ -547,7 +531,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_CONFIGURATION:
|
||||
*data = (uint8_t *)&usbd_core_cfg.configuration;
|
||||
*data = (uint8_t *)&g_usbd_core.configuration;
|
||||
*len = 1;
|
||||
break;
|
||||
|
||||
@@ -557,8 +541,7 @@ static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t
|
||||
if (!usbd_set_configuration(value, 0)) {
|
||||
ret = false;
|
||||
} else {
|
||||
usbd_core_cfg.configuration = value;
|
||||
usbd_core_cfg.configured = true;
|
||||
g_usbd_core.configuration = value;
|
||||
usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
|
||||
usbd_event_handler(USBD_EVENT_CONFIGURED);
|
||||
}
|
||||
@@ -609,13 +592,11 @@ static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
|
||||
USB_LOG_INFO("read hid report descriptor\r\n");
|
||||
usb_slist_t *i;
|
||||
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->intf_num == intf_num) {
|
||||
if (intf && (intf->intf_num == intf_num)) {
|
||||
//*data = (uint8_t *)intf->hid_report_descriptor;
|
||||
memcpy(*data, intf->hid_report_descriptor, intf->hid_report_descriptor_len);
|
||||
*len = intf->hid_report_descriptor_len;
|
||||
@@ -761,22 +742,19 @@ static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t
|
||||
*/
|
||||
static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
|
||||
if (intf && intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
|
||||
return intf->class_interface_handler(setup, data, len);
|
||||
}
|
||||
}
|
||||
} else if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (intf->class_endpoint_handler) {
|
||||
if (intf && intf->class_endpoint_handler) {
|
||||
return intf->class_endpoint_handler(setup, data, len);
|
||||
}
|
||||
}
|
||||
@@ -797,45 +775,56 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **
|
||||
*/
|
||||
static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t desclen;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (usbd_core_cfg.descriptors->msosv1_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv1_descriptor->vendor_code) {
|
||||
if (g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->msosv1_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->compat_id_len;
|
||||
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
|
||||
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->compat_id;
|
||||
*len = desclen;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property;
|
||||
*len = usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property_len;
|
||||
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (usbd_core_cfg.descriptors->msosv2_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->msosv2_descriptor->vendor_code) {
|
||||
} else if (g_usbd_core.descriptors->msosv2_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->msosv2_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->msosv2_descriptor->compat_id;
|
||||
*len = usbd_core_cfg.descriptors->msosv2_descriptor->compat_id_len;
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv2_descriptor->compat_id;
|
||||
*len = g_usbd_core.descriptors->msosv2_descriptor->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (usbd_core_cfg.descriptors->webusb_url_descriptor) {
|
||||
if (setup->bRequest == usbd_core_cfg.descriptors->webusb_url_descriptor->vendor_code) {
|
||||
} else if (g_usbd_core.descriptors->webusb_url_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core.descriptors->webusb_url_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET Webusb url Descriptor\r\n");
|
||||
*data = (uint8_t *)usbd_core_cfg.descriptors->webusb_url_descriptor->string;
|
||||
*len = usbd_core_cfg.descriptors->webusb_url_descriptor->string_len;
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->webusb_url_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->webusb_url_descriptor->string_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
@@ -844,36 +833,42 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (msosv1_desc) {
|
||||
if (setup->bRequest == msosv1_desc->vendor_code) {
|
||||
if (g_usbd_core.msosv1_desc) {
|
||||
if (setup->bRequest == g_usbd_core.msosv1_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
//*data = (uint8_t *)msosv1_desc->compat_id;
|
||||
memcpy(*data, msosv1_desc->compat_id, msosv1_desc->compat_id_len);
|
||||
*len = msosv1_desc->compat_id_len;
|
||||
|
||||
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
|
||||
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
|
||||
memcpy(*data, g_usbd_core.msosv1_desc->compat_id, desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
//*data = (uint8_t *)msosv1_desc->comp_id_property;
|
||||
memcpy(*data, msosv1_desc->comp_id_property, msosv1_desc->comp_id_property_len);
|
||||
*len = msosv1_desc->comp_id_property_len;
|
||||
|
||||
//*data = (uint8_t *)msosv1_desc->comp_id_property[setup->wValue];
|
||||
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
|
||||
memcpy(*data, g_usbd_core.msosv1_desc->comp_id_property[setup->wValue], desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (msosv2_desc) {
|
||||
if (setup->bRequest == msosv2_desc->vendor_code) {
|
||||
} else if (g_usbd_core.msosv2_desc) {
|
||||
if (setup->bRequest == g_usbd_core.msosv2_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
//*data = (uint8_t *)msosv2_desc->compat_id;
|
||||
memcpy(*data, msosv2_desc->compat_id, msosv2_desc->compat_id_len);
|
||||
*len = msosv2_desc->compat_id_len;
|
||||
memcpy(*data, g_usbd_core.msosv2_desc->compat_id, g_usbd_core.msosv2_desc->compat_id_len);
|
||||
*len = g_usbd_core.msosv2_desc->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
@@ -882,13 +877,10 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
}
|
||||
}
|
||||
#endif
|
||||
usb_slist_t *i;
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
|
||||
if (intf->vendor_handler && !intf->vendor_handler(setup, data, len)) {
|
||||
if (intf && intf->vendor_handler && (intf->vendor_handler(setup, data, len) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -910,11 +902,20 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
|
||||
case USB_REQUEST_STANDARD:
|
||||
if (usbd_standard_request_handler(setup, data, len) < 0) {
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (g_usbd_core.speed == USB_SPEED_FULL) {
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef CONFIG_USB_HS
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
USB_LOG_ERR("standard request error\r\n");
|
||||
usbd_print_setup(setup);
|
||||
@@ -945,18 +946,16 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
|
||||
static void usbd_class_event_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
usb_slist_for_each(i, &usbd_intf_head)
|
||||
{
|
||||
struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
|
||||
for (uint8_t i = 0; i < g_usbd_core.intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core.intf[i];
|
||||
|
||||
if (arg) {
|
||||
struct usb_interface_descriptor *desc = (struct usb_interface_descriptor *)arg;
|
||||
if (intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
|
||||
if (intf && intf->notify_handler && (desc->bInterfaceNumber == (intf->intf_num))) {
|
||||
intf->notify_handler(event, arg);
|
||||
}
|
||||
} else {
|
||||
if (intf->notify_handler) {
|
||||
if (intf && intf->notify_handler) {
|
||||
intf->notify_handler(event, arg);
|
||||
}
|
||||
}
|
||||
@@ -986,11 +985,10 @@ void usbd_event_suspend_handler(void)
|
||||
void usbd_event_reset_handler(void)
|
||||
{
|
||||
usbd_set_address(0);
|
||||
usbd_core_cfg.configured = 0;
|
||||
usbd_core_cfg.configuration = 0;
|
||||
g_usbd_core.configuration = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
usbd_core_cfg.test_mode = false;
|
||||
g_usbd_core.test_mode = false;
|
||||
#endif
|
||||
struct usbd_endpoint_cfg ep0_cfg;
|
||||
|
||||
@@ -1008,7 +1006,7 @@ void usbd_event_reset_handler(void)
|
||||
|
||||
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
memcpy(setup, psetup, 8);
|
||||
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
|
||||
@@ -1022,65 +1020,65 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
|
||||
}
|
||||
}
|
||||
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
usbd_core_cfg.ep0_data_buf_residue = setup->wLength;
|
||||
usbd_core_cfg.ep0_data_buf_len = setup->wLength;
|
||||
usbd_core_cfg.zlp_flag = false;
|
||||
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
|
||||
g_usbd_core.ep0_data_buf_residue = setup->wLength;
|
||||
g_usbd_core.ep0_data_buf_len = setup->wLength;
|
||||
g_usbd_core.zlp_flag = false;
|
||||
|
||||
/* handle class request when all the data is received */
|
||||
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, setup->wLength);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ask installed handler to process request */
|
||||
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
|
||||
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
|
||||
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
/* send status in test mode, so do not execute downward, just return */
|
||||
if (usbd_core_cfg.test_mode) {
|
||||
usbd_core_cfg.test_mode = false;
|
||||
if (g_usbd_core.test_mode) {
|
||||
g_usbd_core.test_mode = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* Send smallest of requested and offered length */
|
||||
usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, setup->wLength);
|
||||
if (usbd_core_cfg.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
|
||||
g_usbd_core.ep0_data_buf_residue = MIN(g_usbd_core.ep0_data_buf_len, setup->wLength);
|
||||
if (g_usbd_core.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
|
||||
USB_LOG_ERR("Request buffer too small\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send data or status to host */
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
/*
|
||||
* Set ZLP flag when host asks for a bigger length and the data size is
|
||||
* multiplier of USB_CTRL_EP_MPS, to indicate the transfer done after zlp
|
||||
* sent.
|
||||
*/
|
||||
if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
|
||||
usbd_core_cfg.zlp_flag = true;
|
||||
if ((setup->wLength > g_usbd_core.ep0_data_buf_len) && (!(g_usbd_core.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
|
||||
g_usbd_core.zlp_flag = true;
|
||||
USB_LOG_DBG("EP0 Set zlp\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
usbd_core_cfg.ep0_data_buf += nbytes;
|
||||
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
|
||||
g_usbd_core.ep0_data_buf += nbytes;
|
||||
g_usbd_core.ep0_data_buf_residue -= nbytes;
|
||||
|
||||
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
|
||||
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
|
||||
|
||||
if (usbd_core_cfg.ep0_data_buf_residue != 0) {
|
||||
if (g_usbd_core.ep0_data_buf_residue != 0) {
|
||||
/* Start sending the remain data */
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
} else {
|
||||
if (usbd_core_cfg.zlp_flag == true) {
|
||||
usbd_core_cfg.zlp_flag = false;
|
||||
if (g_usbd_core.zlp_flag == true) {
|
||||
g_usbd_core.zlp_flag = false;
|
||||
/* Send zlp to host */
|
||||
USB_LOG_DBG("EP0 Send zlp\r\n");
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
|
||||
@@ -1100,18 +1098,18 @@ void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
struct usb_setup_packet *setup = &g_usbd_core.setup;
|
||||
|
||||
if (nbytes > 0) {
|
||||
usbd_core_cfg.ep0_data_buf += nbytes;
|
||||
usbd_core_cfg.ep0_data_buf_residue -= nbytes;
|
||||
g_usbd_core.ep0_data_buf += nbytes;
|
||||
g_usbd_core.ep0_data_buf_residue -= nbytes;
|
||||
|
||||
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
|
||||
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core.ep0_data_buf_residue);
|
||||
|
||||
if (usbd_core_cfg.ep0_data_buf_residue == 0) {
|
||||
if (g_usbd_core.ep0_data_buf_residue == 0) {
|
||||
/* Received all, send data to handler */
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
|
||||
g_usbd_core.ep0_data_buf = g_usbd_core.req_data;
|
||||
if (!usbd_setup_request_handler(setup, &g_usbd_core.ep0_data_buf, &g_usbd_core.ep0_data_buf_len)) {
|
||||
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
|
||||
return;
|
||||
}
|
||||
@@ -1120,7 +1118,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
|
||||
} else {
|
||||
/* Start reading the remain data */
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
|
||||
usbd_ep_start_read(USB_CONTROL_OUT_EP0, g_usbd_core.ep0_data_buf, g_usbd_core.ep0_data_buf_residue);
|
||||
}
|
||||
} else {
|
||||
/* Read out status completely, do nothing */
|
||||
@@ -1130,166 +1128,95 @@ void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_TX_THREAD
|
||||
if (tx_msg[ep & 0x7f].cb) {
|
||||
tx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
if (g_usbd_core.tx_msg[ep & 0x7f].cb) {
|
||||
g_usbd_core.tx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
tx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_tx_mq, (uintptr_t)&tx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
#ifndef CONFIG_USBDEV_RX_THREAD
|
||||
if (rx_msg[ep & 0x7f].cb) {
|
||||
rx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
#else
|
||||
rx_msg[ep & 0x7f].nbytes = nbytes;
|
||||
usb_osal_mq_send(usbd_rx_mq, (uintptr_t)&rx_msg[ep & 0x7f]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_TX_THREAD
|
||||
static void usbdev_tx_thread(void *argument)
|
||||
{
|
||||
struct usbd_tx_rx_msg *msg;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usbd_tx_mq, (uintptr_t *)&msg, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg->cb) {
|
||||
msg->cb(msg->ep, msg->nbytes);
|
||||
}
|
||||
if (g_usbd_core.rx_msg[ep & 0x7f].cb) {
|
||||
g_usbd_core.rx_msg[ep & 0x7f].cb(ep, nbytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_RX_THREAD
|
||||
static void usbdev_rx_thread(void *argument)
|
||||
{
|
||||
struct usbd_tx_rx_msg *msg;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usbd_rx_mq, (uintptr_t *)&msg, 0xffffffff);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg->cb) {
|
||||
msg->cb(msg->ep, msg->nbytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
void usbd_desc_register(struct usb_descriptor *desc)
|
||||
{
|
||||
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
|
||||
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
|
||||
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
g_usbd_core.descriptors = desc;
|
||||
g_usbd_core.intf_offset = 0;
|
||||
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
g_usbd_core.tx_msg[0].ep = 0x80;
|
||||
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
g_usbd_core.rx_msg[0].ep = 0x00;
|
||||
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc)
|
||||
{
|
||||
memset(&usbd_core_cfg, 0, sizeof(struct usbd_core_cfg_priv));
|
||||
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
|
||||
|
||||
usbd_core_cfg.descriptors = desc;
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
g_usbd_core.descriptors = desc;
|
||||
g_usbd_core.intf_offset = 0;
|
||||
|
||||
tx_msg[0].ep = 0x80;
|
||||
tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
rx_msg[0].ep = 0x00;
|
||||
rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
g_usbd_core.tx_msg[0].ep = 0x80;
|
||||
g_usbd_core.tx_msg[0].cb = usbd_event_ep0_in_complete_handler;
|
||||
g_usbd_core.rx_msg[0].ep = 0x00;
|
||||
g_usbd_core.rx_msg[0].cb = usbd_event_ep0_out_complete_handler;
|
||||
}
|
||||
|
||||
/* Register MS OS Descriptors version 1 */
|
||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc)
|
||||
{
|
||||
msosv1_desc = desc;
|
||||
g_usbd_core.msosv1_desc = desc;
|
||||
}
|
||||
|
||||
/* Register MS OS Descriptors version 2 */
|
||||
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc)
|
||||
{
|
||||
msosv2_desc = desc;
|
||||
g_usbd_core.msosv2_desc = desc;
|
||||
}
|
||||
|
||||
void usbd_bos_desc_register(struct usb_bos_descriptor *desc)
|
||||
{
|
||||
bos_desc = desc;
|
||||
g_usbd_core.bos_desc = desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(struct usbd_interface *intf)
|
||||
{
|
||||
intf->intf_num = usbd_core_cfg.intf_offset;
|
||||
usb_slist_add_tail(&usbd_intf_head, &intf->list);
|
||||
usbd_core_cfg.intf_offset++;
|
||||
intf->intf_num = g_usbd_core.intf_offset;
|
||||
g_usbd_core.intf[g_usbd_core.intf_offset] = intf;
|
||||
g_usbd_core.intf_offset++;
|
||||
}
|
||||
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep)
|
||||
{
|
||||
if (ep->ep_addr & 0x80) {
|
||||
tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
g_usbd_core.tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
} else {
|
||||
rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr;
|
||||
g_usbd_core.rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_device_is_configured(void)
|
||||
{
|
||||
return usbd_core_cfg.configured;
|
||||
return g_usbd_core.configuration;
|
||||
}
|
||||
|
||||
int usbd_initialize(void)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_TX_THREAD
|
||||
usbd_tx_mq = usb_osal_mq_create(16);
|
||||
if (usbd_tx_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
usbd_tx_thread = usb_osal_thread_create("usbd_tx", CONFIG_USBDEV_TX_STACKSIZE, CONFIG_USBDEV_TX_PRIO, usbdev_tx_thread, NULL);
|
||||
if (usbd_tx_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_USBDEV_RX_THREAD
|
||||
usbd_rx_mq = usb_osal_mq_create(16);
|
||||
if (usbd_rx_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
usbd_rx_thread = usb_osal_thread_create("usbd_rx", CONFIG_USBDEV_RX_STACKSIZE, CONFIG_USBDEV_RX_PRIO, usbdev_rx_thread, NULL);
|
||||
if (usbd_rx_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return usb_dc_init();
|
||||
}
|
||||
|
||||
int usbd_deinitialize(void)
|
||||
{
|
||||
usbd_core_cfg.intf_offset = 0;
|
||||
usb_slist_init(&usbd_intf_head);
|
||||
g_usbd_core.intf_offset = 0;
|
||||
usb_dc_deinit();
|
||||
#if defined(CONFIG_USBDEV_TX_THREAD) || defined(CONFIG_USBDEV_RX_THREAD)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1307,7 +1234,6 @@ __WEAK void usbd_event_handler(uint8_t event)
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
usbd_configure_done_callback();
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
@@ -46,15 +46,12 @@ typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **da
|
||||
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
|
||||
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
||||
|
||||
extern usb_slist_t usbd_intf_head;
|
||||
|
||||
struct usbd_endpoint {
|
||||
uint8_t ep_addr;
|
||||
usbd_endpoint_callback ep_cb;
|
||||
};
|
||||
|
||||
struct usbd_interface {
|
||||
usb_slist_t list;
|
||||
usbd_request_handler class_interface_handler;
|
||||
usbd_request_handler class_endpoint_handler;
|
||||
usbd_request_handler vendor_handler;
|
||||
@@ -91,7 +88,6 @@ void usbd_add_interface(struct usbd_interface *intf);
|
||||
void usbd_add_endpoint(struct usbd_endpoint *ep);
|
||||
|
||||
bool usb_device_is_configured(void);
|
||||
void usbd_configure_done_callback(void);
|
||||
int usbd_initialize(void);
|
||||
int usbd_deinitialize(void);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#define AUDIO_IN_EP 0x81
|
||||
#define AUDIO_OUT_EP 0x02
|
||||
|
||||
#define AUDIO_IN_FU_ID 0x02
|
||||
#define AUDIO_OUT_FU_ID 0x05
|
||||
|
||||
/* AUDIO Class Config */
|
||||
#define AUDIO_SPEAKER_FREQ 16000U
|
||||
#define AUDIO_SPEAKER_FRAME_SIZE_BYTE 2u
|
||||
@@ -49,7 +52,7 @@
|
||||
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v1_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
|
||||
@@ -59,9 +62,9 @@ const uint8_t audio_descriptor[] = {
|
||||
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
|
||||
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
|
||||
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,\
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
|
||||
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,\
|
||||
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
|
||||
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
@@ -137,24 +140,51 @@ const uint8_t audio_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
volatile bool rx_flag = 0;
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
printf("OPEN1\r\n");
|
||||
} else {
|
||||
tx_flag = 1;
|
||||
printf("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
@@ -166,16 +196,10 @@ void usbd_audio_close(uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -198,32 +222,36 @@ struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void audio_init()
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2));
|
||||
usbd_desc_register(audio_v1_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v1_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||
while (ep_tx_busy_flag) {
|
||||
if (tx_flag == false) {
|
||||
break;
|
||||
}
|
||||
if (tx_flag) {
|
||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||
while (ep_tx_busy_flag) {
|
||||
if (tx_flag == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#define AUDIO_IN_EP 0x81
|
||||
|
||||
#define AUDIO_IN_CLOCK_ID 0x01
|
||||
#define AUDIO_IN_FU_ID 0x03
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -50,7 +53,6 @@
|
||||
|
||||
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||
|
||||
|
||||
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
|
||||
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||
@@ -65,7 +67,7 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
|
||||
@@ -157,29 +159,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
tx_flag = 1;
|
||||
USB_LOG_RAW("OPEN\r\n");
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
USB_LOG_RAW("CLOSE\r\n");
|
||||
tx_flag = 0;
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_IN_EP) {
|
||||
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
}
|
||||
|
||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
}
|
||||
@@ -192,23 +215,27 @@ static struct usbd_endpoint audio_in_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_IN_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (tx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#define AUDIO_OUT_EP 0x02
|
||||
#define AUDIO_IN_EP 0x81
|
||||
|
||||
#define AUDIO_OUT_CLOCK_ID 0x01
|
||||
#define AUDIO_OUT_FU_ID 0x03
|
||||
#define AUDIO_IN_CLOCK_ID 0x05
|
||||
#define AUDIO_IN_FU_ID 0x07
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -49,36 +54,34 @@
|
||||
#define INPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
|
||||
#define OUT_CHANNEL_NUM 2
|
||||
|
||||
#if OUT_CHANNEL_NUM == 1
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000000
|
||||
#elif OUT_CHANNEL_NUM == 2
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000003
|
||||
#elif OUT_CHANNEL_NUM == 3
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000007
|
||||
#elif OUT_CHANNEL_NUM == 4
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||
#elif OUT_CHANNEL_NUM == 5
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||
#elif OUT_CHANNEL_NUM == 6
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||
#elif OUT_CHANNEL_NUM == 7
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||
#elif OUT_CHANNEL_NUM == 8
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
|
||||
/* AudioFreq * DataSize (2 bytes) * NumChannels */
|
||||
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
|
||||
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||
@@ -106,7 +109,7 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
uint8_t audio_descriptor[] = {
|
||||
uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
|
||||
@@ -220,23 +223,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
|
||||
AUDIO_SAMPLE_FREQ_4B(0x00)
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
volatile bool rx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
USB_LOG_RAW("OPEN1\r\n");
|
||||
} else {
|
||||
tx_flag = 1;
|
||||
USB_LOG_RAW("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
@@ -248,36 +278,34 @@ void usbd_audio_close(uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
|
||||
} else if (entity_id == 0x05) {
|
||||
} else if (ep == AUDIO_IN_EP) {
|
||||
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
uint16_t packet_size = 0;
|
||||
if (entity_id == 1) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
|
||||
} else if (entity_id == 5) {
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
|
||||
} else if (ep == AUDIO_IN_EP) {
|
||||
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
|
||||
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
|
||||
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -298,27 +326,37 @@ struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void audio_init()
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_IN_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_IN_EP },
|
||||
{ .bEntityId = AUDIO_IN_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2));
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
|
||||
usbd_add_endpoint(&audio_in_ep);
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
usbd_audio_add_entity(0x05, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x07, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (tx_flag) {
|
||||
}
|
||||
if (rx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#define AUDIO_OUT_EP 0x01
|
||||
|
||||
#define AUDIO_OUT_CLOCK_ID 0x01
|
||||
#define AUDIO_OUT_FU_ID 0x03
|
||||
|
||||
#define AUDIO_FREQ 48000
|
||||
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||
#define SAMPLE_BITS 16 //16 bit per channel
|
||||
@@ -23,28 +26,28 @@
|
||||
#define OUT_CHANNEL_NUM 2
|
||||
|
||||
#if OUT_CHANNEL_NUM == 1
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000000
|
||||
#elif OUT_CHANNEL_NUM == 2
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000003
|
||||
#elif OUT_CHANNEL_NUM == 3
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x00000007
|
||||
#elif OUT_CHANNEL_NUM == 4
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||
#elif OUT_CHANNEL_NUM == 5
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||
#elif OUT_CHANNEL_NUM == 6
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||
#elif OUT_CHANNEL_NUM == 7
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||
#elif OUT_CHANNEL_NUM == 8
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||
#endif
|
||||
|
||||
@@ -64,13 +67,13 @@
|
||||
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||
|
||||
const uint8_t audio_descriptor[] = {
|
||||
const uint8_t audio_v2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
|
||||
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
|
||||
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
|
||||
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
|
||||
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
|
||||
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
|
||||
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
|
||||
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
|
||||
///////////////////////////////////////
|
||||
@@ -166,36 +169,60 @@ static const uint8_t default_sampling_freq_table[] = {
|
||||
AUDIO_SAMPLE_FREQ_4B(0x00),
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
||||
|
||||
volatile bool rx_flag = 0;
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_open(uint8_t intf)
|
||||
{
|
||||
rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
USB_LOG_RAW("OPEN\r\n");
|
||||
}
|
||||
|
||||
void usbd_audio_close(uint8_t intf)
|
||||
{
|
||||
USB_LOG_RAW("CLOSE\r\n");
|
||||
rx_flag = 0;
|
||||
}
|
||||
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
|
||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
if (entity_id == 0x01) {
|
||||
if (ep == AUDIO_OUT_EP) {
|
||||
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||
}
|
||||
|
||||
static struct usbd_endpoint audio_out_ep = {
|
||||
@@ -206,23 +233,27 @@ static struct usbd_endpoint audio_out_ep = {
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void audio_init()
|
||||
{
|
||||
usbd_desc_register(audio_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1));
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
struct audio_entity_info audio_entity_table[] = {
|
||||
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
{ .bEntityId = AUDIO_OUT_FU_ID,
|
||||
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
|
||||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||
void audio_v2_init(void)
|
||||
{
|
||||
usbd_desc_register(audio_v2_descriptor);
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
||||
usbd_add_endpoint(&audio_out_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void audio_test()
|
||||
void audio_v2_test(void)
|
||||
{
|
||||
while (1) {
|
||||
if (rx_flag) {
|
||||
}
|
||||
if (rx_flag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,23 @@
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN + 25)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t cdc_acm_hid_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
@@ -136,35 +148,6 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!< hid mouse report descriptor */
|
||||
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
@@ -255,10 +238,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
@@ -360,3 +364,32 @@ void cdc_acm_data_send_with_dtr_test(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,24 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -109,10 +121,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
@@ -26,14 +26,20 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, CDC_MAX_MPS, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -119,13 +125,34 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
|
||||
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
@@ -14,11 +14,17 @@
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -104,10 +110,31 @@ volatile bool ep_tx_busy_flag = false;
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
|
||||
#define DAP_IN_EP 0x81
|
||||
#define DAP_OUT_EP 0x02
|
||||
|
||||
#define CDC_IN_EP 0x83
|
||||
#define CDC_OUT_EP 0x04
|
||||
#define CDC_INT_EP 0x85
|
||||
|
||||
#define USBD_VID 0xd6e7
|
||||
#define USBD_PID 0x3507
|
||||
#define USBD_MAX_POWER 500
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define CMSIS_DAP_INTERFACE_SIZE (9 + 7 + 7)
|
||||
#define USB_CONFIG_SIZE (9 + CMSIS_DAP_INTERFACE_SIZE + CDC_ACM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#define WCID_VENDOR_CODE 0x01
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
///////////////////////////////////////
|
||||
0x12, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
/* MSFT100 */
|
||||
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
|
||||
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
|
||||
WCID_VENDOR_CODE, /* bVendorCode */
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x28, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x01, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x00, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
|
||||
.string_len = 18,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
|
||||
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
|
||||
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
|
||||
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
|
||||
};
|
||||
|
||||
const uint8_t daplink_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
/* Configuration 0 */
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
|
||||
/* Endpoint IN 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x00),
|
||||
/* String 0 (LANGID) */
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
/* String 1 (Manufacturer) */
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
/* String 2 (Product) */
|
||||
0x28, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'C', 0x00, // wcChar0
|
||||
'h', 0x00, // wcChar1
|
||||
'e', 0x00, // wcChar2
|
||||
'r', 0x00, // wcChar3
|
||||
'r', 0x00, // wcChar4
|
||||
'y', 0x00, // wcChar5
|
||||
'U', 0x00, // wcChar6
|
||||
'S', 0x00, // wcChar7
|
||||
'B', 0x00, // wcChar8
|
||||
' ', 0x00, // wcChar9
|
||||
'C', 0x00, // wcChar10
|
||||
'M', 0x00, // wcChar11
|
||||
'S', 0x00, // wcChar12
|
||||
'I', 0x00, // wcChar13
|
||||
'S', 0x00, // wcChar14
|
||||
'-', 0x00, // wcChar15
|
||||
'D', 0x00, // wcChar16
|
||||
'A', 0x00, // wcChar17
|
||||
'P', 0x00, // wcChar18
|
||||
/* String 3 (Serial Number) */
|
||||
0x1A, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'0', 0, // wcChar0
|
||||
'1', 0, // wcChar1
|
||||
'2', 0, // wcChar2
|
||||
'3', 0, // wcChar3
|
||||
'4', 0, // wcChar4
|
||||
'5', 0, // wcChar5
|
||||
'A', 0, // wcChar6
|
||||
'B', 0, // wcChar7
|
||||
'C', 0, // wcChar8
|
||||
'D', 0, // wcChar9
|
||||
'E', 0, // wcChar10
|
||||
'F', 0, // wcChar11
|
||||
#ifdef CONFIG_USB_HS
|
||||
/* Device Qualifier */
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x10,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
/* End */
|
||||
0x00
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_read_buffer[CDC_MAX_MPS];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Request[DAP_PACKET_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Response[DAP_PACKET_SIZE];
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
|
||||
usbd_ep_start_read(DAP_OUT_EP, USB_Request, DAP_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
/* setup next out ep read transfer */
|
||||
if (1) {
|
||||
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_dap_recv_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
uint32_t actual_len;
|
||||
if (USB_Request[0] == ID_DAP_TransferAbort) {
|
||||
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
|
||||
DAP_TransferAbort = 1;
|
||||
return;
|
||||
}
|
||||
actual_len = DAP_ProcessCommand(USB_Request, USB_Response);
|
||||
|
||||
usbd_ep_start_write(DAP_IN_EP, USB_Response, actual_len & 0xffff);
|
||||
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void usb_dap_send_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(DAP_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_endpoint cdc_out_ep = {
|
||||
.ep_addr = CDC_OUT_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_out
|
||||
};
|
||||
|
||||
static struct usbd_endpoint cdc_in_ep = {
|
||||
.ep_addr = CDC_IN_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
};
|
||||
|
||||
static struct usbd_endpoint dap_out_ep = {
|
||||
.ep_addr = DAP_OUT_EP,
|
||||
.ep_cb = usb_dap_recv_callback
|
||||
};
|
||||
static struct usbd_endpoint dap_in_ep = {
|
||||
.ep_addr = DAP_IN_EP,
|
||||
.ep_cb = usb_dap_send_callback
|
||||
};
|
||||
|
||||
struct usbd_interface dap_interface;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void daplink_init(void)
|
||||
{
|
||||
usbd_desc_register(daplink_descriptor);
|
||||
usbd_msosv1_desc_register(&msosv1_desc);
|
||||
|
||||
/*!< winusb */
|
||||
usbd_add_interface(&dap_interface);
|
||||
usbd_add_endpoint(&dap_out_ep);
|
||||
usbd_add_endpoint(&dap_in_ep);
|
||||
|
||||
/*!< cdc acm */
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
|
||||
usbd_add_endpoint(&cdc_out_ep);
|
||||
usbd_add_endpoint(&cdc_in_ep);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
@@ -137,9 +137,29 @@ const uint8_t dfu_flash_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/*!< hidraw in endpoint */
|
||||
#define HIDRAW_IN_EP 0x81
|
||||
#define HIDRAW_IN_SIZE 64
|
||||
#define HIDRAW_IN_EP_SIZE 64
|
||||
#define HIDRAW_IN_INTERVAL 10
|
||||
|
||||
/*!< hidraw out endpoint */
|
||||
@@ -20,7 +20,7 @@
|
||||
#define USB_HID_CONFIG_DESC_SIZ (9 + 9 + 9 + 7 + 7)
|
||||
|
||||
/*!< custom hid report descriptor size */
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 34
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 38
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t hid_descriptor[] = {
|
||||
@@ -51,7 +51,7 @@ static const uint8_t hid_descriptor[] = {
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
WBVAL(HIDRAW_IN_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
WBVAL(HIDRAW_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||
/******************** Descriptor of Custom out endpoint ********************/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
@@ -61,13 +61,13 @@ static const uint8_t hid_descriptor[] = {
|
||||
WBVAL(HIDRAW_OUT_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 73 */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string0 descriptor
|
||||
*/
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string1 descriptor
|
||||
*/
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
@@ -79,9 +79,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string2 descriptor
|
||||
*/
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
@@ -102,9 +102,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* string3 descriptor
|
||||
*/
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
@@ -118,9 +118,9 @@ static const uint8_t hid_descriptor[] = {
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
* device qualifier descriptor
|
||||
*/
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
@@ -138,38 +138,62 @@ static const uint8_t hid_descriptor[] = {
|
||||
/*!< custom hid report descriptor */
|
||||
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||
/* USER CODE BEGIN 0 */
|
||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Defined Page 1) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0xa1, 0x01, /* COLLECTION (Application) */
|
||||
0x85, 0x02, /* REPORT ID (0x02) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */
|
||||
0x95, 0x40 - 1, /* REPORT_COUNT (63) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x81, 0x02, /* INPUT (Data,Var,Abs) */
|
||||
/* <___________________________________________________> */
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
0x85, 0x01, /* REPORT ID (0x01) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */
|
||||
0x95, 0x40 - 1, /* REPORT_COUNT (63) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
||||
/* USER CODE END 0 */
|
||||
0xC0 /* END_COLLECTION */
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[HIDRAW_OUT_EP_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t send_buffer[HIDRAW_IN_EP_SIZE];
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t custom_state = HID_STATE_IDLE;
|
||||
static volatile uint8_t custom_state;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_hid_custom_in_callback(uint8_t ep, uint32_t nbytes)
|
||||
@@ -182,6 +206,8 @@ static void usbd_hid_custom_out_callback(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
|
||||
read_buffer[0] = 0x02; /* IN: report id */
|
||||
usbd_ep_start_write(HIDRAW_IN_EP, read_buffer, nbytes);
|
||||
}
|
||||
|
||||
static struct usbd_endpoint custom_in_ep = {
|
||||
@@ -194,9 +220,16 @@ static struct usbd_endpoint custom_out_ep = {
|
||||
.ep_addr = HIDRAW_OUT_EP
|
||||
};
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief hid custom init
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_custom_keyboard_init(void)
|
||||
void hid_custom_init(void)
|
||||
{
|
||||
usbd_desc_register(hid_descriptor);
|
||||
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||
@@ -205,16 +238,3 @@ void hid_custom_keyboard_init(void)
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
void hid_custom_test(void)
|
||||
{
|
||||
uint8_t sendbuffer[64] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int ret = usbd_ep_start_write(HIDRAW_IN_EP, sendbuffer, 8);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
custom_state = HID_STATE_BUSY;
|
||||
while (custom_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
||||
@@ -172,9 +172,29 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
@@ -204,11 +224,14 @@ void hid_keyboard_init(void)
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 ------------------------------------------------------------------*/
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usb_midi.h"
|
||||
|
||||
#define MIDI_OUT_EP 0x02
|
||||
#define MIDI_IN_EP 0x81
|
||||
|
||||
#define USBD_VID 0x0d28
|
||||
#define USBD_PID 0x0404
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 9 + 9 + 7 + MIDI_SIZEOF_JACK_DESC + 9 + 5 + 9 + 5)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MIDI_EP_MPS 512
|
||||
#else
|
||||
#define MIDI_EP_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t midi_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
@@ -48,11 +64,11 @@ const uint8_t midi_descriptor[] = {
|
||||
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
|
||||
MIDI_JACK_DESCRIPTOR_INIT(0x01),
|
||||
// OUT endpoint descriptor
|
||||
0x09, 0x05, 0x02, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||
0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
|
||||
0x05, 0x25, 0x01, 0x01, 0x01,
|
||||
|
||||
// IN endpoint descriptor
|
||||
0x09, 0x05, 0x81, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||
0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
|
||||
0x05, 0x25, 0x01, 0x01, 0x03,
|
||||
|
||||
///////////////////////////////////////
|
||||
@@ -130,6 +146,31 @@ const uint8_t midi_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_midi_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x02
|
||||
|
||||
/*!< endpoint address */
|
||||
/*!< hidraw in endpoint */
|
||||
#define HIDRAW_IN_EP 0x83
|
||||
#define HIDRAW_IN_SIZE 64
|
||||
#define HIDRAW_IN_INTERVAL 10
|
||||
|
||||
/*!< hidraw out endpoint */
|
||||
#define HIDRAW_OUT_EP 0x04
|
||||
#define HIDRAW_OUT_EP_SIZE 64
|
||||
#define HIDRAW_OUT_EP_INTERVAL 10
|
||||
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFc
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< custom hid report descriptor size */
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 34
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN + 9+ 9 + 7 + 7)
|
||||
|
||||
const uint8_t hid_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
/************** Descriptor of Custom interface *****************/
|
||||
/* 41 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Custom HID ********************/
|
||||
/* 50 */
|
||||
0x09, /* bLength: HID Descriptor size */
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||
0x11, /* bcdHID: HID Class Spec release number */
|
||||
0x01,
|
||||
0x00, /* bCountryCode: Hardware target country */
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||
0x22, /* bDescriptorType */
|
||||
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Custom in endpoint ********************/
|
||||
/* 59 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HIDRAW_IN_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||
/******************** Descriptor of Custom out endpoint ********************/
|
||||
/* 66 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HIDRAW_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HIDRAW_OUT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'M', 0x00, /* wcChar10 */
|
||||
'S', 0x00, /* wcChar11 */
|
||||
'C', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BlockSpace[BLOCK_SIZE];
|
||||
} BLOCK_TYPE;
|
||||
|
||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||
|
||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < 10)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!< custom hid report descriptor */
|
||||
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||
/* USER CODE BEGIN 0 */
|
||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
/* <___________________________________________________> */
|
||||
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x95, 0x40, // REPORT_COUNT (64)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
/* USER CODE END 0 */
|
||||
0xC0 /* END_COLLECTION */
|
||||
};
|
||||
|
||||
/*!< class */
|
||||
static usbd_class_t hid_class;
|
||||
|
||||
/*!< interface */
|
||||
static usbd_interface_t hid_intf_2;
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
uint8_t custom_state = HID_STATE_IDLE;
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
static void usbd_hid_custom_in_callback(uint8_t ep)
|
||||
{
|
||||
/*!< endpoint call back */
|
||||
/*!< transfer successfully */
|
||||
if (custom_state == HID_STATE_BUSY) {
|
||||
/*!< update the state */
|
||||
custom_state = HID_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_hid_custom_out_callback(uint8_t ep)
|
||||
{
|
||||
/*!< read the data from host send */
|
||||
uint8_t custom_data[HIDRAW_OUT_EP_SIZE];
|
||||
usbd_ep_read(HIDRAW_OUT_EP, custom_data, HIDRAW_OUT_EP_SIZE, NULL);
|
||||
|
||||
/*!< you can use the data do some thing you like */
|
||||
}
|
||||
|
||||
/*!< endpoint call back */
|
||||
static struct usbd_interface custom_in_ep = {
|
||||
.ep_cb = usbd_hid_custom_in_callback,
|
||||
.ep_addr = HIDRAW_IN_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface custom_out_ep = {
|
||||
.ep_cb = usbd_hid_custom_out_callback,
|
||||
.ep_addr = HIDRAW_OUT_EP
|
||||
};
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief msc ram init
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
void hid_msc_descriptor_init(void)
|
||||
{
|
||||
usbd_desc_register(hid_msc_descriptor);
|
||||
|
||||
usbd_msc_class_init(MSC_OUT_EP, MSC_IN_EP);
|
||||
/*!< add interface */
|
||||
/*!< add interface the ! second interface */
|
||||
usbd_hid_add_interface(&hid_class, &hid_intf_2);
|
||||
/*!< interface1 add endpoint ! the first endpoint */
|
||||
usbd_interface_add_endpoint(&hid_intf_2, &custom_in_ep);
|
||||
/*!< interface1 add endpoint ! the second endpoint */
|
||||
usbd_interface_add_endpoint(&hid_intf_2, &custom_out_ep);
|
||||
|
||||
/*!< register report descriptor interface 1 */
|
||||
usbd_hid_report_descriptor_register(1, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE);
|
||||
|
||||
usbd_initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief device send report to host
|
||||
* @pre none
|
||||
* @param[in] ep endpoint address
|
||||
* @param[in] data points to the data buffer waiting to be sent
|
||||
* @param[in] len length of data to be sent
|
||||
* @retval none
|
||||
*/
|
||||
void hid_custom_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||
{
|
||||
if (usb_device_is_configured()) {
|
||||
if (custom_state == HID_STATE_IDLE) {
|
||||
/*!< updata the state */
|
||||
custom_state = HID_STATE_BUSY;
|
||||
/*!< write buffer */
|
||||
usbd_ep_write(ep, data, len, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief hid custom test
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
void hid_custom_test(void)
|
||||
{
|
||||
/*!< keyboard test */
|
||||
uint8_t sendbuffer1[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
|
||||
/*!< custom test */
|
||||
uint8_t sendbuffer2[64] = { 6 };
|
||||
hid_custom_send_report(HIDRAW_IN_EP, sendbuffer2, HIDRAW_IN_SIZE);
|
||||
//HAL_Delay(1000);
|
||||
}
|
||||
@@ -11,10 +11,16 @@
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t msc_ram_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -89,9 +95,29 @@ const uint8_t msc_ram_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
|
||||
@@ -61,10 +61,16 @@ struct usb_msosv1_descriptor msosv1_desc = {
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + MTP_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MTP_MAX_MPS 512
|
||||
#else
|
||||
#define MTP_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t mtp_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0201, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MTP_DESCRIPTOR_INIT(0x00, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, 2),
|
||||
MTP_DESCRIPTOR_INIT(0x00, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, MTP_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -145,8 +151,29 @@ const uint8_t bos_descriptor[] = {
|
||||
0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
@@ -101,10 +101,31 @@ static const uint8_t printer_descriptor[] = {
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[PRINTER_OUT_EP_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[PRINTER_IN_EP_SIZE];
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_printer_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
|
||||
126
demo/usb_host.c
126
demo/usb_host.c
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,9 +141,29 @@ const uint8_t video_descriptor[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* no out ep, so do nothing */
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool tx_flag = 0;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
|
||||
#define DOUBLE_WINUSB 0
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
@@ -16,6 +18,7 @@ __ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
#if DOUBLE_WINUSB == 0
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
@@ -37,61 +40,144 @@ __ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
#else
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[64] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
0x40, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x02, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
|
||||
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
0x00, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
0x01, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* WINUSB */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
#endif
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties [142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
#define WINUSB_IF1_WCID_PROPERTIES_SIZE (142)
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF1_WCIDProperties [142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
WINUSB_IF1_WCIDProperties,
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
|
||||
.string_len = 18,
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
|
||||
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
|
||||
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
|
||||
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
#if DOUBLE_WINUSB == 0
|
||||
.comp_id_property = &WINUSB_IF0_WCIDProperties,
|
||||
#else
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0x0d28
|
||||
#define USBD_PID 0x0404
|
||||
#define USBD_VID 0xefff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#if DOUBLE_WINUSB == 0
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
|
||||
#define INTF_NUM 1
|
||||
#else
|
||||
#define WINUSB_IN_EP2 0x83
|
||||
#define WINUSB_OUT_EP2 0x04
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + 9 + 7 + 7)
|
||||
#define INTF_NUM 2
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define WINUSB_EP_MPS 512
|
||||
@@ -100,11 +186,16 @@ struct usb_msosv1_descriptor msosv1_desc = {
|
||||
#endif
|
||||
|
||||
const uint8_t winusb_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xff, 0xff, 0xff, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0x01, 0x00, 0x02),
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x04),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
#if DOUBLE_WINUSB == 1
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x01, 0x00, 0x02, 0xff, 0xff, 0x00, 0x05),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP2, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP2, 0x02, WINUSB_EP_MPS, 0x00),
|
||||
#endif
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
@@ -164,6 +255,62 @@ const uint8_t winusb_descriptor[] = {
|
||||
'0', 0x00, /* wcChar7 */
|
||||
'0', 0x00, /* wcChar8 */
|
||||
'0', 0x00, /* wcChar9 */
|
||||
///////////////////////////////////////
|
||||
/// string4 descriptor
|
||||
///////////////////////////////////////
|
||||
0x30, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'W', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'N', 0x00, /* wcChar12 */
|
||||
'U', 0x00, /* wcChar13 */
|
||||
'S', 0x00, /* wcChar14 */
|
||||
'B', 0x00, /* wcChar15 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'D', 0x00, /* wcChar17 */
|
||||
'E', 0x00, /* wcChar18 */
|
||||
'M', 0x00, /* wcChar19 */
|
||||
'O', 0x00, /* wcChar20 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'1', 0x00, /* wcChar21 */
|
||||
///////////////////////////////////////
|
||||
/// string5 descriptor
|
||||
///////////////////////////////////////
|
||||
0x30, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'W', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'N', 0x00, /* wcChar12 */
|
||||
'U', 0x00, /* wcChar13 */
|
||||
'S', 0x00, /* wcChar14 */
|
||||
'B', 0x00, /* wcChar15 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'D', 0x00, /* wcChar17 */
|
||||
'E', 0x00, /* wcChar18 */
|
||||
'M', 0x00, /* wcChar19 */
|
||||
'O', 0x00, /* wcChar20 */
|
||||
' ', 0x00, /* wcChar16 */
|
||||
'2', 0x00, /* wcChar21 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
@@ -187,10 +334,34 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
void usbd_configure_done_callback(void)
|
||||
void usbd_event_handler(uint8_t event)
|
||||
{
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
#if DOUBLE_WINUSB == 1
|
||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
||||
#endif
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
|
||||
@@ -200,41 +371,86 @@ void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
|
||||
// printf("%02x ", read_buffer[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
usbd_ep_start_write(WINUSB_IN_EP, read_buffer, nbytes);
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_winusb_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
|
||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
||||
usbd_ep_start_write(WINUSB_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_endpoint winusb_out_ep = {
|
||||
struct usbd_endpoint winusb_out_ep1 = {
|
||||
.ep_addr = WINUSB_OUT_EP,
|
||||
.ep_cb = usbd_winusb_out
|
||||
};
|
||||
|
||||
struct usbd_endpoint winusb_in_ep = {
|
||||
struct usbd_endpoint winusb_in_ep1 = {
|
||||
.ep_addr = WINUSB_IN_EP,
|
||||
.ep_cb = usbd_winusb_in
|
||||
};
|
||||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
#if DOUBLE_WINUSB == 1
|
||||
|
||||
void usbd_winusb_out2(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
// for (int i = 0; i < 100; i++) {
|
||||
// printf("%02x ", read_buffer[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
usbd_ep_start_write(WINUSB_IN_EP2, read_buffer, nbytes);
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_winusb_in2(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
|
||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(WINUSB_IN_EP2, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_endpoint winusb_out_ep2 = {
|
||||
.ep_addr = WINUSB_OUT_EP2,
|
||||
.ep_cb = usbd_winusb_out2
|
||||
};
|
||||
|
||||
struct usbd_endpoint winusb_in_ep2 = {
|
||||
.ep_addr = WINUSB_IN_EP2,
|
||||
.ep_cb = usbd_winusb_in2
|
||||
};
|
||||
|
||||
struct usbd_interface intf1;
|
||||
|
||||
#endif
|
||||
|
||||
void winusb_init(void)
|
||||
{
|
||||
usbd_desc_register(winusb_descriptor);
|
||||
usbd_msosv1_desc_register(&msosv1_desc);
|
||||
usbd_add_interface(&intf0);
|
||||
usbd_add_endpoint(&winusb_out_ep);
|
||||
usbd_add_endpoint(&winusb_in_ep);
|
||||
|
||||
usbd_add_endpoint(&winusb_out_ep1);
|
||||
usbd_add_endpoint(&winusb_in_ep1);
|
||||
#if DOUBLE_WINUSB == 1
|
||||
usbd_add_interface(&intf1);
|
||||
usbd_add_endpoint(&winusb_out_ep2);
|
||||
usbd_add_endpoint(&winusb_in_ep2);
|
||||
#endif
|
||||
usbd_initialize();
|
||||
}
|
||||
1
docs/assets/CherryUSB.svg
Normal file
1
docs/assets/CherryUSB.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,48 +0,0 @@
|
||||
其他
|
||||
=========================
|
||||
|
||||
usb_malloc
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_malloc`` 用来申请内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *usb_malloc(size_t size);
|
||||
|
||||
- **size** 要申请的内存大小
|
||||
- **return** 申请的内存地址
|
||||
|
||||
usb_free
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_free`` 用来释放申请的内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_free(void *ptr);
|
||||
|
||||
- **ptr** 要释放的内存地址
|
||||
|
||||
usb_iomalloc
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_iomalloc`` 用来申请内存,并按照 `CONFIG_DCACHE_LINE_SIZE` 对齐,一般使用到 dcache 和 dma 需要对齐操作的时候使用。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *usb_iomalloc(size_t size);
|
||||
|
||||
- **size** 要申请的内存大小
|
||||
- **return** 申请的内存地址
|
||||
|
||||
usb_iofree
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_iofree`` 用来释放申请的内存。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usb_iofree(void *ptr);
|
||||
|
||||
- **ptr** 要释放的内存地址
|
||||
@@ -103,7 +103,7 @@ usbd_bos_desc_register
|
||||
usbd_add_interface
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_add_interface`` 添加一个接口驱动。
|
||||
``usbd_add_interface`` 添加一个接口驱动。 **添加顺序必须按照描述符顺序**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
@@ -122,37 +122,24 @@ usbd_add_endpoint
|
||||
|
||||
- **ep** 端点句柄
|
||||
|
||||
usb_device_is_configured
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usb_device_is_configured`` 用来检查 USB 设备是否被配置(枚举)。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
bool usb_device_is_configured(void);
|
||||
|
||||
- **return** 配置状态, 0 表示未配置, 1 表示配置成功
|
||||
|
||||
usbd_configure_done_callback
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_configure_done_callback`` 在执行 set_configuration 命令后触发,表示配置完成,用户需要实现该函数, **此函数一般用作启动第一次数据接收**,如果没有使用到 out 端点,则函数为空即可。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
bool usbd_configure_done_callback(void);
|
||||
|
||||
.. warning:: msc 端点不需要在该函数中手动启动,协议栈会自动启动第一次接收
|
||||
|
||||
usbd_initialize
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。
|
||||
``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。 **如果使用 os,必须放在线程中执行**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbd_initialize(void);
|
||||
|
||||
usbd_event_handler
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbd_event_handler`` 是协议栈中中断或者协议栈一些状态的回调函数。大部分 IP 仅支持 USBD_EVENT_RESET 和 USBD_EVENT_CONFIGURED
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_event_handler(uint8_t event);
|
||||
|
||||
CDC ACM
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -82,11 +82,13 @@ hubport 结构体
|
||||
const char *iManufacturer;
|
||||
const char *iProduct;
|
||||
const char *iSerialNumber;
|
||||
#if 0
|
||||
uint8_t* raw_config_desc;
|
||||
#endif
|
||||
USB_MEM_ALIGNX struct usb_setup_packet setup;
|
||||
uint8_t *raw_config_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usbh_hub *parent;
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
usb_osal_thread_t thread;
|
||||
};
|
||||
|
||||
hub 结构体
|
||||
@@ -101,12 +103,11 @@ hub 结构体
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
USB_MEM_ALIGNX uint8_t int_buffer[1];
|
||||
uint8_t *int_buffer;
|
||||
struct usbh_urb intin_urb;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
usb_slist_t hub_event_list;
|
||||
};
|
||||
|
||||
usbh_initialize
|
||||
|
||||
@@ -153,19 +153,19 @@ usbh_roothub_control
|
||||
- **buf** 接收缓冲区
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_ep0_pipe_reconfigure
|
||||
usbh_ep_pipe_reconfigure
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_ep0_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。
|
||||
``usbh_ep_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
- **pipe** pipe 句柄
|
||||
- **dev_addr** 端点所在设备地址
|
||||
- **ep_mps** 端点最大包长
|
||||
- **speed** 端点所在设备的速度
|
||||
- **mult** 端点一次传输个数
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_pipe_alloc
|
||||
|
||||
@@ -6,8 +6,8 @@ project = 'CherryUSB'
|
||||
copyright = '2022, sakumisu'
|
||||
author = 'sakumisu'
|
||||
|
||||
release = '0.9'
|
||||
version = '0.9.0'
|
||||
release = '0.10.0'
|
||||
version = '0.10.0'
|
||||
|
||||
# -- General configuration
|
||||
|
||||
|
||||
@@ -8,23 +8,41 @@ CherryUSB 使用指南
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的 USB 主从协议栈。同时 CherryUSB 具有以下优点:
|
||||
|
||||
- 代码精简,并且内存占用极小,而且还可进一步的裁剪
|
||||
- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律
|
||||
- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类
|
||||
- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程
|
||||
- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。
|
||||
- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制
|
||||
- 能够达到 USB 硬件理论带宽
|
||||
**易于学习 USB**
|
||||
|
||||
从机协议栈整体执行流程:
|
||||
为了方便用户学习 USB 基本知识、枚举、驱动加载、IP 驱动,因此,编写的代码具备以下优点:
|
||||
|
||||
- 代码精简,逻辑简单,无复杂 C 语言语法
|
||||
- 树状化编程,代码层层递进
|
||||
- Class 驱动和 porting 驱动模板化、精简化
|
||||
- API 分类清晰(从机:初始化、注册类、命令回调类、数据收发类;主机:初始化、查找类、数据收发类)
|
||||
|
||||
**易于使用 USB**
|
||||
|
||||
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma,因此,设计的数据收发类接口具备以下优点:
|
||||
|
||||
- 等价于使用 uart tx dma/uart rx dma
|
||||
- 收发长度没有限制,用户不需要关心 USB 分包过程(porting 驱动做分包过程)
|
||||
|
||||
**易于发挥 USB 性能**
|
||||
|
||||
考虑到 USB 性能问题,尽量达到 USB 硬件理论带宽,因此,设计的数据收发类接口具备以下优点:
|
||||
|
||||
- Porting 驱动直接对接寄存器,无抽象层封装
|
||||
- Memory zero copy
|
||||
- IP 如果带 DMA 则使用 DMA 模式(DMA 带硬件分包功能)
|
||||
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
|
||||
- 分包功能在中断中处理
|
||||
|
||||
**从机协议栈整体执行流程**
|
||||
|
||||
.. figure:: usbdev.svg
|
||||
|
||||
主机协议栈整体执行流程:
|
||||
**主机协议栈整体执行流程**
|
||||
|
||||
.. figure:: usbhost.svg
|
||||
|
||||
其他相关链接:
|
||||
**其他相关链接**
|
||||
|
||||
- **CherryUSB 大纲** https://www.bilibili.com/video/BV1st4y1H7K2
|
||||
- **从机协议栈视频教程** https://www.bilibili.com/video/BV1Ef4y1t73d
|
||||
@@ -59,7 +77,6 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
|
||||
api/api_device
|
||||
api/api_host
|
||||
api/api_port
|
||||
api/api_common
|
||||
api/api_config
|
||||
|
||||
.. toctree::
|
||||
|
||||
BIN
docs/source/quick_start/img/keil.png
Normal file
BIN
docs/source/quick_start/img/keil.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -36,6 +36,8 @@
|
||||
|
||||
.. caution :: 如果使用 STM32F7 或者 STM32H7, 请在 CFLAG 中添加 STM32F7 或者 STM32H7 宏定义,否则无法枚举
|
||||
|
||||
.. figure:: img/keil.png
|
||||
|
||||
工程样例试用
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
134
port/ehci/usb_glue_bouffalo.c
Normal file
134
port/ehci/usb_glue_bouffalo.c
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
562
third_party/CMSIS-DAP-2.1.1/Config/DAP_config.h
vendored
562
third_party/CMSIS-DAP-2.1.1/Config/DAP_config.h
vendored
@@ -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__ */
|
||||
367
third_party/CMSIS-DAP-2.1.1/Include/DAP.h
vendored
367
third_party/CMSIS-DAP-2.1.1/Include/DAP.h
vendored
@@ -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__ */
|
||||
201
third_party/CMSIS-DAP-2.1.1/LICENSE.txt
vendored
201
third_party/CMSIS-DAP-2.1.1/LICENSE.txt
vendored
@@ -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.
|
||||
1812
third_party/CMSIS-DAP-2.1.1/Source/DAP.c
vendored
1812
third_party/CMSIS-DAP-2.1.1/Source/DAP.c
vendored
File diff suppressed because it is too large
Load Diff
100
third_party/CMSIS-DAP-2.1.1/Source/DAP_vendor.c
vendored
100
third_party/CMSIS-DAP-2.1.1/Source/DAP_vendor.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
///@}
|
||||
370
third_party/CMSIS-DAP-2.1.1/Source/JTAG_DP.c
vendored
370
third_party/CMSIS-DAP-2.1.1/Source/JTAG_DP.c
vendored
@@ -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
Reference in New Issue
Block a user