Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6d539792f | ||
|
|
7b5d8f29d4 | ||
|
|
e7616399b7 | ||
|
|
a21947ff22 | ||
|
|
078e21066c | ||
|
|
2335e08ef2 | ||
|
|
64f8a86569 | ||
|
|
4164e687f0 | ||
|
|
4da3550582 | ||
|
|
22121bc54d | ||
|
|
68708c0f3a | ||
|
|
5cd50410e6 | ||
|
|
74bb03b8b4 | ||
|
|
bc6ed589b0 | ||
|
|
f99e4ce113 | ||
|
|
d6d1b67761 | ||
|
|
3c16d7c61c | ||
|
|
0d647cf9c0 | ||
|
|
eef3e116b8 | ||
|
|
bfa4490e6c | ||
|
|
2bfb7255cd | ||
|
|
f28b1c61ba | ||
|
|
f4a0ba9839 | ||
|
|
26e2436847 | ||
|
|
6cb442503d | ||
|
|
9dbc441082 | ||
|
|
44c408959b | ||
|
|
aa1a30d581 | ||
|
|
235139ad77 | ||
|
|
b2af686e67 | ||
|
|
15b97f3348 | ||
|
|
9145add9af | ||
|
|
ce241024b1 | ||
|
|
1d38fde61a | ||
|
|
b628c737ec | ||
|
|
e40c72f3a8 | ||
|
|
b4c455e5e6 | ||
|
|
2660af5d87 | ||
|
|
869b5809f3 | ||
|
|
4c062d4442 | ||
|
|
bba4b46fa4 | ||
|
|
2e862f3864 | ||
|
|
6369ead152 | ||
|
|
969c0342f0 | ||
|
|
5bd8ea8925 | ||
|
|
7910666998 | ||
|
|
39693f4702 | ||
|
|
f489619c20 | ||
|
|
215534982a | ||
|
|
6af1c143d3 | ||
|
|
9e9772fde7 | ||
|
|
b545830f70 | ||
|
|
850e96577c | ||
|
|
384b11eb88 | ||
|
|
cfbe5615c4 | ||
|
|
cbefa69715 | ||
|
|
9e0cc8347c | ||
|
|
8c72947794 | ||
|
|
d5b4cdd4bd | ||
|
|
3508879e1d | ||
|
|
5c36affc3c | ||
|
|
762c3cbb2f | ||
|
|
b4e952b371 | ||
|
|
756987050f | ||
|
|
64773ab5e8 | ||
|
|
743669861e | ||
|
|
0e3e9477cc | ||
|
|
56c90ab6f9 | ||
|
|
9c247f6e6b | ||
|
|
556fd6af63 | ||
|
|
4803a6826b | ||
|
|
e0551b3e7b | ||
|
|
31fa2b99c5 | ||
|
|
4313a2666e | ||
|
|
466d241c31 | ||
|
|
49116c6fbc | ||
|
|
e7a57289ce | ||
|
|
e34ecc6cbb | ||
|
|
d1c7fa8c19 | ||
|
|
920b02cb7c | ||
|
|
3f89d1b003 | ||
|
|
5897edffed | ||
|
|
a01c08ddaa | ||
|
|
dcad369d06 | ||
|
|
8232f64775 | ||
|
|
6fb3f31cbe | ||
|
|
eeb304ae08 | ||
|
|
fc80972284 | ||
|
|
feb69dcd95 | ||
|
|
cdfb7c3fb2 | ||
|
|
24511c4d4b | ||
|
|
c7cf09f6c3 | ||
|
|
6b0a0135ac | ||
|
|
04a300d803 | ||
|
|
0f5e05052f | ||
|
|
b773cecd2e | ||
|
|
c4a65146e8 | ||
|
|
6bc6b06076 | ||
|
|
125aad65d6 | ||
|
|
07ced6d023 | ||
|
|
45cca3930b | ||
|
|
eff338f8a7 | ||
|
|
1158fc3d8c | ||
|
|
d517f2594e | ||
|
|
b37f494304 | ||
|
|
5fe66b4f0d | ||
|
|
249e650c37 | ||
|
|
cbfac7ec0c |
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth"]
|
||||||
|
path = third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth
|
||||||
|
url = https://github.com/sakumisu/zephyr_bluetooth.git
|
||||||
|
[submodule "third_party/nimble-1.6.0/nimble"]
|
||||||
|
path = third_party/nimble-1.6.0/nimble
|
||||||
|
url = https://github.com/sakumisu/mynewt-nimble.git
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
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)
|
|
||||||
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_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()
|
|
||||||
3
CherryUSB.svg
Normal file
|
After Width: | Height: | Size: 38 KiB |
36
README.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
|
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Why choose
|
## Why choose
|
||||||
|
|
||||||
@@ -80,6 +80,7 @@ CherryUSB Device Stack has the following functions:
|
|||||||
- Support Remote NDIS (RNDIS)
|
- Support Remote NDIS (RNDIS)
|
||||||
- Support WINUSB1.0、WINUSB2.0(with BOS)
|
- Support WINUSB1.0、WINUSB2.0(with BOS)
|
||||||
- Support Vendor class
|
- Support Vendor class
|
||||||
|
- Support multi device with the same USB IP
|
||||||
|
|
||||||
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
||||||
|
|
||||||
@@ -102,15 +103,17 @@ CherryUSB Host Stack has the following functions:
|
|||||||
- Automatic loading of supported Class drivers
|
- Automatic loading of supported Class drivers
|
||||||
- Support blocking transfers and asynchronous transfers
|
- Support blocking transfers and asynchronous transfers
|
||||||
- Support Composite Device
|
- Support Composite Device
|
||||||
- Multi-level HUB support, expandable up to 7 levels
|
- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2 and ehci now)
|
||||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||||
- Support Human Interface Device (HID)
|
- Support Human Interface Device (HID)
|
||||||
- Support Mass Storage Class (MSC)
|
- Support Mass Storage Class (MSC)
|
||||||
- Support USB Video CLASS
|
- Support USB Video CLASS (commercial charge)
|
||||||
- Support USB Audio CLASS
|
- Support USB Audio CLASS (commercial charge)
|
||||||
- Support Remote NDIS (RNDIS)
|
- Support Remote NDIS (RNDIS)
|
||||||
|
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
|
||||||
- Support Vendor class
|
- Support Vendor class
|
||||||
- Support USB modeswitch
|
- Support USB modeswitch
|
||||||
|
- Support multi host with the same USB IP
|
||||||
|
|
||||||
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
|
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
|
||||||
|
|
||||||
@@ -127,6 +130,7 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
|||||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||||
|
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||||
|
|
||||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||||
|
|
||||||
@@ -148,6 +152,23 @@ x is affected by the following macros:
|
|||||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## USB IP Support
|
||||||
|
|
||||||
|
Only standard and commercial USB IP are listed.
|
||||||
|
|
||||||
|
| IP | device | host | Support status |
|
||||||
|
|:----------------:|:----------:|:--------:|:--------------:|
|
||||||
|
| OHCI(intel) | none | OHCI | × |
|
||||||
|
| EHCI(intel) | none | EHCI | √ |
|
||||||
|
| XHCI(intel) | none | XHCI | √ |
|
||||||
|
| UHCI(intel) | none | UHCI | × |
|
||||||
|
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||||
|
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||||
|
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||||
|
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||||
|
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||||
|
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||||
|
|
||||||
## Documentation Tutorial
|
## Documentation Tutorial
|
||||||
|
|
||||||
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
||||||
@@ -169,13 +190,14 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|
|||||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
|
||||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||||
|
|artinchip | d12x/d13x/d21x | dwc2/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||||
|
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||||
|
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
|
||||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
QQ group: 642693751
|
CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
|
||||||
42
README_zh.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 为什么选择
|
## 为什么选择
|
||||||
|
|
||||||
@@ -78,6 +78,7 @@ CherryUSB Device 协议栈当前实现以下功能:
|
|||||||
- 支持 Remote NDIS (RNDIS)
|
- 支持 Remote NDIS (RNDIS)
|
||||||
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
||||||
- 支持 Vendor 类 class
|
- 支持 Vendor 类 class
|
||||||
|
- 支持相同 USB IP 的多从机
|
||||||
|
|
||||||
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||||
|
|
||||||
@@ -100,15 +101,17 @@ CherryUSB Host 协议栈当前实现以下功能:
|
|||||||
- 自动加载支持的Class 驱动
|
- 自动加载支持的Class 驱动
|
||||||
- 支持阻塞式传输和异步传输
|
- 支持阻塞式传输和异步传输
|
||||||
- 支持复合设备
|
- 支持复合设备
|
||||||
- 支持多级 HUB,最高可拓展到 7 级
|
- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,当前仅支持 dwc2 和 ehci)
|
||||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||||
- 支持 Human Interface Device (HID)
|
- 支持 Human Interface Device (HID)
|
||||||
- 支持 Mass Storage Class (MSC)
|
- 支持 Mass Storage Class (MSC)
|
||||||
- Support USB Video CLASS
|
- Support USB Video CLASS(商业收费)
|
||||||
- Support USB Audio CLASS
|
- Support USB Audio CLASS(商业收费)
|
||||||
- 支持 Remote NDIS (RNDIS)
|
- 支持 Remote NDIS (RNDIS)
|
||||||
|
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
|
||||||
- 支持 Vendor 类 class
|
- 支持 Vendor 类 class
|
||||||
- 支持 USB modeswitch
|
- 支持 USB modeswitch
|
||||||
|
- 支持相同 USB IP 的多主机
|
||||||
|
|
||||||
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||||
|
|
||||||
@@ -125,6 +128,7 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
|||||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||||
|
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||||
|
|
||||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||||
|
|
||||||
@@ -146,13 +150,31 @@ x 受以下宏影响:
|
|||||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## USB IP 支持情况
|
||||||
|
|
||||||
|
仅列举标准 USB IP 和商业性 USB IP
|
||||||
|
|
||||||
|
| IP | device | host | Support status |
|
||||||
|
|:----------------:|:----------:|:--------:|:--------------:|
|
||||||
|
| OHCI(intel) | none | OHCI | × |
|
||||||
|
| EHCI(intel) | none | EHCI | √ |
|
||||||
|
| XHCI(intel) | none | XHCI | √ |
|
||||||
|
| UHCI(intel) | none | UHCI | × |
|
||||||
|
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||||
|
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||||
|
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||||
|
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||||
|
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||||
|
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||||
|
|
||||||
## 文档教程
|
## 文档教程
|
||||||
|
|
||||||
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
|
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
||||||
|
|
||||||
## 视频教程
|
## 视频教程
|
||||||
|
|
||||||
USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [CherryUSB Device 协议栈教程](https://www.bilibili.com/video/BV1Ef4y1t73d).
|
- USB 基本知识点与 CherryUSB Device 协议栈是如何编写的(使用v0.4.1 版本),参考 https://www.bilibili.com/video/BV1Ef4y1t73d.
|
||||||
|
- CherryUSB 腾讯会议(使用v1.1.0 版本),参考 https://www.bilibili.com/video/BV16x421y7mM.
|
||||||
|
|
||||||
## 图形化界面配置工具
|
## 图形化界面配置工具
|
||||||
|
|
||||||
@@ -167,13 +189,15 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
|
|||||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
|
||||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||||
|
|artinchip | d12x/d13x/d21x | dwc2/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||||
|
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||||
|
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
|
||||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
QQ 群:642693751
|
CherryUSB QQ 群:642693751
|
||||||
|
CherryUSB 微信群:与我联系后邀请加入
|
||||||
208
SConscript
@@ -10,6 +10,9 @@ path += [cwd + '/class/audio']
|
|||||||
path += [cwd + '/class/video']
|
path += [cwd + '/class/video']
|
||||||
path += [cwd + '/class/wireless']
|
path += [cwd + '/class/wireless']
|
||||||
path += [cwd + '/class/dfu']
|
path += [cwd + '/class/dfu']
|
||||||
|
path += [cwd + '/class/midi']
|
||||||
|
path += [cwd + '/class/vendor/net']
|
||||||
|
path += [cwd + '/class/vendor/serial']
|
||||||
src = []
|
src = []
|
||||||
|
|
||||||
CPPDEFINES = []
|
CPPDEFINES = []
|
||||||
@@ -23,7 +26,45 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
|||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||||
CPPDEFINES+=['CONFIG_USB_HS']
|
CPPDEFINES+=['CONFIG_USB_HS']
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']):
|
||||||
|
CPPDEFINES += ['CONFIG_CHERRYUSB']
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32']):
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||||
|
src += Glob('port/ch32/usb_dc_usbhs.c')
|
||||||
|
else:
|
||||||
|
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
|
||||||
|
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ST']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_st.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ESP']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_esp.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AT']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_at.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AIC']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_aic.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_STANDARD']):
|
||||||
|
src += Glob('port/musb/usb_dc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
|
||||||
|
src += Glob('port/musb/usb_dc_musb.c')
|
||||||
|
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
|
||||||
|
src += Glob('port/musb/usb_dc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
||||||
|
src += Glob('port/hpm/usb_dc_hpm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
|
||||||
|
path += [cwd + '/port/pusb2/common']
|
||||||
|
path += [cwd + '/port/pusb2/fpusb2']
|
||||||
|
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||||
|
src += Glob('port/pusb2/usb_dc_pusb2.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
|
||||||
src += Glob('class/cdc/usbd_cdc.c')
|
src += Glob('class/cdc/usbd_cdc.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
||||||
src += Glob('class/hid/usbd_hid.c')
|
src += Glob('class/hid/usbd_hid.c')
|
||||||
@@ -33,111 +74,132 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
|||||||
src += Glob('class/audio/usbd_audio.c')
|
src += Glob('class/audio/usbd_audio.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO']):
|
||||||
src += Glob('class/video/usbd_video.c')
|
src += Glob('class/video/usbd_video.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_RNDIS']):
|
||||||
src += Glob('class/wireless/usbd_rndis.c')
|
src += Glob('class/wireless/usbd_rndis.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ECM']):
|
||||||
|
src += Glob('class/cdc/usbd_cdc_ecm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_NCM']):
|
||||||
|
src += Glob('class/cdc/usbd_cdc_ncm.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
|
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
|
||||||
src += Glob('class/dfu/usbd_dfu.c')
|
src += Glob('class/dfu/usbd_dfu.c')
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
|
||||||
src += Glob('demo/cdc_acm_template.c')
|
src += Glob('demo/cdc_acm_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_MOUSE_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
|
||||||
src += Glob('demo/hid_mouse_template.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_KEYBOARD_TEMPLATE']):
|
|
||||||
src += Glob('demo/hid_keyboard_template.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
|
|
||||||
src += Glob('demo/msc_ram_template.c')
|
src += Glob('demo/msc_ram_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
|
||||||
src += Glob('demo/msc_storage_template.c')
|
src += Glob('demo/hid_mouse_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
|
||||||
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
src += Glob('demo/hid_keyboard_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM']):
|
||||||
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
|
src += Glob('demo/hid_custom_inout_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_VIDEO']):
|
||||||
src += Glob('demo/video_static_mjpeg_template.c')
|
src += Glob('demo/video_static_mjpeg_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER']):
|
||||||
|
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER']):
|
||||||
|
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS']):
|
||||||
src += Glob('demo/cdc_rndis_template.c')
|
src += Glob('demo/cdc_rndis_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM']):
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
|
src += Glob('demo/cdc_ecm_template.c')
|
||||||
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
|
||||||
|
src += Glob('demo/cdc_ncm_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
|
||||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
src += Glob('demo/cdc_acm_msc_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_STM32']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
|
||||||
src += Glob('port/dwc2/usb_glue_st.c')
|
src += Glob('demo/cdc_acm_hid_msc_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1']):
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
|
src += Glob('demo/winusb1.0_template.c')
|
||||||
src += Glob('port/musb/usb_dc_musb.c')
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC']):
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
|
src += Glob('demo/winusb2.0_cdc_template.c')
|
||||||
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID']):
|
||||||
|
src += Glob('demo/winusb2.0_hid_template.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
|
||||||
src += Glob('port/hpm/usb_dc_hpm.c')
|
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32_CH32V307']):
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
|
||||||
src += Glob('port/ch32/usb_dc_usbhs.c')
|
|
||||||
else:
|
|
||||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
|
|
||||||
path += [cwd + '/port/pusb2/common']
|
|
||||||
path += [cwd + '/port/pusb2/fpusb2']
|
|
||||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
|
||||||
src += Glob('port/pusb2/usb_dc_pusb2.c')
|
|
||||||
|
|
||||||
# USB HOST
|
# USB HOST
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST']):
|
if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||||
path += [cwd + '/osal']
|
|
||||||
path += [cwd + '/class/hub']
|
path += [cwd + '/class/hub']
|
||||||
src += Glob('core/usbh_core.c')
|
src += Glob('core/usbh_core.c')
|
||||||
src += Glob('class/hub/usbh_hub.c')
|
src += Glob('class/hub/usbh_hub.c')
|
||||||
src += Glob('osal/usb_osal_rtthread.c')
|
src += Glob('osal/usb_osal_rtthread.c')
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_BL']):
|
||||||
src += Glob('class/cdc/usbh_cdc_acm.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_HID']):
|
|
||||||
src += Glob('class/hid/usbh_hid.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
|
|
||||||
src += Glob('class/msc/usbh_msc.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
|
|
||||||
src += Glob('class/wireless/usbh_rndis.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
|
|
||||||
src += Glob('class/cdc/usbh_cdc_ecm.c')
|
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
|
|
||||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_STM32']):
|
|
||||||
src += Glob('port/dwc2/usb_glue_st.c')
|
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
|
|
||||||
src += Glob('port/musb/usb_hc_musb.c')
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
|
|
||||||
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI']):
|
|
||||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
|
src += Glob('port/ehci/usb_glue_bouffalo.c')
|
||||||
src += Glob('port/ehci/usb_glue_hpm.c')
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
|
||||||
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
|
src += Glob('port/ehci/usb_glue_hpm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_AIC']):
|
||||||
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
|
src += Glob('port/ehci/usb_glue_aic.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980']):
|
||||||
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
|
src += Glob('port/ehci/usb_glue_nuc980.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
|
||||||
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
|
src += Glob('port/ehci/usb_glue_ma35d0.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
|
||||||
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ST']):
|
||||||
|
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_st.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ESP']):
|
||||||
|
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||||
|
src += Glob('port/dwc2/usb_glue_esp.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_CUSTOM']):
|
||||||
|
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_STANDARD']):
|
||||||
|
src += Glob('port/musb/usb_hc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
|
||||||
|
src += Glob('port/musb/usb_hc_musb.c')
|
||||||
|
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
|
||||||
|
src += Glob('port/musb/usb_hc_musb.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
|
||||||
src += Glob('port/xhci/usb_hc_xhci.c')
|
src += Glob('port/xhci/usb_hc_xhci.c')
|
||||||
src += Glob('port/xhci/xhci_dbg.c')
|
src += Glob('port/xhci/xhci_dbg.c')
|
||||||
src += Glob('port/xhci/xhci.c')
|
src += Glob('port/xhci/xhci.c')
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
|
||||||
path += [cwd + '/port/pusb2/common']
|
path += [cwd + '/port/pusb2/common']
|
||||||
path += [cwd + '/port/pusb2/fpusb2']
|
path += [cwd + '/port/pusb2/fpusb2']
|
||||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||||
src += Glob('port/pusb2/usb_hc_pusb2.c')
|
src += Glob('port/pusb2/usb_hc_pusb2.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']):
|
||||||
|
src += Glob('class/cdc/usbh_cdc_acm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_HID']):
|
||||||
|
src += Glob('class/hid/usbh_hid.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
|
||||||
|
src += Glob('class/msc/usbh_msc.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_RNDIS']):
|
||||||
|
src += Glob('class/wireless/usbh_rndis.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
|
||||||
|
src += Glob('class/cdc/usbh_cdc_ecm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_NCM']):
|
||||||
|
src += Glob('class/cdc/usbh_cdc_ncm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_VIDEO']):
|
||||||
|
src += Glob('class/video/usbh_video.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_AUDIO']):
|
||||||
|
src += Glob('class/audio/usbh_audio.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_BLUETOOTH']):
|
||||||
|
src += Glob('class/wireless/usbh_bluetooth.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_ASIX']):
|
||||||
|
src += Glob('class/vendor/net/usbh_asix.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_RTL8152']):
|
||||||
|
src += Glob('class/vendor/net/usbh_rtl8152.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_FTDI']):
|
||||||
|
src += Glob('class/vendor/serial/usbh_ftdi.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CH34X']):
|
||||||
|
src += Glob('class/vendor/serial/usbh_ch34x.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
|
||||||
|
src += Glob('class/vendor/serial/usbh_cp210x.c')
|
||||||
|
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
||||||
src += Glob('demo/usb_host.c')
|
src += Glob('demo/usb_host.c')
|
||||||
|
|
||||||
if GetDepend('RT_USING_DFS'):
|
if GetDepend('RT_USING_DFS'):
|
||||||
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
|
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
|
||||||
|
|
||||||
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
|
|
||||||
|
|
||||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||||
|
|
||||||
Return('group')
|
Return('group')
|
||||||
|
|||||||
2
VERSION
@@ -1,5 +1,5 @@
|
|||||||
VERSION_MAJOR = 1
|
VERSION_MAJOR = 1
|
||||||
VERSION_MINOR = 0
|
VERSION_MINOR = 2
|
||||||
PATCHLEVEL = 99
|
PATCHLEVEL = 99
|
||||||
VERSION_TWEAK = 0
|
VERSION_TWEAK = 0
|
||||||
EXTRAVERSION = 0
|
EXTRAVERSION = 0
|
||||||
|
|||||||
219
cherryusb.cmake
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024, sakumisu
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
# set(CONFIG_CHERRYUSB_DEVICE 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_DEVICE_HID 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_DEVICE_DCD "dwc2_st")
|
||||||
|
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_HCD "ehci_xxx")
|
||||||
|
|
||||||
|
list(APPEND cherryusb_incs
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/common
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/core
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/hub
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/cdc
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/hid
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/msc
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/audio
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/video
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/wireless
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/midi
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_MSC)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbd_msc.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbd_audio.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbd_video.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_CDC_ECM)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ecm.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_CDC_NCM)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ncm.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_CDC_RNDIS)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbd_rndis.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_DEVICE_DFU)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
|
||||||
|
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_st")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_esp")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_aic")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_aic.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_at")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_at.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST)
|
||||||
|
list(APPEND cherryusb_srcs
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/core/usbh_core.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/hub/usbh_hub.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_acm.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_HID)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbh_hid.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbh_msc.c)
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_MSC_FATFS)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/port/fatfs_usbh.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/diskio.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ff.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffsystem.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffunicode.c)
|
||||||
|
|
||||||
|
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
|
||||||
|
|
||||||
|
set(BLUETOOTH_PATH ${CMAKE_CURRENT_LIST_DIR}/third_party/zephyr_bluetooth-2.7.5)
|
||||||
|
|
||||||
|
list(APPEND cherryusb_srcs
|
||||||
|
${BLUETOOTH_PATH}/ble_hci_usbh.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/beacon/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_hr/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_ht/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/central_multilink.c
|
||||||
|
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/handsfree/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/ibeacon/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/cts.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_csc/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_dis/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_esp/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/hog.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hr/src/main.c
|
||||||
|
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/main.c
|
||||||
|
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/hts.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/peripheral_identity.c
|
||||||
|
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ots/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_sc_only/src/main.c
|
||||||
|
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/scan_adv/src/main.c
|
||||||
|
)
|
||||||
|
|
||||||
|
include(${BLUETOOTH_PATH}/zephyr_bluetooth/zephyr_bluetooth.cmake)
|
||||||
|
list(APPEND cherryusb_srcs ${zephyr_bluetooth_srcs})
|
||||||
|
list(APPEND cherryusb_incs ${zephyr_bluetooth_incs})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_ASIX)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_asix.c)
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_RTL8152)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_rtl8152.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
|
||||||
|
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||||
|
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_bouffalo.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_hpm")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||||
|
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_hpm.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_aic")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||||
|
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_nuvoton")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||||
|
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_nuvoton.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "dwc2_st")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "dwc2_esp")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
||||||
|
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_freertos.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
|
||||||
|
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
||||||
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_yoc.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
#ifndef CHERRYUSB_CONFIG_H
|
#ifndef CHERRYUSB_CONFIG_H
|
||||||
#define CHERRYUSB_CONFIG_H
|
#define CHERRYUSB_CONFIG_H
|
||||||
|
|
||||||
#define CHERRYUSB_VERSION 0x010000
|
#define CHERRYUSB_VERSION 0x010200
|
||||||
#define CHERRYUSB_VERSION_STR "v1.0.0"
|
#define CHERRYUSB_VERSION_STR "v1.2.0"
|
||||||
|
|
||||||
/* ================ USB common Configuration ================ */
|
/* ================ USB common Configuration ================ */
|
||||||
|
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
/* ================= USB Device Stack Configuration ================ */
|
/* ================= USB Device Stack Configuration ================ */
|
||||||
|
|
||||||
|
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
|
||||||
|
|
||||||
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
|
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
|
||||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
|
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
|
||||||
|
|
||||||
@@ -45,8 +47,12 @@
|
|||||||
/* Enable test mode */
|
/* Enable test mode */
|
||||||
// #define CONFIG_USBDEV_TEST_MODE
|
// #define CONFIG_USBDEV_TEST_MODE
|
||||||
|
|
||||||
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
|
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
|
||||||
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
|
#define CONFIG_USBDEV_MSC_MAX_LUN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
|
||||||
|
#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
||||||
@@ -91,6 +97,7 @@
|
|||||||
|
|
||||||
/* ================ USB HOST Stack Configuration ================== */
|
/* ================ USB HOST Stack Configuration ================== */
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_MAX_BUS 1
|
||||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||||
@@ -129,26 +136,34 @@
|
|||||||
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
|
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
|
||||||
|
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
|
||||||
|
#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
|
||||||
|
#endif
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
|
||||||
|
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ================ USB Device Port Configuration ================*/
|
/* ================ USB Device Port Configuration ================*/
|
||||||
|
|
||||||
#define USBD_IRQHandler USBD_IRQHandler
|
#ifndef CONFIG_USBDEV_EP_NUM
|
||||||
#define USBD_BASE (0)
|
#define CONFIG_USBDEV_EP_NUM 8
|
||||||
#define CONFIG_USBDEV_EP_NUM 4
|
#endif
|
||||||
|
|
||||||
/* ================ USB Host Port Configuration ==================*/
|
/* ================ USB Host Port Configuration ==================*/
|
||||||
|
|
||||||
// #define USBH_IRQHandler USBH_IRQHandler
|
|
||||||
// #define USBH_BASE (0)
|
|
||||||
// #define CONFIG_USBHOST_PIPE_NUM 10
|
// #define CONFIG_USBHOST_PIPE_NUM 10
|
||||||
|
|
||||||
/* ================ EHCI Configuration ================ */
|
/* ================ EHCI Configuration ================ */
|
||||||
|
|
||||||
#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000)
|
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
|
||||||
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
|
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x10)
|
||||||
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
||||||
// #define CONFIG_USB_EHCI_INFO_ENABLE
|
|
||||||
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||||
// #define CONFIG_USB_EHCI_CONFIGFLAG
|
// #define CONFIG_USB_EHCI_CONFIGFLAG
|
||||||
// #define CONFIG_USB_EHCI_PORT_POWER
|
// #define CONFIG_USB_EHCI_PORT_POWER
|
||||||
|
// #define CONFIG_USB_EHCI_PRINT_HW_PARAM
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ struct usbd_audio_priv {
|
|||||||
struct audio_entity_info *table;
|
struct audio_entity_info *table;
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
uint16_t uac_version;
|
uint16_t uac_version;
|
||||||
} g_usbd_audio;
|
} g_usbd_audio[CONFIG_USBDEV_MAX_BUS];
|
||||||
|
|
||||||
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t control_selector;
|
uint8_t control_selector;
|
||||||
uint32_t sampling_freq = 0;
|
uint32_t sampling_freq = 0;
|
||||||
@@ -34,13 +34,13 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
|
|||||||
case AUDIO_REQUEST_SET_CUR:
|
case AUDIO_REQUEST_SET_CUR:
|
||||||
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
memcpy((uint8_t *)&sampling_freq, *data, *len);
|
||||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
|
||||||
break;
|
break;
|
||||||
case AUDIO_REQUEST_GET_CUR:
|
case AUDIO_REQUEST_GET_CUR:
|
||||||
case AUDIO_REQUEST_GET_MIN:
|
case AUDIO_REQUEST_GET_MIN:
|
||||||
case AUDIO_REQUEST_GET_MAX:
|
case AUDIO_REQUEST_GET_MAX:
|
||||||
case AUDIO_REQUEST_GET_RES:
|
case AUDIO_REQUEST_GET_RES:
|
||||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
|
||||||
memcpy(*data, &sampling_freq, 3);
|
memcpy(*data, &sampling_freq, 3);
|
||||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||||
*len = 3;
|
*len = 3;
|
||||||
@@ -55,7 +55,7 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int audio_class_interface_request_handler(uint8_t busid, 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",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -79,10 +79,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
|
|
||||||
ARG_UNUSED(mute_string);
|
ARG_UNUSED(mute_string);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
|
for (uint8_t i = 0; i < g_usbd_audio[busid].num; i++) {
|
||||||
if (g_usbd_audio.table[i].bEntityId == entity_id) {
|
if (g_usbd_audio[busid].table[i].bEntityId == entity_id) {
|
||||||
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
|
subtype = g_usbd_audio[busid].table[i].bDescriptorSubtype;
|
||||||
ep = g_usbd_audio.table[i].ep;
|
ep = g_usbd_audio[busid].table[i].ep;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,14 +98,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
case AUDIO_CONTROL_FEATURE_UNIT:
|
case AUDIO_CONTROL_FEATURE_UNIT:
|
||||||
switch (control_selector) {
|
switch (control_selector) {
|
||||||
case AUDIO_FU_CONTROL_MUTE:
|
case AUDIO_FU_CONTROL_MUTE:
|
||||||
if (g_usbd_audio.uac_version < 0x0200) {
|
if (g_usbd_audio[busid].uac_version < 0x0200) {
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case AUDIO_REQUEST_SET_CUR:
|
case AUDIO_REQUEST_SET_CUR:
|
||||||
mute = (*data)[0];
|
mute = (*data)[0];
|
||||||
usbd_audio_set_mute(ep, ch, mute);
|
usbd_audio_set_mute(busid, ep, ch, mute);
|
||||||
break;
|
break;
|
||||||
case AUDIO_REQUEST_GET_CUR:
|
case AUDIO_REQUEST_GET_CUR:
|
||||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -116,11 +116,11 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case AUDIO_REQUEST_CUR:
|
case AUDIO_REQUEST_CUR:
|
||||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||||
(*data)[0] = usbd_audio_get_mute(ep, ch);
|
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
|
||||||
*len = 1;
|
*len = 1;
|
||||||
} else {
|
} else {
|
||||||
mute = (*data)[0];
|
mute = (*data)[0];
|
||||||
usbd_audio_set_mute(ep, ch, mute);
|
usbd_audio_set_mute(busid, ep, ch, mute);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -130,7 +130,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIO_FU_CONTROL_VOLUME:
|
case AUDIO_FU_CONTROL_VOLUME:
|
||||||
if (g_usbd_audio.uac_version < 0x0200) {
|
if (g_usbd_audio[busid].uac_version < 0x0200) {
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case AUDIO_REQUEST_SET_CUR:
|
case AUDIO_REQUEST_SET_CUR:
|
||||||
memcpy(&volume, *data, *len);
|
memcpy(&volume, *data, *len);
|
||||||
@@ -141,10 +141,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
}
|
}
|
||||||
volume_db += 128; /* 0 ~ 255 */
|
volume_db += 128; /* 0 ~ 255 */
|
||||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
|
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);
|
usbd_audio_set_volume(busid, ep, ch, volume_db);
|
||||||
break;
|
break;
|
||||||
case AUDIO_REQUEST_GET_CUR:
|
case AUDIO_REQUEST_GET_CUR:
|
||||||
volume_db = usbd_audio_get_volume(ep, ch);
|
volume_db = usbd_audio_get_volume(busid, ep, ch);
|
||||||
volume_db -= 128;
|
volume_db -= 128;
|
||||||
if (volume_db >= 0) {
|
if (volume_db >= 0) {
|
||||||
volume = volume_db * 256;
|
volume = volume_db * 256;
|
||||||
@@ -177,7 +177,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case AUDIO_REQUEST_CUR:
|
case AUDIO_REQUEST_CUR:
|
||||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||||
volume_db = usbd_audio_get_volume(ep, ch);
|
volume_db = usbd_audio_get_volume(busid, ep, ch);
|
||||||
volume = volume_db;
|
volume = volume_db;
|
||||||
memcpy(*data, &volume, 2);
|
memcpy(*data, &volume, 2);
|
||||||
*len = 2;
|
*len = 2;
|
||||||
@@ -185,7 +185,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
memcpy(&volume, *data, *len);
|
memcpy(&volume, *data, *len);
|
||||||
volume_db = volume;
|
volume_db = volume;
|
||||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, 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);
|
usbd_audio_set_volume(busid, ep, ch, volume_db);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIO_REQUEST_RANGE:
|
case AUDIO_REQUEST_RANGE:
|
||||||
@@ -216,14 +216,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case AUDIO_REQUEST_CUR:
|
case AUDIO_REQUEST_CUR:
|
||||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||||
sampling_freq = usbd_audio_get_sampling_freq(ep);
|
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
|
||||||
memcpy(*data, &sampling_freq, 4);
|
memcpy(*data, &sampling_freq, 4);
|
||||||
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||||
*len = 4;
|
*len = 4;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&sampling_freq, *data, setup->wLength);
|
memcpy(&sampling_freq, *data, setup->wLength);
|
||||||
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
|
||||||
usbd_audio_set_sampling_freq(ep, sampling_freq);
|
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIO_REQUEST_RANGE:
|
case AUDIO_REQUEST_RANGE:
|
||||||
@@ -231,7 +231,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
uint8_t *sampling_freq_table = NULL;
|
uint8_t *sampling_freq_table = NULL;
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
|
|
||||||
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
|
usbd_audio_get_sampling_freq_table(busid, ep, &sampling_freq_table);
|
||||||
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
|
||||||
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
memcpy(*data, sampling_freq_table, (12 * num + 2));
|
||||||
*len = (12 * num + 2);
|
*len = (12 * num + 2);
|
||||||
@@ -264,7 +264,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_notify_handler(uint8_t event, void *arg)
|
static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -274,9 +274,9 @@ static void audio_notify_handler(uint8_t event, void *arg)
|
|||||||
case USBD_EVENT_SET_INTERFACE: {
|
case USBD_EVENT_SET_INTERFACE: {
|
||||||
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
||||||
if (intf->bAlternateSetting) {
|
if (intf->bAlternateSetting) {
|
||||||
usbd_audio_open(intf->bInterfaceNumber);
|
usbd_audio_open(busid, intf->bInterfaceNumber);
|
||||||
} else {
|
} else {
|
||||||
usbd_audio_close(intf->bInterfaceNumber);
|
usbd_audio_close(busid, intf->bInterfaceNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +287,8 @@ 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(uint8_t busid,
|
||||||
|
struct usbd_interface *intf,
|
||||||
uint16_t uac_version,
|
uint16_t uac_version,
|
||||||
struct audio_entity_info *table,
|
struct audio_entity_info *table,
|
||||||
uint8_t num)
|
uint8_t num)
|
||||||
@@ -304,40 +305,40 @@ struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
|||||||
intf->notify_handler = audio_notify_handler;
|
intf->notify_handler = audio_notify_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_usbd_audio.uac_version = uac_version;
|
g_usbd_audio[busid].uac_version = uac_version;
|
||||||
g_usbd_audio.table = table;
|
g_usbd_audio[busid].table = table;
|
||||||
g_usbd_audio.num = num;
|
g_usbd_audio[busid].num = num;
|
||||||
|
|
||||||
return intf;
|
return intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
|
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
|
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
|
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
|
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
|
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,22 +19,22 @@ struct audio_entity_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Init audio interface driver */
|
/* Init audio interface driver */
|
||||||
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
|
struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||||
uint16_t uac_version,
|
uint16_t uac_version,
|
||||||
struct audio_entity_info *table,
|
struct audio_entity_info *table,
|
||||||
uint8_t num);
|
uint8_t num);
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf);
|
void usbd_audio_open(uint8_t busid, uint8_t intf);
|
||||||
void usbd_audio_close(uint8_t intf);
|
void usbd_audio_close(uint8_t busid, uint8_t intf);
|
||||||
|
|
||||||
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
|
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
|
||||||
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
|
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
|
||||||
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
|
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
|
||||||
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
|
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);
|
||||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
|
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq);
|
||||||
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
|
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep);
|
||||||
|
|
||||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
|
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_audio.h"
|
#include "usbh_audio.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_audio"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/audio%d"
|
#define DEV_FORMAT "/dev/audio%d"
|
||||||
|
|
||||||
/* general descriptor field offsets */
|
/* general descriptor field offsets */
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
|
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
|
||||||
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
|
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
|
||||||
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
|
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
|
||||||
|
#define CDC_FUNC_DESC_NCM 0x1A
|
||||||
|
|
||||||
/* CDC class-specific request codes */
|
/* CDC class-specific request codes */
|
||||||
/* (usbcdc11.pdf, 6.2, Table 46) */
|
/* (usbcdc11.pdf, 6.2, Table 46) */
|
||||||
@@ -156,6 +157,17 @@
|
|||||||
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
|
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
|
||||||
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
|
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
|
||||||
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
|
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
|
||||||
|
#define CDC_REQUEST_GET_NTB_PARAMETERS 0x80
|
||||||
|
#define CDC_REQUEST_GET_NET_ADDRESS 0x81
|
||||||
|
#define CDC_REQUEST_SET_NET_ADDRESS 0x82
|
||||||
|
#define CDC_REQUEST_GET_NTB_FORMAT 0x83
|
||||||
|
#define CDC_REQUEST_SET_NTB_FORMAT 0x84
|
||||||
|
#define CDC_REQUEST_GET_NTB_INPUT_SIZE 0x85
|
||||||
|
#define CDC_REQUEST_SET_NTB_INPUT_SIZE 0x86
|
||||||
|
#define CDC_REQUEST_GET_MAX_DATAGRAM_SIZE 0x87
|
||||||
|
#define CDC_REQUEST_SET_MAX_DATAGRAM_SIZE 0x88
|
||||||
|
#define CDC_REQUEST_GET_CRC_MODE 0x89
|
||||||
|
#define CDC_REQUEST_SET_CRC_MODE 0x90
|
||||||
|
|
||||||
/* Communication feature selector codes */
|
/* Communication feature selector codes */
|
||||||
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
|
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
|
||||||
@@ -263,6 +275,10 @@
|
|||||||
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
|
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
|
||||||
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
|
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
|
||||||
|
|
||||||
|
#define CDC_NCM_NTH16_SIGNATURE 0x484D434E
|
||||||
|
#define CDC_NCM_NDP16_SIGNATURE_NCM0 0x304D434E
|
||||||
|
#define CDC_NCM_NDP16_SIGNATURE_NCM1 0x314D434E
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* Structures based on usbcdc11.pdf (www.usb.org)
|
* Structures based on usbcdc11.pdf (www.usb.org)
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@@ -339,7 +355,7 @@ struct cdc_acm_notification {
|
|||||||
} __PACKED;
|
} __PACKED;
|
||||||
|
|
||||||
/** Ethernet Networking Functional Descriptor */
|
/** Ethernet Networking Functional Descriptor */
|
||||||
struct cdc_ecm_descriptor {
|
struct cdc_eth_descriptor {
|
||||||
uint8_t bFunctionLength;
|
uint8_t bFunctionLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bDescriptorSubtype;
|
uint8_t bDescriptorSubtype;
|
||||||
@@ -350,7 +366,7 @@ struct cdc_ecm_descriptor {
|
|||||||
uint8_t bNumberPowerFilters;
|
uint8_t bNumberPowerFilters;
|
||||||
} __PACKED;
|
} __PACKED;
|
||||||
|
|
||||||
struct cdc_ecm_notification {
|
struct cdc_eth_notification {
|
||||||
uint8_t bmRequestType;
|
uint8_t bmRequestType;
|
||||||
uint8_t bNotificationType;
|
uint8_t bNotificationType;
|
||||||
uint16_t wValue;
|
uint16_t wValue;
|
||||||
@@ -359,6 +375,41 @@ struct cdc_ecm_notification {
|
|||||||
uint8_t data[8];
|
uint8_t data[8];
|
||||||
} __PACKED;
|
} __PACKED;
|
||||||
|
|
||||||
|
struct cdc_ncm_ntb_parameters {
|
||||||
|
uint16_t wLength;
|
||||||
|
uint16_t bmNtbFormatsSupported;
|
||||||
|
uint32_t dwNtbInMaxSize;
|
||||||
|
uint16_t wNdbInDivisor;
|
||||||
|
uint16_t wNdbInPayloadRemainder;
|
||||||
|
uint16_t wNdbInAlignment;
|
||||||
|
uint16_t wReserved;
|
||||||
|
uint32_t dwNtbOutMaxSize;
|
||||||
|
uint16_t wNdbOutDivisor;
|
||||||
|
uint16_t wNdbOutPayloadRemainder;
|
||||||
|
uint16_t wNdbOutAlignment;
|
||||||
|
uint16_t wNtbOutMaxDatagrams;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cdc_ncm_nth16 {
|
||||||
|
uint32_t dwSignature;
|
||||||
|
uint16_t wHeaderLength;
|
||||||
|
uint16_t wSequence;
|
||||||
|
uint16_t wBlockLength;
|
||||||
|
uint16_t wNdpIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cdc_ncm_ndp16_datagram {
|
||||||
|
uint16_t wDatagramIndex;
|
||||||
|
uint16_t wDatagramLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cdc_ncm_ndp16 {
|
||||||
|
uint32_t dwSignature;
|
||||||
|
uint16_t wLength;
|
||||||
|
uint16_t wNextNdpIndex;
|
||||||
|
struct cdc_ncm_ndp16_datagram datagram[];
|
||||||
|
};
|
||||||
|
|
||||||
/*Length of template descriptor: 66 bytes*/
|
/*Length of template descriptor: 66 bytes*/
|
||||||
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@@ -499,7 +550,7 @@ struct cdc_ecm_notification {
|
|||||||
|
|
||||||
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
|
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
|
||||||
|
|
||||||
/*Length of template descriptor: 66 bytes*/
|
/*Length of template descriptor: 71 bytes*/
|
||||||
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
|
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||||
@@ -569,4 +620,79 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
|
|||||||
0x00 /* bInterval */
|
0x00 /* bInterval */
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
/*Length of template descriptor: 77 bytes*/
|
||||||
|
#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 7 + 7)
|
||||||
|
// clang-format off
|
||||||
|
#define CDC_NCM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||||
|
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
|
||||||
|
/* Interface Associate */ \
|
||||||
|
0x08, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||||
|
bFirstInterface, /* bFirstInterface */ \
|
||||||
|
0x02, /* bInterfaceCount */ \
|
||||||
|
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||||
|
CDC_NETWORK_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||||
|
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||||
|
0x00, /* iFunction */ \
|
||||||
|
0x09, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||||
|
bFirstInterface, /* bInterfaceNumber */ \
|
||||||
|
0x00, /* bAlternateSetting */ \
|
||||||
|
0x01, /* bNumEndpoints */ \
|
||||||
|
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||||
|
CDC_NETWORK_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||||
|
CDC_COMMON_PROTOCOL_NONE, /* 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_UNION, /* bDescriptorSubtype */ \
|
||||||
|
bFirstInterface, /* bMasterInterface */ \
|
||||||
|
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||||
|
/* CDC ETH Functional Descriptor */ \
|
||||||
|
0x0D, /* bFunctionLength */\
|
||||||
|
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
|
||||||
|
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
|
||||||
|
str_idx, /* Device's MAC string index */\
|
||||||
|
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
|
||||||
|
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
|
||||||
|
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
|
||||||
|
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
|
||||||
|
0x06, \
|
||||||
|
CDC_CS_INTERFACE, \
|
||||||
|
CDC_FUNC_DESC_NCM, \
|
||||||
|
0x00, 0x01, \
|
||||||
|
0x23, \
|
||||||
|
0x07, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||||
|
int_ep, /* bEndpointAddress */ \
|
||||||
|
0x03, /* bmAttributes */ \
|
||||||
|
0x10, 0x00, /* wMaxPacketSize */ \
|
||||||
|
0x10, /* bInterval */ \
|
||||||
|
0x09, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||||
|
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||||
|
0x00, /* bAlternateSetting */ \
|
||||||
|
0x02, /* bNumEndpoints */ \
|
||||||
|
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||||
|
0x00, /* bInterfaceSubClass */ \
|
||||||
|
0x00, /* bInterfaceProtocol */ \
|
||||||
|
0x00, /* iInterface */ \
|
||||||
|
0x07, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||||
|
out_ep, /* bEndpointAddress */ \
|
||||||
|
0x02, /* bmAttributes */ \
|
||||||
|
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||||
|
0x00, /* bInterval */ \
|
||||||
|
0x07, /* bLength */ \
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||||
|
in_ep, /* bEndpointAddress */ \
|
||||||
|
0x02, /* bmAttributes */ \
|
||||||
|
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||||
|
0x00 /* bInterval */
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#endif /* USB_CDC_H */
|
#endif /* USB_CDC_H */
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
const char *stop_name[] = { "1", "1.5", "2" };
|
const char *stop_name[] = { "1", "1.5", "2" };
|
||||||
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
||||||
|
|
||||||
static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("CDC Class request: "
|
USB_LOG_DBG("CDC Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -47,7 +47,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
|||||||
parity_name[line_coding.bParityType],
|
parity_name[line_coding.bParityType],
|
||||||
stop_name[line_coding.bCharFormat]);
|
stop_name[line_coding.bCharFormat]);
|
||||||
|
|
||||||
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
|
usbd_cdc_acm_set_line_coding(busid, intf_num, &line_coding);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||||
@@ -57,12 +57,12 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
|||||||
intf_num,
|
intf_num,
|
||||||
dtr,
|
dtr,
|
||||||
rts);
|
rts);
|
||||||
usbd_cdc_acm_set_dtr(intf_num, dtr);
|
usbd_cdc_acm_set_dtr(busid, intf_num, dtr);
|
||||||
usbd_cdc_acm_set_rts(intf_num, rts);
|
usbd_cdc_acm_set_rts(busid, intf_num, rts);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CDC_REQUEST_GET_LINE_CODING:
|
case CDC_REQUEST_GET_LINE_CODING:
|
||||||
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
|
usbd_cdc_acm_get_line_coding(busid, intf_num, &line_coding);
|
||||||
memcpy(*data, &line_coding, 7);
|
memcpy(*data, &line_coding, 7);
|
||||||
*len = 7;
|
*len = 7;
|
||||||
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
|
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
|
||||||
@@ -73,7 +73,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
|||||||
line_coding.bDataBits);
|
line_coding.bDataBits);
|
||||||
break;
|
break;
|
||||||
case CDC_REQUEST_SEND_BREAK:
|
case CDC_REQUEST_SEND_BREAK:
|
||||||
usbd_cdc_acm_send_break(intf_num);
|
usbd_cdc_acm_send_break(busid, intf_num);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
|
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||||
@@ -83,7 +83,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
|
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
|
||||||
{
|
{
|
||||||
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
|
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
@@ -93,11 +93,11 @@ struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
|
|||||||
return intf;
|
return intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
|
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
|
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||||
{
|
{
|
||||||
line_coding->dwDTERate = 2000000;
|
line_coding->dwDTERate = 2000000;
|
||||||
line_coding->bDataBits = 8;
|
line_coding->bDataBits = 8;
|
||||||
@@ -105,14 +105,14 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *l
|
|||||||
line_coding->bCharFormat = 0;
|
line_coding->bCharFormat = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
|
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
|
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init cdc acm interface driver */
|
/* Init cdc acm interface driver */
|
||||||
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf);
|
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||||
|
|
||||||
/* Setup request command callback api */
|
/* Setup request command callback api */
|
||||||
void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
|
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||||
void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
|
void usbd_cdc_acm_get_line_coding(uint8_t busid, 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_dtr(uint8_t busid, uint8_t intf, bool dtr);
|
||||||
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
|
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
|
||||||
void usbd_cdc_acm_send_break(uint8_t intf);
|
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
|
|||||||
|
|
||||||
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
|
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
|
||||||
{
|
{
|
||||||
struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
|
struct cdc_eth_notification *notify = (struct cdc_eth_notification *)g_cdc_ecm_notify_buf;
|
||||||
uint8_t bytes2send = 0;
|
uint8_t bytes2send = 0;
|
||||||
|
|
||||||
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
|
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
|
||||||
@@ -75,11 +75,11 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bytes2send) {
|
if (bytes2send) {
|
||||||
usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
|
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("CDC ECM Class request: "
|
USB_LOG_DBG("CDC ECM Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -109,7 +109,7 @@ static int cdc_ecm_class_interface_request_handler(struct usb_setup_packet *setu
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_ecm_notify_handler(uint8_t event, void *arg)
|
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -119,7 +119,7 @@ void cdc_ecm_notify_handler(uint8_t event, void *arg)
|
|||||||
g_cdc_ecm_rx_data_buffer = NULL;
|
g_cdc_ecm_rx_data_buffer = NULL;
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -127,29 +127,29 @@ void cdc_ecm_notify_handler(uint8_t event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
|
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
g_cdc_ecm_rx_data_length += nbytes;
|
g_cdc_ecm_rx_data_length += nbytes;
|
||||||
|
|
||||||
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
|
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
|
||||||
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
|
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
|
||||||
usbd_cdc_ecm_data_recv_done();
|
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||||
} else {
|
} else {
|
||||||
usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
|
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
|
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(ep, NULL, 0);
|
usbd_ep_start_write(0, ep, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
g_cdc_ecm_tx_data_length = 0;
|
g_cdc_ecm_tx_data_length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
|
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
if (g_current_net_status == 1) {
|
if (g_current_net_status == 1) {
|
||||||
g_current_net_status = 2;
|
g_current_net_status = 2;
|
||||||
@@ -157,6 +157,25 @@ void cdc_ecm_int_in(uint8_t ep, uint32_t nbytes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
|
||||||
|
{
|
||||||
|
if (g_cdc_ecm_tx_data_length > 0) {
|
||||||
|
return -USB_ERR_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cdc_ecm_tx_data_length = len;
|
||||||
|
|
||||||
|
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
|
||||||
|
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_cdc_ecm_start_read_next(void)
|
||||||
|
{
|
||||||
|
g_cdc_ecm_rx_data_length = 0;
|
||||||
|
g_cdc_ecm_rx_data_buffer = NULL;
|
||||||
|
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||||
struct pbuf *usbd_cdc_ecm_eth_rx(void)
|
struct pbuf *usbd_cdc_ecm_eth_rx(void)
|
||||||
{
|
{
|
||||||
@@ -167,16 +186,14 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
|
|||||||
}
|
}
|
||||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
|
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
usbd_cdc_ecm_start_read_next();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||||
p->len = g_cdc_ecm_rx_data_length;
|
p->len = g_cdc_ecm_rx_data_length;
|
||||||
|
|
||||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
|
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
|
||||||
g_cdc_ecm_rx_data_length = 0;
|
usbd_cdc_ecm_start_read_next();
|
||||||
g_cdc_ecm_rx_data_buffer = NULL;
|
|
||||||
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,8 +218,7 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
|
|||||||
|
|
||||||
g_cdc_ecm_tx_data_length = p->tot_len;
|
g_cdc_ecm_tx_data_length = p->tot_len;
|
||||||
|
|
||||||
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
|
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
|
||||||
return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -220,9 +236,9 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const
|
|||||||
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
|
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
|
||||||
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
|
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
|
||||||
|
|
||||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
|
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
|
||||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
|
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
|
||||||
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
|
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
|
||||||
|
|
||||||
return intf;
|
return intf;
|
||||||
}
|
}
|
||||||
@@ -232,6 +248,6 @@ void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
|
|||||||
memcpy(g_connect_speed_table, speed, 8);
|
memcpy(g_connect_speed_table, speed, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_cdc_ecm_data_recv_done(void)
|
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -14,17 +14,23 @@ extern "C" {
|
|||||||
|
|
||||||
/* Ethernet Maximum Segment size, typically 1514 bytes */
|
/* Ethernet Maximum Segment size, typically 1514 bytes */
|
||||||
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
|
||||||
|
|
||||||
/* Init cdc ecm interface driver */
|
/* Init cdc ecm interface driver */
|
||||||
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
|
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
|
||||||
|
|
||||||
/* Setup request command callback api */
|
/* Setup request command callback api */
|
||||||
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
|
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
|
||||||
void usbd_cdc_ecm_data_recv_done(void);
|
|
||||||
|
/* Api for eth only without any net stack */
|
||||||
|
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
|
||||||
|
void usbd_cdc_ecm_send_done(void);
|
||||||
|
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
|
||||||
|
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
|
||||||
|
void usbd_cdc_ecm_start_read_next(void);
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||||
#include <lwip/pbuf.h>
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
struct pbuf *usbd_cdc_ecm_eth_rx(void);
|
struct pbuf *usbd_cdc_ecm_eth_rx(void);
|
||||||
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
|
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,9 +6,13 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_cdc_acm.h"
|
#include "usbh_cdc_acm.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_cdc_acm"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/ttyACM%d"
|
#define DEV_FORMAT "/dev/ttyACM%d"
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
|
||||||
|
|
||||||
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_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 uint32_t g_devinuse = 0;
|
||||||
@@ -45,12 +49,12 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
|||||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
|
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
|
||||||
setup->wValue = 0;
|
setup->wValue = 0;
|
||||||
setup->wIndex = cdc_acm_class->ctrl_intf;
|
setup->wIndex = cdc_acm_class->intf;
|
||||||
setup->wLength = 7;
|
setup->wLength = 7;
|
||||||
|
|
||||||
memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
|
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
|
||||||
return usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||||
@@ -61,14 +65,14 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
|||||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
|
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
|
||||||
setup->wValue = 0;
|
setup->wValue = 0;
|
||||||
setup->wIndex = cdc_acm_class->ctrl_intf;
|
setup->wIndex = cdc_acm_class->intf;
|
||||||
setup->wLength = 7;
|
setup->wLength = 7;
|
||||||
|
|
||||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(line_coding, (uint8_t *)&g_cdc_line_coding, sizeof(struct cdc_line_coding));
|
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,19 +83,16 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
|
|||||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
|
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
|
||||||
setup->wValue = (dtr << 0) | (rts << 1);
|
setup->wValue = (dtr << 0) | (rts << 1);
|
||||||
setup->wIndex = cdc_acm_class->ctrl_intf;
|
setup->wIndex = cdc_acm_class->intf;
|
||||||
setup->wLength = 0;
|
setup->wLength = 0;
|
||||||
|
|
||||||
cdc_acm_class->dtr = dtr;
|
|
||||||
cdc_acm_class->rts = rts;
|
|
||||||
|
|
||||||
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
|
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
struct usb_endpoint_descriptor *ep_desc;
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
|
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
|
||||||
if (cdc_acm_class == NULL) {
|
if (cdc_acm_class == NULL) {
|
||||||
@@ -100,28 +101,11 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cdc_acm_class->hport = hport;
|
cdc_acm_class->hport = hport;
|
||||||
cdc_acm_class->ctrl_intf = intf;
|
cdc_acm_class->intf = intf;
|
||||||
cdc_acm_class->data_intf = intf + 1;
|
|
||||||
|
|
||||||
hport->config.intf[intf].priv = cdc_acm_class;
|
hport->config.intf[intf].priv = cdc_acm_class;
|
||||||
hport->config.intf[intf + 1].priv = NULL;
|
hport->config.intf[intf + 1].priv = NULL;
|
||||||
|
|
||||||
cdc_acm_class->linecoding.dwDTERate = 115200;
|
|
||||||
cdc_acm_class->linecoding.bDataBits = 8;
|
|
||||||
cdc_acm_class->linecoding.bParityType = 0;
|
|
||||||
cdc_acm_class->linecoding.bCharFormat = 0;
|
|
||||||
ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, &cdc_acm_class->linecoding);
|
|
||||||
if (ret < 0) {
|
|
||||||
USB_LOG_ERR("Fail to set linecoding\r\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = usbh_cdc_acm_set_line_state(cdc_acm_class, true, true);
|
|
||||||
if (ret < 0) {
|
|
||||||
USB_LOG_ERR("Fail to set line state\r\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||||
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
|
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
|
||||||
@@ -140,6 +124,34 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
|
|
||||||
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
|
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
USB_LOG_INFO("Test cdc acm rx and tx and rx for 5 times, baudrate is 115200\r\n");
|
||||||
|
|
||||||
|
struct cdc_line_coding linecoding;
|
||||||
|
uint8_t count = 5;
|
||||||
|
|
||||||
|
linecoding.dwDTERate = 115200;
|
||||||
|
linecoding.bDataBits = 8;
|
||||||
|
linecoding.bParityType = 0;
|
||||||
|
linecoding.bCharFormat = 0;
|
||||||
|
usbh_cdc_acm_set_line_coding(cdc_acm_class, &linecoding);
|
||||||
|
usbh_cdc_acm_set_line_state(cdc_acm_class, true, false);
|
||||||
|
|
||||||
|
memset(g_cdc_acm_buf, 'a', sizeof(g_cdc_acm_buf));
|
||||||
|
ret = usbh_cdc_acm_bulk_out_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("out ret:%d\r\n", ret);
|
||||||
|
while (count--) {
|
||||||
|
ret = usbh_cdc_acm_bulk_in_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("in ret:%d\r\n", ret);
|
||||||
|
if (ret > 0) {
|
||||||
|
for (uint32_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", g_cdc_acm_buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
usbh_cdc_acm_run(cdc_acm_class);
|
usbh_cdc_acm_run(cdc_acm_class);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,18 @@ struct usbh_cdc_acm {
|
|||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
|
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||||
|
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
|
||||||
|
#endif
|
||||||
struct usbh_urb bulkout_urb;
|
struct usbh_urb bulkout_urb;
|
||||||
struct usbh_urb bulkin_urb;
|
struct usbh_urb bulkin_urb;
|
||||||
|
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||||
struct usbh_urb intin_urb;
|
struct usbh_urb intin_urb;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct cdc_line_coding linecoding;
|
struct cdc_line_coding linecoding;
|
||||||
uint8_t ctrl_intf; /* Control interface number */
|
|
||||||
uint8_t data_intf; /* Data interface number */
|
uint8_t intf;
|
||||||
bool dtr;
|
|
||||||
bool rts;
|
|
||||||
uint8_t minor;
|
uint8_t minor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, sakumisu
|
* Copyright (c) 2024, sakumisu
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_cdc_ecm.h"
|
#include "usbh_cdc_ecm.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_cdc_ecm"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/cdc_ether"
|
#define DEV_FORMAT "/dev/cdc_ether"
|
||||||
|
|
||||||
/* general descriptor field offsets */
|
/* general descriptor field offsets */
|
||||||
@@ -39,7 +43,7 @@ static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class
|
|||||||
return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL);
|
return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_cdc_ecm_get_notification(struct usbh_cdc_ecm *cdc_ecm_class)
|
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -91,7 +95,7 @@ static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
break;
|
break;
|
||||||
case CDC_CS_INTERFACE:
|
case CDC_CS_INTERFACE:
|
||||||
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
||||||
struct cdc_ecm_descriptor *desc = (struct cdc_ecm_descriptor *)p;
|
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
|
||||||
mac_str_idx = desc->iMACAddress;
|
mac_str_idx = desc->iMACAddress;
|
||||||
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
|
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
|
||||||
goto get_mac;
|
goto get_mac;
|
||||||
@@ -240,7 +244,7 @@ find_class:
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (g_cdc_ecm_class.connect_status == false) {
|
while (g_cdc_ecm_class.connect_status == false) {
|
||||||
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
|
ret = usbh_cdc_ecm_get_connect_status(&g_cdc_ecm_class);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
usb_osal_msleep(100);
|
usb_osal_msleep(100);
|
||||||
goto find_class;
|
goto find_class;
|
||||||
@@ -257,7 +261,7 @@ find_class:
|
|||||||
|
|
||||||
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
|
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
|
||||||
|
|
||||||
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
|
if (g_cdc_ecm_class.bulkin_urb.actual_length != USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
|
||||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
|
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
|
||||||
|
|
||||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
|
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
|
||||||
@@ -274,6 +278,7 @@ find_class:
|
|||||||
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
|
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* read continue util read short packet */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, sakumisu
|
* Copyright (c) 2024, sakumisu
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +38,8 @@ struct usbh_cdc_ecm {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||||
|
|
||||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
|
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
|
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||||
|
|
||||||
@@ -48,4 +50,4 @@ void usbh_cdc_ecm_rx_thread(void *argument);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* USBH_CDC_ACM_H */
|
#endif /* USBH_CDC_ECM_H */
|
||||||
|
|||||||
408
class/cdc/usbh_cdc_ncm.c
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_cdc_ncm.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_cdc_ncm"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/cdc_ncm"
|
||||||
|
|
||||||
|
/* general descriptor field offsets */
|
||||||
|
#define DESC_bLength 0 /** Length offset */
|
||||||
|
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||||
|
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
|
||||||
|
|
||||||
|
/* interface descriptor field offsets */
|
||||||
|
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||||
|
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE 1514U
|
||||||
|
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_rx_buffer[2048];
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_tx_buffer[2048];
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_inttx_buffer[16];
|
||||||
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_buf[32];
|
||||||
|
|
||||||
|
static struct usbh_cdc_ncm g_cdc_ncm_class;
|
||||||
|
|
||||||
|
static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, struct cdc_ncm_ntb_parameters *param)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cdc_ncm_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CDC_REQUEST_GET_NTB_PARAMETERS;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = cdc_ncm_class->ctrl_intf;
|
||||||
|
setup->wLength = 28;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((uint8_t *)param, g_cdc_ncm_buf, ret - 8);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("CDC NCM ntb parameters:\r\n");
|
||||||
|
USB_LOG_RAW("wLength: 0x%02x \r\n", param->wLength);
|
||||||
|
USB_LOG_RAW("bmNtbFormatsSupported: %s \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
|
||||||
|
|
||||||
|
USB_LOG_RAW("dwNtbInMaxSize: 0x%04x \r\n", param->dwNtbInMaxSize);
|
||||||
|
USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
|
||||||
|
USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x \r\n", param->wNdbInPayloadRemainder);
|
||||||
|
USB_LOG_RAW("wNdbInAlignment: 0x%02x \r\n", param->wNdbInAlignment);
|
||||||
|
|
||||||
|
USB_LOG_RAW("dwNtbOutMaxSize: 0x%04x \r\n", param->dwNtbOutMaxSize);
|
||||||
|
USB_LOG_RAW("wNdbOutDivisor: 0x%02x \r\n", param->wNdbOutDivisor);
|
||||||
|
USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x \r\n", param->wNdbOutPayloadRemainder);
|
||||||
|
USB_LOG_RAW("wNdbOutAlignment: 0x%02x \r\n", param->wNdbOutAlignment);
|
||||||
|
|
||||||
|
USB_LOG_RAW("wNtbOutMaxDatagrams: 0x%02x \r\n", param->wNtbOutMaxDatagrams);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
usbh_int_urb_fill(&cdc_ncm_class->intin_urb, cdc_ncm_class->hport, cdc_ncm_class->intin, g_cdc_ncm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&cdc_ncm_class->intin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
|
||||||
|
if (g_cdc_ncm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
|
||||||
|
cdc_ncm_class->connect_status = true;
|
||||||
|
} else {
|
||||||
|
cdc_ncm_class->connect_status = false;
|
||||||
|
}
|
||||||
|
} else if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
|
||||||
|
memcpy(cdc_ncm_class->speed, &g_cdc_ncm_inttx_buffer[8], 8);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cdc_ncm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret;
|
||||||
|
uint8_t altsetting = 0;
|
||||||
|
char mac_buffer[12];
|
||||||
|
uint8_t *p;
|
||||||
|
uint8_t cur_iface = 0xff;
|
||||||
|
uint8_t mac_str_idx = 0xff;
|
||||||
|
|
||||||
|
struct usbh_cdc_ncm *cdc_ncm_class = &g_cdc_ncm_class;
|
||||||
|
|
||||||
|
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
|
||||||
|
|
||||||
|
cdc_ncm_class->hport = hport;
|
||||||
|
cdc_ncm_class->ctrl_intf = intf;
|
||||||
|
cdc_ncm_class->data_intf = intf + 1;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = cdc_ncm_class;
|
||||||
|
hport->config.intf[intf + 1].priv = NULL;
|
||||||
|
|
||||||
|
p = hport->raw_config_desc;
|
||||||
|
while (p[DESC_bLength]) {
|
||||||
|
switch (p[DESC_bDescriptorType]) {
|
||||||
|
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||||
|
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||||
|
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
|
||||||
|
break;
|
||||||
|
case CDC_CS_INTERFACE:
|
||||||
|
if ((cur_iface == cdc_ncm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
||||||
|
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
|
||||||
|
mac_str_idx = desc->iMACAddress;
|
||||||
|
cdc_ncm_class->max_segment_size = desc->wMaxSegmentSize;
|
||||||
|
goto get_mac;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* skip to next descriptor */
|
||||||
|
p += p[DESC_bLength];
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mac:
|
||||||
|
if (mac_str_idx == 0xff) {
|
||||||
|
USB_LOG_ERR("Do not find cdc ncm mac string\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(mac_buffer, 0, 12);
|
||||||
|
ret = usbh_get_string_desc(cdc_ncm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < 12; i += 2, j++) {
|
||||||
|
char byte_str[3];
|
||||||
|
byte_str[0] = mac_buffer[i];
|
||||||
|
byte_str[1] = mac_buffer[i + 1];
|
||||||
|
byte_str[2] = '\0';
|
||||||
|
|
||||||
|
uint32_t byte = strtoul(byte_str, NULL, 16);
|
||||||
|
cdc_ncm_class->mac[j] = (unsigned char)byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("CDC NCM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||||
|
cdc_ncm_class->mac[0],
|
||||||
|
cdc_ncm_class->mac[1],
|
||||||
|
cdc_ncm_class->mac[2],
|
||||||
|
cdc_ncm_class->mac[3],
|
||||||
|
cdc_ncm_class->mac[4],
|
||||||
|
cdc_ncm_class->mac[5]);
|
||||||
|
|
||||||
|
if (cdc_ncm_class->max_segment_size > CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE) {
|
||||||
|
USB_LOG_ERR("CDC NCM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE, cdc_ncm_class->max_segment_size);
|
||||||
|
} else {
|
||||||
|
USB_LOG_INFO("CDC NCM Max Segment Size:%u\r\n", cdc_ncm_class->max_segment_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbh_cdc_ncm_get_ntb_parameters(cdc_ncm_class, &cdc_ncm_class->ntb_param);
|
||||||
|
print_ntb_parameters(&cdc_ncm_class->ntb_param);
|
||||||
|
|
||||||
|
/* enable int ep */
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||||
|
USBH_EP_INIT(cdc_ncm_class->intin, ep_desc);
|
||||||
|
|
||||||
|
if (hport->config.intf[intf + 1].altsetting_num > 1) {
|
||||||
|
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
|
||||||
|
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("Select cdc ncm altsetting: %d\r\n", altsetting);
|
||||||
|
usbh_set_interface(cdc_ncm_class->hport, cdc_ncm_class->data_intf, altsetting);
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||||
|
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
usbh_cdc_ncm_run(cdc_ncm_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (cdc_ncm_class) {
|
||||||
|
if (cdc_ncm_class->bulkin) {
|
||||||
|
usbh_kill_urb(&cdc_ncm_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdc_ncm_class->bulkout) {
|
||||||
|
usbh_kill_urb(&cdc_ncm_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdc_ncm_class->intin) {
|
||||||
|
usbh_kill_urb(&cdc_ncm_class->intin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_cdc_ncm_stop(cdc_ncm_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_cdc_ncm_rx_thread(void *argument)
|
||||||
|
{
|
||||||
|
uint32_t g_cdc_ncm_rx_length;
|
||||||
|
int ret;
|
||||||
|
err_t err;
|
||||||
|
struct pbuf *p;
|
||||||
|
struct netif *netif = (struct netif *)argument;
|
||||||
|
|
||||||
|
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
|
||||||
|
// clang-format off
|
||||||
|
find_class:
|
||||||
|
// clang-format on
|
||||||
|
g_cdc_ncm_class.connect_status = false;
|
||||||
|
if (usbh_find_class_instance("/dev/cdc_ncm") == NULL) {
|
||||||
|
goto delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g_cdc_ncm_class.connect_status == false) {
|
||||||
|
ret = usbh_cdc_ncm_get_connect_status(&g_cdc_ncm_class);
|
||||||
|
if (ret < 0) {
|
||||||
|
usb_osal_msleep(100);
|
||||||
|
goto find_class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cdc_ncm_rx_length = 0;
|
||||||
|
while (1) {
|
||||||
|
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkin_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkin, &g_cdc_ncm_rx_buffer[g_cdc_ncm_rx_length], USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto find_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cdc_ncm_rx_length += g_cdc_ncm_class.bulkin_urb.actual_length;
|
||||||
|
|
||||||
|
if (g_cdc_ncm_class.bulkin_urb.actual_length != USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) {
|
||||||
|
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length);
|
||||||
|
|
||||||
|
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0];
|
||||||
|
if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) ||
|
||||||
|
(nth16->wHeaderLength != 12) ||
|
||||||
|
(nth16->wBlockLength != g_cdc_ncm_rx_length)) {
|
||||||
|
USB_LOG_ERR("invalid rx nth16\r\n");
|
||||||
|
g_cdc_ncm_rx_length = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex];
|
||||||
|
if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) {
|
||||||
|
USB_LOG_ERR("invalid rx ndp16\r\n");
|
||||||
|
g_cdc_ncm_rx_length = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t datagram_num = (ndp16->wLength - 8) / 4;
|
||||||
|
|
||||||
|
USB_LOG_DBG("datagram num:%02x\r\n", datagram_num);
|
||||||
|
for (uint16_t i = 0; i < datagram_num; i++) {
|
||||||
|
struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i];
|
||||||
|
if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
|
||||||
|
USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, ndp16_datagram->wDatagramLength, PBUF_POOL);
|
||||||
|
if (p != NULL) {
|
||||||
|
memcpy(p->payload, (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex], ndp16_datagram->wDatagramLength);
|
||||||
|
|
||||||
|
err = netif->input(p, netif);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
USB_LOG_ERR("No memory to alloc pbuf for cdc ncm rx\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cdc_ncm_rx_length = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
delete:
|
||||||
|
USB_LOG_INFO("Delete cdc ncm rx thread\r\n");
|
||||||
|
usb_osal_thread_delete(NULL);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct pbuf *q;
|
||||||
|
uint8_t *buffer;
|
||||||
|
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
|
||||||
|
|
||||||
|
if (g_cdc_ncm_class.connect_status == false) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
|
||||||
|
|
||||||
|
nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
|
||||||
|
nth16->wHeaderLength = 12;
|
||||||
|
nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
|
||||||
|
nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(p->tot_len, 4);
|
||||||
|
nth16->wNdpIndex = 16 + USB_ALIGN_UP(p->tot_len, 4);
|
||||||
|
|
||||||
|
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex];
|
||||||
|
|
||||||
|
ndp16->dwSignature = CDC_NCM_NDP16_SIGNATURE_NCM0;
|
||||||
|
ndp16->wLength = 16;
|
||||||
|
ndp16->wNextNdpIndex = 0;
|
||||||
|
|
||||||
|
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
|
||||||
|
ndp16_datagram->wDatagramIndex = 16;
|
||||||
|
ndp16_datagram->wDatagramLength = p->tot_len;
|
||||||
|
|
||||||
|
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
|
||||||
|
ndp16_datagram->wDatagramIndex = 0;
|
||||||
|
ndp16_datagram->wDatagramLength = 0;
|
||||||
|
|
||||||
|
buffer = &g_cdc_ncm_tx_buffer[16];
|
||||||
|
|
||||||
|
for (q = p; q != NULL; q = q->next) {
|
||||||
|
memcpy(buffer, q->payload, q->len);
|
||||||
|
buffer += q->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver cdc_ncm_class_driver = {
|
||||||
|
.driver_name = "cdc_ncm",
|
||||||
|
.connect = usbh_cdc_ncm_connect,
|
||||||
|
.disconnect = usbh_cdc_ncm_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||||
|
.class = USB_DEVICE_CLASS_CDC,
|
||||||
|
.subclass = CDC_NETWORK_CONTROL_MODEL,
|
||||||
|
.protocol = CDC_COMMON_PROTOCOL_NONE,
|
||||||
|
.vid = 0x00,
|
||||||
|
.pid = 0x00,
|
||||||
|
.class_driver = &cdc_ncm_class_driver
|
||||||
|
};
|
||||||
57
class/cdc/usbh_cdc_ncm.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_CDC_NCM_H
|
||||||
|
#define USBH_CDC_NCM_H
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
|
struct usbh_cdc_ncm {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
|
||||||
|
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
|
||||||
|
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
|
||||||
|
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
|
||||||
|
|
||||||
|
uint8_t ctrl_intf; /* Control interface number */
|
||||||
|
uint8_t data_intf; /* Data interface number */
|
||||||
|
uint8_t minor;
|
||||||
|
|
||||||
|
struct cdc_ncm_ntb_parameters ntb_param;
|
||||||
|
uint16_t bulkin_sequence;
|
||||||
|
uint16_t bulkout_sequence;
|
||||||
|
|
||||||
|
uint8_t mac[6];
|
||||||
|
bool connect_status;
|
||||||
|
uint16_t max_segment_size;
|
||||||
|
uint32_t speed[2];
|
||||||
|
|
||||||
|
ip_addr_t ipaddr;
|
||||||
|
ip_addr_t netmask;
|
||||||
|
ip_addr_t gateway;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||||
|
|
||||||
|
void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||||
|
void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||||
|
|
||||||
|
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p);
|
||||||
|
void usbh_cdc_ncm_rx_thread(void *argument);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_CDC_NCM_H */
|
||||||
@@ -428,7 +428,7 @@ void dfu_request_abort(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("DFU Class request: "
|
USB_LOG_DBG("DFU Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -464,7 +464,7 @@ static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, u
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dfu_notify_handler(uint8_t event, void *arg)
|
static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_hid.h"
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
static int hid_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("HID Class request: "
|
USB_LOG_DBG("HID Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -17,27 +17,27 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
|
|||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case HID_REQUEST_GET_REPORT:
|
case HID_REQUEST_GET_REPORT:
|
||||||
/* report id ,report type */
|
/* report id ,report type */
|
||||||
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
usbd_hid_get_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
|
||||||
break;
|
break;
|
||||||
case HID_REQUEST_GET_IDLE:
|
case HID_REQUEST_GET_IDLE:
|
||||||
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
|
(*data)[0] = usbd_hid_get_idle(busid, intf_num, LO_BYTE(setup->wValue));
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
case HID_REQUEST_GET_PROTOCOL:
|
case HID_REQUEST_GET_PROTOCOL:
|
||||||
(*data)[0] = usbd_hid_get_protocol(intf_num);
|
(*data)[0] = usbd_hid_get_protocol(busid, intf_num);
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
case HID_REQUEST_SET_REPORT:
|
case HID_REQUEST_SET_REPORT:
|
||||||
/* report id ,report type, report, report len */
|
/* report id ,report type, report, report len */
|
||||||
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
usbd_hid_set_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
|
||||||
break;
|
break;
|
||||||
case HID_REQUEST_SET_IDLE:
|
case HID_REQUEST_SET_IDLE:
|
||||||
/* report id, duration */
|
/* report id, duration */
|
||||||
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
usbd_hid_set_idle(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
|
||||||
break;
|
break;
|
||||||
case HID_REQUEST_SET_PROTOCOL:
|
case HID_REQUEST_SET_PROTOCOL:
|
||||||
/* protocol */
|
/* protocol */
|
||||||
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
|
usbd_hid_set_protocol(busid, intf_num, LO_BYTE(setup->wValue));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -48,7 +48,7 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
|
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
|
||||||
{
|
{
|
||||||
intf->class_interface_handler = hid_class_interface_request_handler;
|
intf->class_interface_handler = hid_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
@@ -60,30 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
|
|||||||
return intf;
|
return intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_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 busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
(*data[0]) = 0;
|
(*data[0]) = 0;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id)
|
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
|
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__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 usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
|
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
|
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -13,19 +13,19 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init hid interface driver */
|
/* Init hid interface driver */
|
||||||
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
|
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
|
||||||
|
|
||||||
/* Register desc api */
|
/* Register desc api */
|
||||||
void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
|
void usbd_hid_descriptor_register(uint8_t busid, 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);
|
void usbd_hid_report_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
|
||||||
|
|
||||||
/* Setup request command callback api */
|
/* Setup request command callback api */
|
||||||
void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
void usbd_hid_get_report(uint8_t busid, 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_idle(uint8_t busid, uint8_t intf, uint8_t report_id);
|
||||||
uint8_t usbd_hid_get_protocol(uint8_t intf);
|
uint8_t usbd_hid_get_protocol(uint8_t busid, 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_report(uint8_t busid, 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_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration);
|
||||||
void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol);
|
void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_hid.h"
|
#include "usbh_hid.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_hid"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/input%d"
|
#define DEV_FORMAT "/dev/input%d"
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
||||||
|
|||||||
@@ -6,24 +6,21 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_hub.h"
|
#include "usbh_hub.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/hub%d"
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_hub"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/hub%d"
|
||||||
|
|
||||||
#define HUB_DEBOUNCE_TIMEOUT 1500
|
#define HUB_DEBOUNCE_TIMEOUT 1500
|
||||||
#define HUB_DEBOUNCE_STEP 25
|
#define HUB_DEBOUNCE_STEP 25
|
||||||
#define HUB_DEBOUNCE_STABLE 100
|
#define HUB_DEBOUNCE_STABLE 100
|
||||||
#define DELAY_TIME_AFTER_RESET 200
|
#define DELAY_TIME_AFTER_RESET 200
|
||||||
|
|
||||||
#define EXTHUB_FIRST_INDEX 2
|
#define EXTHUB_FIRST_INDEX 2
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][USB_ALIGN_UP(1, CONFIG_USB_ALIGN_SIZE)];
|
||||||
|
|
||||||
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
|
|
||||||
|
|
||||||
usb_osal_thread_t hub_thread;
|
|
||||||
usb_osal_mq_t hub_mq;
|
|
||||||
|
|
||||||
struct usbh_hub roothub;
|
|
||||||
|
|
||||||
extern int usbh_free_devaddr(struct usbh_hubport *hport);
|
extern int usbh_free_devaddr(struct usbh_hubport *hport);
|
||||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||||
@@ -67,17 +64,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void usbh_hub_register(struct usbh_hub *hub)
|
|
||||||
{
|
|
||||||
usb_slist_add_tail(&hub_class_head, &hub->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||||
static void usbh_hub_unregister(struct usbh_hub *hub)
|
|
||||||
{
|
|
||||||
usb_slist_remove(&hub_class_head, &hub->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
struct usb_setup_packet *setup;
|
struct usb_setup_packet *setup;
|
||||||
@@ -100,7 +87,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
|||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -144,11 +131,11 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h
|
|||||||
setup->wIndex = port;
|
setup->wIndex = port;
|
||||||
setup->wLength = 4;
|
setup->wLength = 4;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(port_status, g_hub_buf, 4);
|
memcpy(port_status, g_hub_buf[hub->bus->busid], 4);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +220,7 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
|
|||||||
setup->wValue = 0;
|
setup->wValue = 0;
|
||||||
setup->wIndex = port;
|
setup->wIndex = port;
|
||||||
setup->wLength = 4;
|
setup->wLength = 4;
|
||||||
return usbh_roothub_control(&roothub_setup, (uint8_t *)port_status);
|
return usbh_roothub_control(hub->bus, &roothub_setup, (uint8_t *)port_status);
|
||||||
} else {
|
} else {
|
||||||
return _usbh_hub_get_portstatus(hub, port, port_status);
|
return _usbh_hub_get_portstatus(hub, port, port_status);
|
||||||
}
|
}
|
||||||
@@ -251,7 +238,7 @@ int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
|||||||
setup->wValue = feature;
|
setup->wValue = feature;
|
||||||
setup->wIndex = port;
|
setup->wIndex = port;
|
||||||
setup->wLength = 0;
|
setup->wLength = 0;
|
||||||
return usbh_roothub_control(setup, NULL);
|
return usbh_roothub_control(hub->bus, setup, NULL);
|
||||||
} else {
|
} else {
|
||||||
return _usbh_hub_set_feature(hub, port, feature);
|
return _usbh_hub_set_feature(hub, port, feature);
|
||||||
}
|
}
|
||||||
@@ -269,7 +256,7 @@ int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
|||||||
setup->wValue = feature;
|
setup->wValue = feature;
|
||||||
setup->wIndex = port;
|
setup->wIndex = port;
|
||||||
setup->wLength = 0;
|
setup->wLength = 0;
|
||||||
return usbh_roothub_control(setup, NULL);
|
return usbh_roothub_control(hub->bus, setup, NULL);
|
||||||
} else {
|
} else {
|
||||||
return _usbh_hub_clear_feature(hub, port, feature);
|
return _usbh_hub_clear_feature(hub, port, feature);
|
||||||
}
|
}
|
||||||
@@ -287,17 +274,12 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
|||||||
setup->wValue = depth;
|
setup->wValue = depth;
|
||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = 0;
|
setup->wLength = 0;
|
||||||
return usbh_roothub_control(setup, NULL);
|
return usbh_roothub_control(hub->bus, setup, NULL);
|
||||||
} else {
|
} else {
|
||||||
return _usbh_hub_set_depth(hub, depth);
|
return _usbh_hub_set_depth(hub, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
|
||||||
{
|
|
||||||
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||||
{
|
{
|
||||||
if (child->connected) {
|
if (child->connected) {
|
||||||
@@ -321,9 +303,22 @@ static void hub_int_complete_callback(void *arg, int nbytes)
|
|||||||
|
|
||||||
if (nbytes > 0) {
|
if (nbytes > 0) {
|
||||||
usbh_hub_thread_wakeup(hub);
|
usbh_hub_thread_wakeup(hub);
|
||||||
|
} else if (nbytes == -USB_ERR_NAK) {
|
||||||
|
/* Restart timer to submit urb again */
|
||||||
|
USB_LOG_DBG("Restart timer\r\n");
|
||||||
|
usb_osal_timer_start(hub->int_timer);
|
||||||
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hub_int_timeout(void *arg)
|
||||||
|
{
|
||||||
|
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||||
|
|
||||||
|
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||||
|
usbh_submit_urb(&hub->intin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
struct usb_endpoint_descriptor *ep_desc;
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
@@ -338,6 +333,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
|
|
||||||
hub->hub_addr = hport->dev_addr;
|
hub->hub_addr = hport->dev_addr;
|
||||||
hub->parent = hport;
|
hub->parent = hport;
|
||||||
|
hub->bus = hport->bus;
|
||||||
|
|
||||||
hport->config.intf[intf].priv = hub;
|
hport->config.intf[intf].priv = hub;
|
||||||
|
|
||||||
@@ -351,6 +347,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
hub->child[port].port = port + 1;
|
hub->child[port].port = port + 1;
|
||||||
hub->child[port].parent = hub;
|
hub->child[port].parent = hub;
|
||||||
|
hub->child[port].bus = hport->bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||||
@@ -391,12 +388,15 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
|
|
||||||
hub->connected = true;
|
hub->connected = true;
|
||||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
|
||||||
usbh_hub_register(hub);
|
|
||||||
|
usb_slist_add_tail(&hub->bus->hub_list, &hub->list);
|
||||||
|
|
||||||
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
hub->int_buffer = g_hub_intbuf[hub->index - 1];
|
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
|
||||||
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
|
||||||
usbh_submit_urb(&hub->intin_urb);
|
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
|
||||||
|
usb_osal_timer_start(hub->int_timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,6 +412,8 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
usbh_kill_urb(&hub->intin_urb);
|
usbh_kill_urb(&hub->intin_urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb_osal_timer_delete(hub->int_timer);
|
||||||
|
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
child = &hub->child[port];
|
child = &hub->child[port];
|
||||||
usbh_hubport_release(child);
|
usbh_hubport_release(child);
|
||||||
@@ -420,7 +422,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
|
|
||||||
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);
|
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
usbh_hub_unregister(hub);
|
usb_slist_remove(&hub->bus->hub_list, &hub->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
usbh_hub_class_free(hub);
|
usbh_hub_class_free(hub);
|
||||||
@@ -458,7 +460,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
}
|
}
|
||||||
|
|
||||||
portchange_index = hub->int_buffer[0];
|
portchange_index = hub->int_buffer[0];
|
||||||
hub->int_buffer[0] = 0;
|
hub->int_buffer[0] &= ~portchange_index;
|
||||||
|
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
||||||
@@ -599,9 +601,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
child->connected = true;
|
child->connected = true;
|
||||||
child->port = port + 1;
|
child->port = port + 1;
|
||||||
child->speed = speed;
|
child->speed = speed;
|
||||||
|
child->bus = hub->bus;
|
||||||
child->mutex = usb_osal_mutex_create();
|
child->mutex = usb_osal_mutex_create();
|
||||||
|
|
||||||
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
|
USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
|
||||||
|
|
||||||
/* create disposable thread to enumerate device on current hport, do not block hub thread */
|
/* create disposable thread to enumerate device on current hport, do not block hub thread */
|
||||||
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
||||||
@@ -619,14 +622,14 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
child = &hub->child[port];
|
child = &hub->child[port];
|
||||||
/** release child sources */
|
/** release child sources */
|
||||||
usbh_hubport_release(child);
|
usbh_hubport_release(child);
|
||||||
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
|
USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hub->bus->busid, hub->index, port + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start next hub int transfer */
|
/* Start next hub int transfer */
|
||||||
if (!hub->is_roothub && hub->connected) {
|
if (!hub->is_roothub && hub->connected) {
|
||||||
usbh_submit_urb(&hub->intin_urb);
|
usb_osal_timer_start(hub->int_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,9 +638,11 @@ static void usbh_hub_thread(void *argument)
|
|||||||
struct usbh_hub *hub;
|
struct usbh_hub *hub;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
usb_hc_init();
|
struct usbh_bus *bus = (struct usbh_bus *)argument;
|
||||||
|
|
||||||
|
usb_hc_init(bus);
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
|
ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -645,55 +650,41 @@ static void usbh_hub_thread(void *argument)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbh_roothub_register(void)
|
void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||||
{
|
{
|
||||||
usb_slist_init(&hub_class_head);
|
usb_osal_mq_send(hub->bus->hub_mq, (uintptr_t)hub);
|
||||||
|
|
||||||
memset(&roothub, 0, sizeof(struct usbh_hub));
|
|
||||||
|
|
||||||
roothub.connected = true;
|
|
||||||
roothub.index = 1;
|
|
||||||
roothub.is_roothub = true;
|
|
||||||
roothub.parent = NULL;
|
|
||||||
roothub.hub_addr = 1;
|
|
||||||
roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
|
|
||||||
usbh_hub_register(&roothub);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbh_roothub_thread_wakeup(uint8_t port)
|
int usbh_hub_initialize(struct usbh_bus *bus)
|
||||||
{
|
{
|
||||||
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
|
char thread_name[32] = { 0 };
|
||||||
roothub.int_buffer[0] |= (1 << port);
|
|
||||||
usbh_hub_thread_wakeup(&roothub);
|
|
||||||
}
|
|
||||||
|
|
||||||
int usbh_hub_initialize(void)
|
bus->hub_mq = usb_osal_mq_create(7);
|
||||||
{
|
if (bus->hub_mq == NULL) {
|
||||||
usbh_roothub_register();
|
USB_LOG_ERR("Failed to create hub mq\r\n");
|
||||||
|
|
||||||
hub_mq = usb_osal_mq_create(7);
|
|
||||||
if (hub_mq == NULL) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hub_thread = usb_osal_thread_create("usbh_hub", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, NULL);
|
snprintf(thread_name, 32, "usbh_hub%u", bus->busid);
|
||||||
if (hub_thread == NULL) {
|
bus->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, bus);
|
||||||
|
if (bus->hub_thread == NULL) {
|
||||||
|
USB_LOG_ERR("Failed to create hub thread\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_hub_deinitialize(void)
|
int usbh_hub_deinitialize(struct usbh_bus *bus)
|
||||||
{
|
{
|
||||||
usb_slist_t *i;
|
usb_slist_t *hub_list;
|
||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
size_t flags;
|
size_t flags;
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
usb_slist_for_each(i, &hub_class_head)
|
usb_slist_for_each(hub_list, &bus->hub_list)
|
||||||
{
|
{
|
||||||
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
|
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||||
|
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
hport = &hub->child[port];
|
hport = &hub->child[port];
|
||||||
@@ -702,12 +693,12 @@ int usbh_hub_deinitialize(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_hc_deinit();
|
usb_hc_deinit(bus);
|
||||||
|
|
||||||
usb_osal_leave_critical_section(flags);
|
usb_osal_leave_critical_section(flags);
|
||||||
|
|
||||||
usb_osal_mq_delete(hub_mq);
|
usb_osal_mq_delete(bus->hub_mq);
|
||||||
usb_osal_thread_delete(hub_thread);
|
usb_osal_thread_delete(bus->hub_thread);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,12 @@
|
|||||||
|
|
||||||
#include "usb_hub.h"
|
#include "usb_hub.h"
|
||||||
|
|
||||||
|
struct usbh_hub;
|
||||||
|
|
||||||
#define USBH_HUB_MAX_PORTS 4
|
#define USBH_HUB_MAX_PORTS 4
|
||||||
/* Maximum size of an interrupt IN transfer */
|
/* Maximum size of an interrupt IN transfer */
|
||||||
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
||||||
|
|
||||||
extern usb_slist_t hub_class_head;
|
|
||||||
extern struct usbh_hub roothub;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -22,10 +21,10 @@ extern "C" {
|
|||||||
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||||
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||||
|
|
||||||
void usbh_roothub_thread_wakeup(uint8_t port);
|
void usbh_hub_thread_wakeup(struct usbh_hub *hub);
|
||||||
|
|
||||||
int usbh_hub_initialize(void);
|
int usbh_hub_initialize(struct usbh_bus *bus);
|
||||||
int usbh_hub_deinitialize(void);
|
int usbh_hub_deinitialize(struct usbh_bus *bus);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, sakumisu
|
* Copyright (c) 2022, sakumisu
|
||||||
|
* Copyright (c) 2024, zhihong chen
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -13,16 +14,16 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init msc interface driver */
|
/* Init msc interface driver */
|
||||||
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf,
|
struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||||
const uint8_t out_ep,
|
const uint8_t out_ep,
|
||||||
const uint8_t in_ep);
|
const uint8_t in_ep);
|
||||||
|
|
||||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
|
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size);
|
||||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
|
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
|
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||||
|
|
||||||
void usbd_msc_set_readonly(bool readonly);
|
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
|
||||||
bool usbd_msc_set_popup(void);
|
bool usbd_msc_set_popup(uint8_t busid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,13 @@
|
|||||||
#include "usbh_msc.h"
|
#include "usbh_msc.h"
|
||||||
#include "usb_scsi.h"
|
#include "usb_scsi.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_msc"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/sd%c"
|
#define DEV_FORMAT "/dev/sd%c"
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[64];
|
||||||
|
|
||||||
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
static uint32_t g_devinuse = 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_xxx.h"
|
#include "usbd_xxx.h"
|
||||||
|
|
||||||
static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int xxx_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_WRN("XXX Class request: "
|
USB_LOG_WRN("XXX Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -16,7 +16,7 @@ static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, u
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xxx_notify_handler(uint8_t event, void *arg)
|
static void xxx_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -28,7 +28,7 @@ static void xxx_notify_handler(uint8_t event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf)
|
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf)
|
||||||
{
|
{
|
||||||
intf->class_interface_handler = xxx_class_interface_request_handler;
|
intf->class_interface_handler = xxx_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf);
|
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
797
class/vendor/net/usbh_asix.c
vendored
Normal file
@@ -0,0 +1,797 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_asix.h"
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "asix"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/asix"
|
||||||
|
|
||||||
|
static struct usbh_asix g_asix_class;
|
||||||
|
#define CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE (1514U + 8)
|
||||||
|
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32];
|
||||||
|
|
||||||
|
#define ETH_ALEN 6
|
||||||
|
|
||||||
|
#define PHY_MODE_MARVELL 0x0000
|
||||||
|
#define MII_MARVELL_LED_CTRL 0x0018
|
||||||
|
#define MII_MARVELL_STATUS 0x001b
|
||||||
|
#define MII_MARVELL_CTRL 0x0014
|
||||||
|
|
||||||
|
#define MARVELL_LED_MANUAL 0x0019
|
||||||
|
|
||||||
|
#define MARVELL_STATUS_HWCFG 0x0004
|
||||||
|
|
||||||
|
#define MARVELL_CTRL_TXDELAY 0x0002
|
||||||
|
#define MARVELL_CTRL_RXDELAY 0x0080
|
||||||
|
|
||||||
|
#define PHY_MODE_RTL8211CL 0x000C
|
||||||
|
|
||||||
|
#define AX88772A_PHY14H 0x14
|
||||||
|
#define AX88772A_PHY14H_DEFAULT 0x442C
|
||||||
|
|
||||||
|
#define AX88772A_PHY15H 0x15
|
||||||
|
#define AX88772A_PHY15H_DEFAULT 0x03C8
|
||||||
|
|
||||||
|
#define AX88772A_PHY16H 0x16
|
||||||
|
#define AX88772A_PHY16H_DEFAULT 0x4044
|
||||||
|
|
||||||
|
#define SPEED_100 0
|
||||||
|
#define SPEED_10 1
|
||||||
|
|
||||||
|
static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint16_t value,
|
||||||
|
uint16_t index,
|
||||||
|
void *data,
|
||||||
|
uint16_t size)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = asix_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = cmd;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = index;
|
||||||
|
setup->wLength = size;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
memcpy(data, g_asix_buf, ret - 8);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint16_t value,
|
||||||
|
uint16_t index,
|
||||||
|
void *data,
|
||||||
|
uint16_t size)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = asix_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = cmd;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = index;
|
||||||
|
setup->wLength = size;
|
||||||
|
|
||||||
|
memcpy(g_asix_buf, data, size);
|
||||||
|
|
||||||
|
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val)
|
||||||
|
{
|
||||||
|
uint8_t smsr;
|
||||||
|
uint16_t res = (uint16_t)val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 10; i++) {
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
usb_osal_msleep(1);
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smsr & AX_HOST_EN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MII_REG, phy_id, loc, &res, 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_mdio_read(struct usbh_asix *asix_class, int phy_id, int loc)
|
||||||
|
{
|
||||||
|
uint8_t smsr;
|
||||||
|
uint16_t res;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 10; i++) {
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
usb_osal_msleep(1);
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smsr & AX_HOST_EN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MII_REG, phy_id, loc, &res, 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_read_phy_addr(struct usbh_asix *asix_class, bool internal)
|
||||||
|
{
|
||||||
|
int ret, offset;
|
||||||
|
uint8_t buf[2];
|
||||||
|
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_PHY_ID, 0, 0, buf, 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (internal ? 1 : 0);
|
||||||
|
ret = buf[offset];
|
||||||
|
|
||||||
|
USB_LOG_INFO("%s PHY address 0x%x\r\n", internal ? "internal" : "external", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_sw_reset(struct usbh_asix *asix_class, uint8_t flags)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_RESET, flags, 0, NULL, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
USB_LOG_ERR("Failed to send software reset: %d\r\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t usbh_asix_read_rx_ctl(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
uint16_t v;
|
||||||
|
int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_RX_CTL, 0, 0, &v, 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_write_rx_ctl(struct usbh_asix *asix_class, uint16_t mode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
USB_LOG_DBG("asix_write_rx_ctl() - mode = 0x%04x\r\n", mode);
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, mode, 0, NULL, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
USB_LOG_ERR("Failed to write RX_CTL mode to 0x%04x: %02x\r\n",
|
||||||
|
mode, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t usbh_asix_read_medium_status(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
uint16_t v;
|
||||||
|
int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MEDIUM_STATUS, 0, 0, &v, 2);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Error reading Medium Status register: %02x\r\n",
|
||||||
|
ret);
|
||||||
|
return ret; /* TODO: callers not checking for error ret */
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_write_medium_mode(struct usbh_asix *asix_class, uint16_t mode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
USB_LOG_DBG("asix_write_medium_mode() - mode = 0x%04x\r\n", mode);
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, NULL, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
USB_LOG_ERR("Failed to write Medium Mode mode to 0x%04x: %02x\r\n",
|
||||||
|
mode, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, int sleep)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
USB_LOG_DBG("asix_write_gpio() - value = 0x%04x\r\n", value);
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_GPIOS, value, 0, NULL, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
USB_LOG_ERR("Failed to write GPIO value 0x%04x: %d\r\n",
|
||||||
|
value, ret);
|
||||||
|
|
||||||
|
if (sleep)
|
||||||
|
usb_osal_msleep(sleep);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AX88772 & AX88178 have a 16-bit RX_CTL value
|
||||||
|
*/
|
||||||
|
static void usbh_asix_set_multicast(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM;
|
||||||
|
const uint8_t multi_filter[] = { 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40 };
|
||||||
|
|
||||||
|
usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MULTI_FILTER, 0, 0, (uint8_t *)multi_filter, AX_MCAST_FILTER_SIZE);
|
||||||
|
usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ax88772_hw_reset(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
uint16_t rx_ctl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy,
|
||||||
|
0, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asix_class->embd_phy) {
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
usb_osal_msleep(10);
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
usb_osal_msleep(60);
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL | AX_SWRESET_PRL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_PRL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_msleep(150);
|
||||||
|
|
||||||
|
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
|
||||||
|
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
|
||||||
|
AX88772_IPG2_DEFAULT, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewrite MAC address */
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
|
||||||
|
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rx_ctl = usbh_asix_read_rx_ctl(asix_class);
|
||||||
|
USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n",
|
||||||
|
rx_ctl);
|
||||||
|
|
||||||
|
rx_ctl = usbh_asix_read_medium_status(asix_class);
|
||||||
|
USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n",
|
||||||
|
rx_ctl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
uint16_t rx_ctl, phy14h, phy15h, phy16h;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE, 5);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, 0, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
usb_osal_msleep(10);
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_IPRL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
usb_osal_msleep(10);
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
usb_osal_msleep(160);
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
usb_osal_msleep(200);
|
||||||
|
|
||||||
|
if (asix_class->chipcode == AX_AX88772B_CHIPCODE) {
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_QCTCTRL, 0x8000, 0x8001, NULL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Write BQ setting failed: %d\r\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else if (asix_class->chipcode == AX_AX88772A_CHIPCODE) {
|
||||||
|
/* Check if the PHY registers have default settings */
|
||||||
|
phy14h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY14H);
|
||||||
|
phy15h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY15H);
|
||||||
|
phy16h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY16H);
|
||||||
|
|
||||||
|
USB_LOG_DBG("772a_hw_reset: MR20=0x%x MR21=0x%x MR22=0x%x\r\n",
|
||||||
|
phy14h, phy15h, phy16h);
|
||||||
|
|
||||||
|
/* Restore PHY registers default setting if not */
|
||||||
|
if (phy14h != AX88772A_PHY14H_DEFAULT)
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY14H,
|
||||||
|
AX88772A_PHY14H_DEFAULT);
|
||||||
|
if (phy15h != AX88772A_PHY15H_DEFAULT)
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY15H,
|
||||||
|
AX88772A_PHY15H_DEFAULT);
|
||||||
|
if (phy16h != AX88772A_PHY16H_DEFAULT)
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
|
||||||
|
AX88772A_PHY16H,
|
||||||
|
AX88772A_PHY16H_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
|
||||||
|
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
|
||||||
|
AX88772_IPG2_DEFAULT, 0, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewrite MAC address */
|
||||||
|
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
|
||||||
|
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
|
||||||
|
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rx_ctl = usbh_asix_read_rx_ctl(asix_class);
|
||||||
|
USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", rx_ctl);
|
||||||
|
|
||||||
|
rx_ctl = usbh_asix_read_medium_status(asix_class);
|
||||||
|
USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", rx_ctl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_ax88772_mac_link_down(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
usbh_asix_write_medium_mode(asix_class, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_ax88772_mac_link_up(struct usbh_asix *asix_class, int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||||
|
{
|
||||||
|
uint16_t m = AX_MEDIUM_AC | AX_MEDIUM_RE;
|
||||||
|
|
||||||
|
m |= duplex ? AX_MEDIUM_FD : 0;
|
||||||
|
|
||||||
|
switch (speed) {
|
||||||
|
case SPEED_100:
|
||||||
|
m |= AX_MEDIUM_PS;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx_pause)
|
||||||
|
m |= AX_MEDIUM_TFC;
|
||||||
|
|
||||||
|
if (rx_pause)
|
||||||
|
m |= AX_MEDIUM_RFC;
|
||||||
|
|
||||||
|
usbh_asix_write_medium_mode(asix_class, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
struct usbh_asix *asix_class = &g_asix_class;
|
||||||
|
|
||||||
|
memset(asix_class, 0, sizeof(struct usbh_asix));
|
||||||
|
|
||||||
|
asix_class->hport = hport;
|
||||||
|
asix_class->intf = intf;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = asix_class;
|
||||||
|
|
||||||
|
if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x772b)) {
|
||||||
|
asix_class->name = "ASIX AX88772B";
|
||||||
|
} else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x7720)) {
|
||||||
|
asix_class->name = "ASIX AX88772";
|
||||||
|
} else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x1780)) {
|
||||||
|
asix_class->name = "ASIX AX88178";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < (ETH_ALEN >> 1); i++) {
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_EEPROM,
|
||||||
|
0x04 + i, 0, &asix_class->mac[i * 2], 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("asix MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||||
|
asix_class->mac[0],
|
||||||
|
asix_class->mac[1],
|
||||||
|
asix_class->mac[2],
|
||||||
|
asix_class->mac[3],
|
||||||
|
asix_class->mac[4],
|
||||||
|
asix_class->mac[5]);
|
||||||
|
|
||||||
|
ret = usbh_asix_read_phy_addr(asix_class, true);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to read phy addr: %d\r\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
asix_class->phy_addr = ret;
|
||||||
|
asix_class->embd_phy = ((ret & 0x1f) == AX_EMBD_PHY_ADDR);
|
||||||
|
|
||||||
|
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &asix_class->chipcode, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to read STATMNGSTS_REG: %d\r\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
asix_class->chipcode &= AX_CHIPCODE_MASK;
|
||||||
|
USB_LOG_INFO("asix chipcode 0x%x\r\n", asix_class->chipcode);
|
||||||
|
|
||||||
|
if (asix_class->chipcode == AX_AX88772_CHIPCODE) {
|
||||||
|
usbh_ax88772_hw_reset(asix_class);
|
||||||
|
} else {
|
||||||
|
usbh_ax88772a_hw_reset(asix_class);
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||||
|
|
||||||
|
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(asix_class->intin, ep_desc);
|
||||||
|
} else {
|
||||||
|
return -USB_ERR_NOTSUPP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(asix_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(asix_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asix_class->chipcode == AX_AX88772B_CHIPCODE) {
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
|
||||||
|
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x8200);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
|
||||||
|
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3900);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
|
||||||
|
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3100);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 4);
|
||||||
|
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 4, 0x01e1);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 1);
|
||||||
|
|
||||||
|
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3300);
|
||||||
|
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("Init %s done\r\n", asix_class->name);
|
||||||
|
|
||||||
|
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register ASIX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_asix_run(asix_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_asix_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_asix *asix_class = (struct usbh_asix *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (asix_class) {
|
||||||
|
if (asix_class->bulkin) {
|
||||||
|
usbh_kill_urb(&asix_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asix_class->bulkout) {
|
||||||
|
usbh_kill_urb(&asix_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asix_class->intin) {
|
||||||
|
usbh_kill_urb(&asix_class->intin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister ASIX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_asix_stop(asix_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(asix_class, 0, sizeof(struct usbh_asix));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_asix_get_connect_status(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
usbh_int_urb_fill(&asix_class->intin_urb, asix_class->hport, asix_class->intin, g_asix_inttx_buffer, 8, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&asix_class->intin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_asix_inttx_buffer[1] == 0x00) {
|
||||||
|
if (g_asix_inttx_buffer[2] & 0x01) {
|
||||||
|
asix_class->connect_status = true;
|
||||||
|
usbh_ax88772_mac_link_up(asix_class, SPEED_100, 1, 1, 1);
|
||||||
|
usbh_asix_set_multicast(asix_class);
|
||||||
|
} else {
|
||||||
|
asix_class->connect_status = false;
|
||||||
|
usbh_ax88772_mac_link_down(asix_class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_asix_rx_thread(void *argument)
|
||||||
|
{
|
||||||
|
uint32_t g_asix_rx_length;
|
||||||
|
int ret;
|
||||||
|
err_t err;
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t len_crc;
|
||||||
|
struct pbuf *p;
|
||||||
|
struct netif *netif = (struct netif *)argument;
|
||||||
|
|
||||||
|
USB_LOG_INFO("Create asix rx thread\r\n");
|
||||||
|
// clang-format off
|
||||||
|
find_class:
|
||||||
|
// clang-format on
|
||||||
|
g_asix_class.connect_status = false;
|
||||||
|
if (usbh_find_class_instance("/dev/asix") == NULL) {
|
||||||
|
goto delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g_asix_class.connect_status == false) {
|
||||||
|
ret = usbh_asix_get_connect_status(&g_asix_class);
|
||||||
|
if (ret < 0) {
|
||||||
|
usb_osal_msleep(100);
|
||||||
|
goto find_class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_asix_rx_length = 0;
|
||||||
|
while (1) {
|
||||||
|
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_asix_class.bulkin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto find_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_asix_rx_length += g_asix_class.bulkin_urb.actual_length;
|
||||||
|
|
||||||
|
if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize)) {
|
||||||
|
len = ((uint16_t)g_asix_rx_buffer[0] | ((uint16_t)(g_asix_rx_buffer[1]) << 8)) & 0x7ff;
|
||||||
|
len_crc = g_asix_rx_buffer[2] | ((uint16_t)(g_asix_rx_buffer[3]) << 8);
|
||||||
|
|
||||||
|
if (len != (~len_crc & 0x7ff)) {
|
||||||
|
USB_LOG_ERR("asix rx header error\r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length);
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||||
|
if (p != NULL) {
|
||||||
|
memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
|
||||||
|
g_asix_rx_length = 0;
|
||||||
|
|
||||||
|
err = netif->input(p, netif);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_asix_rx_length = 0;
|
||||||
|
USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
delete:
|
||||||
|
USB_LOG_INFO("Delete asix rx thread\r\n");
|
||||||
|
usb_osal_thread_delete(NULL);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct pbuf *q;
|
||||||
|
uint16_t actual_len;
|
||||||
|
uint8_t *buffer = &g_asix_tx_buffer[4];
|
||||||
|
|
||||||
|
if (g_asix_class.connect_status == false) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (q = p; q != NULL; q = q->next) {
|
||||||
|
memcpy(buffer, q->payload, q->len);
|
||||||
|
buffer += q->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_asix_tx_buffer[0] = p->tot_len & 0xff;
|
||||||
|
g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff;
|
||||||
|
g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0];
|
||||||
|
g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1];
|
||||||
|
|
||||||
|
if (!(p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
|
||||||
|
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8);
|
||||||
|
g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00;
|
||||||
|
g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00;
|
||||||
|
g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff;
|
||||||
|
g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff;
|
||||||
|
actual_len = p->tot_len + 8;
|
||||||
|
} else {
|
||||||
|
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4);
|
||||||
|
actual_len = p->tot_len + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_asix_class.bulkout_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct usbh_class_driver asix_class_driver = {
|
||||||
|
.driver_name = "asix",
|
||||||
|
.connect = usbh_asix_connect,
|
||||||
|
.disconnect = usbh_asix_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info ax88772b_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0x00,
|
||||||
|
.protocol = 0x00,
|
||||||
|
.vid = 0x0B95,
|
||||||
|
.pid = 0x772B,
|
||||||
|
.class_driver = &asix_class_driver
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info ax88772_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0x00,
|
||||||
|
.protocol = 0x00,
|
||||||
|
.vid = 0x0B95,
|
||||||
|
.pid = 0x7720,
|
||||||
|
.class_driver = &asix_class_driver
|
||||||
|
};
|
||||||
180
class/vendor/net/usbh_asix.h
vendored
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_ASIX_H
|
||||||
|
#define USBH_ASIX_H
|
||||||
|
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
|
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
|
||||||
|
|
||||||
|
#define AX_CMD_SET_SW_MII 0x06
|
||||||
|
#define AX_CMD_READ_MII_REG 0x07
|
||||||
|
#define AX_CMD_WRITE_MII_REG 0x08
|
||||||
|
#define AX_CMD_STATMNGSTS_REG 0x09
|
||||||
|
#define AX_CMD_SET_HW_MII 0x0a
|
||||||
|
#define AX_CMD_READ_EEPROM 0x0b
|
||||||
|
#define AX_CMD_WRITE_EEPROM 0x0c
|
||||||
|
#define AX_CMD_WRITE_ENABLE 0x0d
|
||||||
|
#define AX_CMD_WRITE_DISABLE 0x0e
|
||||||
|
#define AX_CMD_READ_RX_CTL 0x0f
|
||||||
|
#define AX_CMD_WRITE_RX_CTL 0x10
|
||||||
|
#define AX_CMD_READ_IPG012 0x11
|
||||||
|
#define AX_CMD_WRITE_IPG0 0x12
|
||||||
|
#define AX_CMD_WRITE_IPG1 0x13
|
||||||
|
#define AX_CMD_READ_NODE_ID 0x13
|
||||||
|
#define AX_CMD_WRITE_NODE_ID 0x14
|
||||||
|
#define AX_CMD_WRITE_IPG2 0x14
|
||||||
|
#define AX_CMD_WRITE_MULTI_FILTER 0x16
|
||||||
|
#define AX88172_CMD_READ_NODE_ID 0x17
|
||||||
|
#define AX_CMD_READ_PHY_ID 0x19
|
||||||
|
#define AX_CMD_READ_MEDIUM_STATUS 0x1a
|
||||||
|
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
|
||||||
|
#define AX_CMD_READ_MONITOR_MODE 0x1c
|
||||||
|
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
|
||||||
|
#define AX_CMD_READ_GPIOS 0x1e
|
||||||
|
#define AX_CMD_WRITE_GPIOS 0x1f
|
||||||
|
#define AX_CMD_SW_RESET 0x20
|
||||||
|
#define AX_CMD_SW_PHY_STATUS 0x21
|
||||||
|
#define AX_CMD_SW_PHY_SELECT 0x22
|
||||||
|
#define AX_QCTCTRL 0x2A
|
||||||
|
|
||||||
|
#define AX_CHIPCODE_MASK 0x70
|
||||||
|
#define AX_AX88772_CHIPCODE 0x00
|
||||||
|
#define AX_AX88772A_CHIPCODE 0x10
|
||||||
|
#define AX_AX88772B_CHIPCODE 0x20
|
||||||
|
#define AX_HOST_EN 0x01
|
||||||
|
|
||||||
|
#define AX_PHYSEL_PSEL 0x01
|
||||||
|
#define AX_PHYSEL_SSMII 0
|
||||||
|
#define AX_PHYSEL_SSEN 0x10
|
||||||
|
|
||||||
|
#define AX_PHY_SELECT_MASK (BIT(3) | BIT(2))
|
||||||
|
#define AX_PHY_SELECT_INTERNAL 0
|
||||||
|
#define AX_PHY_SELECT_EXTERNAL BIT(2)
|
||||||
|
|
||||||
|
#define AX_MONITOR_MODE 0x01
|
||||||
|
#define AX_MONITOR_LINK 0x02
|
||||||
|
#define AX_MONITOR_MAGIC 0x04
|
||||||
|
#define AX_MONITOR_HSFS 0x10
|
||||||
|
|
||||||
|
/* AX88172 Medium Status Register values */
|
||||||
|
#define AX88172_MEDIUM_FD 0x02
|
||||||
|
#define AX88172_MEDIUM_TX 0x04
|
||||||
|
#define AX88172_MEDIUM_FC 0x10
|
||||||
|
#define AX88172_MEDIUM_DEFAULT \
|
||||||
|
(AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC)
|
||||||
|
|
||||||
|
#define AX_MCAST_FILTER_SIZE 8
|
||||||
|
#define AX_MAX_MCAST 64
|
||||||
|
|
||||||
|
#define AX_SWRESET_CLEAR 0x00
|
||||||
|
#define AX_SWRESET_RR 0x01
|
||||||
|
#define AX_SWRESET_RT 0x02
|
||||||
|
#define AX_SWRESET_PRTE 0x04
|
||||||
|
#define AX_SWRESET_PRL 0x08
|
||||||
|
#define AX_SWRESET_BZ 0x10
|
||||||
|
#define AX_SWRESET_IPRL 0x20
|
||||||
|
#define AX_SWRESET_IPPD 0x40
|
||||||
|
|
||||||
|
#define AX88772_IPG0_DEFAULT 0x15
|
||||||
|
#define AX88772_IPG1_DEFAULT 0x0c
|
||||||
|
#define AX88772_IPG2_DEFAULT 0x12
|
||||||
|
|
||||||
|
/* AX88772 & AX88178 Medium Mode Register */
|
||||||
|
#define AX_MEDIUM_PF 0x0080
|
||||||
|
#define AX_MEDIUM_JFE 0x0040
|
||||||
|
#define AX_MEDIUM_TFC 0x0020
|
||||||
|
#define AX_MEDIUM_RFC 0x0010
|
||||||
|
#define AX_MEDIUM_ENCK 0x0008
|
||||||
|
#define AX_MEDIUM_AC 0x0004
|
||||||
|
#define AX_MEDIUM_FD 0x0002
|
||||||
|
#define AX_MEDIUM_GM 0x0001
|
||||||
|
#define AX_MEDIUM_SM 0x1000
|
||||||
|
#define AX_MEDIUM_SBP 0x0800
|
||||||
|
#define AX_MEDIUM_PS 0x0200
|
||||||
|
#define AX_MEDIUM_RE 0x0100
|
||||||
|
|
||||||
|
#define AX88178_MEDIUM_DEFAULT \
|
||||||
|
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
|
||||||
|
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
|
||||||
|
AX_MEDIUM_RE)
|
||||||
|
|
||||||
|
#define AX88772_MEDIUM_DEFAULT \
|
||||||
|
(AX_MEDIUM_FD | AX_MEDIUM_PS | \
|
||||||
|
AX_MEDIUM_AC | AX_MEDIUM_RE)
|
||||||
|
|
||||||
|
/* AX88772 & AX88178 RX_CTL values */
|
||||||
|
#define AX_RX_CTL_SO 0x0080
|
||||||
|
#define AX_RX_CTL_AP 0x0020
|
||||||
|
#define AX_RX_CTL_AM 0x0010
|
||||||
|
#define AX_RX_CTL_AB 0x0008
|
||||||
|
#define AX_RX_CTL_SEP 0x0004
|
||||||
|
#define AX_RX_CTL_AMALL 0x0002
|
||||||
|
#define AX_RX_CTL_PRO 0x0001
|
||||||
|
#define AX_RX_CTL_MFB_2048 0x0000
|
||||||
|
#define AX_RX_CTL_MFB_4096 0x0100
|
||||||
|
#define AX_RX_CTL_MFB_8192 0x0200
|
||||||
|
#define AX_RX_CTL_MFB_16384 0x0300
|
||||||
|
|
||||||
|
#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB)
|
||||||
|
|
||||||
|
/* GPIO 0 .. 2 toggles */
|
||||||
|
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
|
||||||
|
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
|
||||||
|
#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
|
||||||
|
#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
|
||||||
|
#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
|
||||||
|
#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
|
||||||
|
#define AX_GPIO_RESERVED 0x40 /* Reserved */
|
||||||
|
#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
|
||||||
|
|
||||||
|
#define AX_EEPROM_MAGIC 0xdeadbeef
|
||||||
|
#define AX_EEPROM_LEN 0x200
|
||||||
|
|
||||||
|
#define AX_EMBD_PHY_ADDR 0x10
|
||||||
|
|
||||||
|
struct usbh_asix {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||||
|
struct usbh_urb bulkout_urb;
|
||||||
|
struct usbh_urb bulkin_urb;
|
||||||
|
struct usbh_urb intin_urb;
|
||||||
|
|
||||||
|
uint8_t intf;
|
||||||
|
char *name;
|
||||||
|
uint8_t phy_addr;
|
||||||
|
uint8_t embd_phy;
|
||||||
|
uint8_t chipcode;
|
||||||
|
uint16_t mac_capabilities;
|
||||||
|
|
||||||
|
bool connect_status;
|
||||||
|
uint8_t mac[6];
|
||||||
|
|
||||||
|
ip_addr_t ipaddr;
|
||||||
|
ip_addr_t netmask;
|
||||||
|
ip_addr_t gateway;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_asix_get_connect_status(struct usbh_asix *asix_class);
|
||||||
|
|
||||||
|
void usbh_asix_run(struct usbh_asix *asix_class);
|
||||||
|
void usbh_asix_stop(struct usbh_asix *asix_class);
|
||||||
|
|
||||||
|
void usbh_asix_rx_thread(void *argument);
|
||||||
|
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_ASIX_H */
|
||||||
2265
class/vendor/net/usbh_rtl8152.c
vendored
Normal file
71
class/vendor/net/usbh_rtl8152.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_RTL8152_H
|
||||||
|
#define USBH_RTL8152_H
|
||||||
|
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
|
struct usbh_rtl8152 {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||||
|
struct usbh_urb bulkout_urb;
|
||||||
|
struct usbh_urb bulkin_urb;
|
||||||
|
struct usbh_urb intin_urb;
|
||||||
|
|
||||||
|
uint8_t intf;
|
||||||
|
|
||||||
|
uint8_t mac[6];
|
||||||
|
bool connect_status;
|
||||||
|
uint32_t speed[2];
|
||||||
|
|
||||||
|
ip_addr_t ipaddr;
|
||||||
|
ip_addr_t netmask;
|
||||||
|
ip_addr_t gateway;
|
||||||
|
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t eee_adv;
|
||||||
|
uint8_t eee_en;
|
||||||
|
uint8_t supports_gmii;
|
||||||
|
uint16_t min_mtu;
|
||||||
|
uint16_t max_mtu;
|
||||||
|
uint16_t ocp_base;
|
||||||
|
uint32_t saved_wolopts;
|
||||||
|
uint32_t rx_buf_sz;
|
||||||
|
|
||||||
|
struct rtl_ops {
|
||||||
|
void (*init)(struct usbh_rtl8152 *tp);
|
||||||
|
int (*enable)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*disable)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*up)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*down)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*unload)(struct usbh_rtl8152 *tp);
|
||||||
|
bool (*in_nway)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*hw_phy_cfg)(struct usbh_rtl8152 *tp);
|
||||||
|
void (*autosuspend_en)(struct usbh_rtl8152 *tp, bool enable);
|
||||||
|
void (*change_mtu)(struct usbh_rtl8152 *tp);
|
||||||
|
} rtl_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_rtl8152_get_connect_status(struct usbh_rtl8152 *rtl8152_class);
|
||||||
|
|
||||||
|
void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class);
|
||||||
|
void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
|
||||||
|
|
||||||
|
void usbh_rtl8152_rx_thread(void *argument);
|
||||||
|
err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_RTL8152_H */
|
||||||
352
class/vendor/serial/usbh_ch34x.c
vendored
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_ch34x.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||||
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[64];
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
|
||||||
|
|
||||||
|
static struct usbh_ch34x g_ch34x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
|
||||||
|
{
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
|
||||||
|
if ((g_devinuse & (1 << devno)) == 0) {
|
||||||
|
g_devinuse |= (1 << devno);
|
||||||
|
memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x));
|
||||||
|
g_ch34x_class[devno].minor = devno;
|
||||||
|
return &g_ch34x_class[devno];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class)
|
||||||
|
{
|
||||||
|
int devno = ch34x_class->minor;
|
||||||
|
|
||||||
|
if (devno >= 0 && devno < 32) {
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
}
|
||||||
|
memset(ch34x_class, 0, sizeof(struct usbh_ch34x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8_t *divisor)
|
||||||
|
{
|
||||||
|
uint8_t a;
|
||||||
|
uint8_t b;
|
||||||
|
uint32_t c;
|
||||||
|
|
||||||
|
switch (baudrate) {
|
||||||
|
case 921600:
|
||||||
|
a = 0xf3;
|
||||||
|
b = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 307200:
|
||||||
|
a = 0xd9;
|
||||||
|
b = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (baudrate > 6000000 / 255) {
|
||||||
|
b = 3;
|
||||||
|
c = 6000000;
|
||||||
|
} else if (baudrate > 750000 / 255) {
|
||||||
|
b = 2;
|
||||||
|
c = 750000;
|
||||||
|
} else if (baudrate > 93750 / 255) {
|
||||||
|
b = 1;
|
||||||
|
c = 93750;
|
||||||
|
} else {
|
||||||
|
b = 0;
|
||||||
|
c = 11719;
|
||||||
|
}
|
||||||
|
a = (uint8_t)(c / baudrate);
|
||||||
|
if (a == 0 || a == 0xFF) {
|
||||||
|
return -USB_ERR_INVAL;
|
||||||
|
}
|
||||||
|
if ((c / a - baudrate) > (baudrate - c / (a + 1))) {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
a = (uint8_t)(256 - a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*factor = a;
|
||||||
|
*divisor = b;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = CH34X_READ_VERSION;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = 0;
|
||||||
|
setup->wLength = 2;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(ch34x_class->hport, setup, g_ch34x_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("Ch34x chip version %02x:%02x\r\n", g_ch34x_buf[0], g_ch34x_buf[1]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = CH34X_WRITE_REG;
|
||||||
|
setup->wValue = 0x2727;
|
||||||
|
setup->wIndex = 0;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||||
|
uint16_t reg_value = 0;
|
||||||
|
uint16_t value = 0;
|
||||||
|
uint8_t factor = 0;
|
||||||
|
uint8_t divisor = 0;
|
||||||
|
|
||||||
|
memcpy((uint8_t *)&ch34x_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
|
||||||
|
/* refer to https://github.com/WCHSoftGroup/ch341ser_linux/blob/main/driver/ch341.c */
|
||||||
|
|
||||||
|
switch (line_coding->bParityType) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
reg_value |= CH341_L_PO;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
reg_value |= CH341_L_PE;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
reg_value |= CH341_L_PM;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
reg_value |= CH341_L_PS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -USB_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (line_coding->bDataBits) {
|
||||||
|
case 5:
|
||||||
|
reg_value |= CH341_L_D5;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
reg_value |= CH341_L_D6;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
reg_value |= CH341_L_D7;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
reg_value |= CH341_L_D8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -USB_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_coding->bCharFormat == 2) {
|
||||||
|
reg_value |= CH341_L_SB;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_value |= 0xC0;
|
||||||
|
|
||||||
|
value |= 0x9c;
|
||||||
|
value |= reg_value << 8;
|
||||||
|
|
||||||
|
usbh_ch34x_get_baudrate_div(line_coding->dwDTERate, &factor, &divisor);
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = CH34X_SERIAL_INIT;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = (factor << 8) | 0x80 | divisor;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
memcpy(line_coding, (uint8_t *)&ch34x_class->line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = CH34X_MODEM_CTRL;
|
||||||
|
setup->wValue = 0x0f | (dtr << 5) | (rts << 6);
|
||||||
|
setup->wIndex = 0;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ch34x_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_ch34x *ch34x_class = usbh_ch34x_class_alloc();
|
||||||
|
if (ch34x_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc ch34x_class\r\n");
|
||||||
|
return -USB_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch34x_class->hport = hport;
|
||||||
|
ch34x_class->intf = intf;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = ch34x_class;
|
||||||
|
|
||||||
|
usbh_ch34x_get_version(ch34x_class);
|
||||||
|
usbh_ch34x_flow_ctrl(ch34x_class);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||||
|
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(ch34x_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(ch34x_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ch34x_class->minor);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register CH34X Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
USB_LOG_INFO("Test ch34x rx and tx and rx for 5 times, baudrate is 115200\r\n");
|
||||||
|
|
||||||
|
struct cdc_line_coding linecoding;
|
||||||
|
uint8_t count = 5;
|
||||||
|
|
||||||
|
linecoding.dwDTERate = 115200;
|
||||||
|
linecoding.bDataBits = 8;
|
||||||
|
linecoding.bParityType = 0;
|
||||||
|
linecoding.bCharFormat = 0;
|
||||||
|
usbh_ch34x_set_line_coding(ch34x_class, &linecoding);
|
||||||
|
usbh_ch34x_set_line_state(ch34x_class, true, false);
|
||||||
|
|
||||||
|
memset(g_ch34x_buf, 'a', sizeof(g_ch34x_buf));
|
||||||
|
ret = usbh_ch34x_bulk_out_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("out ret:%d\r\n", ret);
|
||||||
|
while (count--) {
|
||||||
|
ret = usbh_ch34x_bulk_in_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("in ret:%d\r\n", ret);
|
||||||
|
if (ret > 0) {
|
||||||
|
for (uint32_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", g_ch34x_buf[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
usbh_ch34x_run(ch34x_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ch34x_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (ch34x_class) {
|
||||||
|
if (ch34x_class->bulkin) {
|
||||||
|
usbh_kill_urb(&ch34x_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch34x_class->bulkout) {
|
||||||
|
usbh_kill_urb(&ch34x_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister CH34X Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_ch34x_stop(ch34x_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbh_ch34x_class_free(ch34x_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &ch34x_class->bulkin_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &ch34x_class->bulkout_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver ch34x_class_driver = {
|
||||||
|
.driver_name = "ch34x",
|
||||||
|
.connect = usbh_ch34x_connect,
|
||||||
|
.disconnect = usbh_ch34x_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0xff,
|
||||||
|
.protocol = 0xff,
|
||||||
|
.vid = 0x1A86,
|
||||||
|
.pid = 0x7523,
|
||||||
|
.class_driver = &ch34x_class_driver
|
||||||
|
};
|
||||||
74
class/vendor/serial/usbh_ch34x.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_CH34X_H
|
||||||
|
#define USBH_CH34X_H
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
/* Requests */
|
||||||
|
#define CH34X_READ_VERSION 0x5F
|
||||||
|
#define CH34X_WRITE_REG 0x9A
|
||||||
|
#define CH34X_READ_REG 0x95
|
||||||
|
#define CH34X_SERIAL_INIT 0xA1
|
||||||
|
#define CH34X_MODEM_CTRL 0xA4
|
||||||
|
|
||||||
|
// modem control bits
|
||||||
|
#define CH34X_BIT_RTS (1 << 6)
|
||||||
|
#define CH34X_BIT_DTR (1 << 5)
|
||||||
|
|
||||||
|
#define CH341_CTO_O 0x10
|
||||||
|
#define CH341_CTO_D 0x20
|
||||||
|
#define CH341_CTO_R 0x40
|
||||||
|
#define CH341_CTI_C 0x01
|
||||||
|
#define CH341_CTI_DS 0x02
|
||||||
|
#define CH341_CTRL_RI 0x04
|
||||||
|
#define CH341_CTI_DC 0x08
|
||||||
|
#define CH341_CTI_ST 0x0f
|
||||||
|
|
||||||
|
#define CH341_L_ER 0x80
|
||||||
|
#define CH341_L_ET 0x40
|
||||||
|
#define CH341_L_PS 0x38
|
||||||
|
#define CH341_L_PM 0x28
|
||||||
|
#define CH341_L_PE 0x18
|
||||||
|
#define CH341_L_PO 0x08
|
||||||
|
#define CH341_L_SB 0x04
|
||||||
|
#define CH341_L_D8 0x03
|
||||||
|
#define CH341_L_D7 0x02
|
||||||
|
#define CH341_L_D6 0x01
|
||||||
|
#define CH341_L_D5 0x00
|
||||||
|
|
||||||
|
struct usbh_ch34x {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usbh_urb bulkout_urb;
|
||||||
|
struct usbh_urb bulkin_urb;
|
||||||
|
|
||||||
|
struct cdc_line_coding line_coding;
|
||||||
|
|
||||||
|
uint8_t intf;
|
||||||
|
uint8_t minor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts);
|
||||||
|
|
||||||
|
int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
|
||||||
|
void usbh_ch34x_run(struct usbh_ch34x *ch34x_class);
|
||||||
|
void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_CH34X_H */
|
||||||
291
class/vendor/serial/usbh_cp210x.c
vendored
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_cp210x.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||||
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
|
||||||
|
|
||||||
|
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
|
||||||
|
{
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
|
||||||
|
if ((g_devinuse & (1 << devno)) == 0) {
|
||||||
|
g_devinuse |= (1 << devno);
|
||||||
|
memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x));
|
||||||
|
g_cp210x_class[devno].minor = devno;
|
||||||
|
return &g_cp210x_class[devno];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
int devno = cp210x_class->minor;
|
||||||
|
|
||||||
|
if (devno >= 0 && devno < 32) {
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
}
|
||||||
|
memset(cp210x_class, 0, sizeof(struct usbh_cp210x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_IFC_ENABLE;
|
||||||
|
setup->wValue = 1;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_SET_FLOW;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 16;
|
||||||
|
|
||||||
|
memset(g_cp210x_buf, 0, 16);
|
||||||
|
g_cp210x_buf[13] = 0x20;
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_SET_CHARS;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 6;
|
||||||
|
|
||||||
|
memset(g_cp210x_buf, 0, 6);
|
||||||
|
g_cp210x_buf[0] = 0x80;
|
||||||
|
g_cp210x_buf[4] = 0x88;
|
||||||
|
g_cp210x_buf[5] = 0x28;
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_SET_BAUDRATE;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 4;
|
||||||
|
|
||||||
|
memcpy(g_cp210x_buf, (uint8_t *)&baudrate, 4);
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t databits, uint8_t parity, uint8_t stopbits)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
uint16_t value;
|
||||||
|
|
||||||
|
value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0);
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_SET_LINE_CTL;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_set_mhs(struct usbh_cp210x *cp210x_class, uint8_t dtr, uint8_t rts, uint8_t dtr_mask, uint8_t rts_mask)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||||
|
uint16_t value;
|
||||||
|
|
||||||
|
value = ((dtr & 0x01) << 0) | ((rts & 0x01) << 1) | ((dtr_mask & 0x01) << 8) | ((rts_mask & 0x01) << 9);
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = CP210X_SET_MHS;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = cp210x_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cp210x_set_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
memcpy((uint8_t *)&cp210x_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
usbh_cp210x_set_baudrate(cp210x_class, line_coding->dwDTERate);
|
||||||
|
return usbh_cp210x_set_data_format(cp210x_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cp210x_get_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
memcpy(line_coding, (uint8_t *)&cp210x_class->line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cp210x_set_line_state(struct usbh_cp210x *cp210x_class, bool dtr, bool rts)
|
||||||
|
{
|
||||||
|
return usbh_cp210x_set_mhs(cp210x_class, dtr, rts, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_cp210x *cp210x_class = usbh_cp210x_class_alloc();
|
||||||
|
if (cp210x_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc cp210x_class\r\n");
|
||||||
|
return -USB_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp210x_class->hport = hport;
|
||||||
|
cp210x_class->intf = intf;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = cp210x_class;
|
||||||
|
|
||||||
|
usbh_cp210x_enable(cp210x_class);
|
||||||
|
usbh_cp210x_set_flow(cp210x_class);
|
||||||
|
usbh_cp210x_set_chars(cp210x_class);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||||
|
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(cp210x_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(cp210x_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cp210x_class->minor);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register CP210X Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
USB_LOG_INFO("Test cp2102 rx and tx and rx for 5 times, baudrate is 115200\r\n");
|
||||||
|
|
||||||
|
struct cdc_line_coding linecoding;
|
||||||
|
uint8_t count = 5;
|
||||||
|
|
||||||
|
linecoding.dwDTERate = 115200;
|
||||||
|
linecoding.bDataBits = 8;
|
||||||
|
linecoding.bParityType = 0;
|
||||||
|
linecoding.bCharFormat = 0;
|
||||||
|
usbh_cp210x_set_line_coding(cp210x_class, &linecoding);
|
||||||
|
usbh_cp210x_set_line_state(cp210x_class, true, false);
|
||||||
|
|
||||||
|
memset(g_cp210x_buf, 'a', sizeof(g_cp210x_buf));
|
||||||
|
ret = usbh_cp210x_bulk_out_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("out ret:%d\r\n", ret);
|
||||||
|
while (count--) {
|
||||||
|
ret = usbh_cp210x_bulk_in_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("in ret:%d\r\n", ret);
|
||||||
|
if (ret > 0) {
|
||||||
|
for (uint32_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", g_cp210x_buf[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
usbh_cp210x_run(cp210x_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cp210x_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (cp210x_class) {
|
||||||
|
if (cp210x_class->bulkin) {
|
||||||
|
usbh_kill_urb(&cp210x_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp210x_class->bulkout) {
|
||||||
|
usbh_kill_urb(&cp210x_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister CP210X Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_cp210x_stop(cp210x_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbh_cp210x_class_free(cp210x_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &cp210x_class->bulkin_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &cp210x_class->bulkout_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver cp210x_class_driver = {
|
||||||
|
.driver_name = "cp210x",
|
||||||
|
.connect = usbh_cp210x_connect,
|
||||||
|
.disconnect = usbh_cp210x_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0xff,
|
||||||
|
.protocol = 0xff,
|
||||||
|
.vid = 0x10C4,
|
||||||
|
.pid = 0xEA60,
|
||||||
|
.class_driver = &cp210x_class_driver
|
||||||
|
};
|
||||||
71
class/vendor/serial/usbh_cp210x.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_CP210X_H
|
||||||
|
#define USBH_CP210X_H
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
/* Requests */
|
||||||
|
#define CP210X_IFC_ENABLE 0x00
|
||||||
|
#define CP210X_SET_BAUDDIV 0x01
|
||||||
|
#define CP210X_GET_BAUDDIV 0x02
|
||||||
|
#define CP210X_SET_LINE_CTL 0x03 // Set parity, data bits, stop bits
|
||||||
|
#define CP210X_GET_LINE_CTL 0x04
|
||||||
|
#define CP210X_SET_BREAK 0x05
|
||||||
|
#define CP210X_IMM_CHAR 0x06
|
||||||
|
#define CP210X_SET_MHS 0x07 // Set DTR, RTS
|
||||||
|
#define CP210X_GET_MDMSTS 0x08
|
||||||
|
#define CP210X_SET_XON 0x09
|
||||||
|
#define CP210X_SET_XOFF 0x0A
|
||||||
|
#define CP210X_SET_EVENTMASK 0x0B
|
||||||
|
#define CP210X_GET_EVENTMASK 0x0C
|
||||||
|
#define CP210X_SET_CHAR 0x0D
|
||||||
|
#define CP210X_GET_CHARS 0x0E
|
||||||
|
#define CP210X_GET_PROPS 0x0F
|
||||||
|
#define CP210X_GET_COMM_STATUS 0x10
|
||||||
|
#define CP210X_RESET 0x11
|
||||||
|
#define CP210X_PURGE 0x12
|
||||||
|
#define CP210X_SET_FLOW 0x13
|
||||||
|
#define CP210X_GET_FLOW 0x14
|
||||||
|
#define CP210X_EMBED_EVENTS 0x15
|
||||||
|
#define CP210X_GET_EVENTSTATE 0x16
|
||||||
|
#define CP210X_SET_CHARS 0x19
|
||||||
|
#define CP210X_GET_BAUDRATE 0x1D
|
||||||
|
#define CP210X_SET_BAUDRATE 0x1E // Set baudrate
|
||||||
|
#define CP210X_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
|
struct usbh_cp210x {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usbh_urb bulkout_urb;
|
||||||
|
struct usbh_urb bulkin_urb;
|
||||||
|
|
||||||
|
struct cdc_line_coding line_coding;
|
||||||
|
|
||||||
|
uint8_t intf;
|
||||||
|
uint8_t minor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_cp210x_set_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_cp210x_get_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_cp210x_set_line_state(struct usbh_cp210x *ftdi_class, bool dtr, bool rts);
|
||||||
|
|
||||||
|
int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
|
||||||
|
void usbh_cp210x_run(struct usbh_cp210x *cp210x_class);
|
||||||
|
void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_CP210X_H */
|
||||||
368
class/vendor/serial/usbh_ftdi.c
vendored
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_ftdi.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||||
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
|
||||||
|
|
||||||
|
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
|
||||||
|
|
||||||
|
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
|
||||||
|
{
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) {
|
||||||
|
if ((g_devinuse & (1 << devno)) == 0) {
|
||||||
|
g_devinuse |= (1 << devno);
|
||||||
|
memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi));
|
||||||
|
g_ftdi_class[devno].minor = devno;
|
||||||
|
return &g_ftdi_class[devno];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class)
|
||||||
|
{
|
||||||
|
int devno = ftdi_class->minor;
|
||||||
|
|
||||||
|
if (devno >= 0 && devno < 32) {
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
}
|
||||||
|
memset(ftdi_class, 0, sizeof(struct usbh_ftdi));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_baudrate)
|
||||||
|
{
|
||||||
|
#define FTDI_USB_CLK 48000000
|
||||||
|
int baudrate;
|
||||||
|
uint8_t frac[] = { 0, 8, 4, 2, 6, 10, 12, 14 };
|
||||||
|
|
||||||
|
if (actual_baudrate == 2000000) {
|
||||||
|
*itdf_divisor = 0x01;
|
||||||
|
} else if (actual_baudrate == 3000000) {
|
||||||
|
*itdf_divisor = 0x00;
|
||||||
|
} else {
|
||||||
|
baudrate = actual_baudrate;
|
||||||
|
if (baudrate > 100000 && baudrate < 12000000) {
|
||||||
|
baudrate = (baudrate / 100000) + 100000;
|
||||||
|
}
|
||||||
|
int divisor = FTDI_USB_CLK / baudrate;
|
||||||
|
int frac_bits = 0;
|
||||||
|
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
|
||||||
|
if ((divisor & 0xF) == frac[i]) {
|
||||||
|
frac_bits = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
divisor >>= 4;
|
||||||
|
divisor &= 0x3FFF;
|
||||||
|
*itdf_divisor = (divisor << 14) | (frac_bits << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_RESET_REQUEST;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_SET_MODEM_CTRL_REQUEST;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
uint32_t itdf_divisor;
|
||||||
|
uint16_t value;
|
||||||
|
uint8_t baudrate_high;
|
||||||
|
|
||||||
|
usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate);
|
||||||
|
value = itdf_divisor & 0xFFFF;
|
||||||
|
baudrate_high = (itdf_divisor >> 16) & 0xff;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_SET_BAUDRATE_REQUEST;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = (baudrate_high << 8) | ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t databits, uint8_t parity, uint8_t stopbits, uint8_t isbreak)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* D0-D7 databits BITS_7=7, BITS_8=8
|
||||||
|
* D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4
|
||||||
|
* D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2
|
||||||
|
* D14 BREAK_OFF=0, BREAK_ON=1
|
||||||
|
**/
|
||||||
|
|
||||||
|
uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
|
||||||
|
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_SET_DATA_REQUEST;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_SET_LATENCY_TIMER_REQUEST;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_SET_FLOW_CTRL_REQUEST;
|
||||||
|
setup->wValue = value;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST;
|
||||||
|
setup->wValue = 0x0000;
|
||||||
|
setup->wIndex = ftdi_class->intf;
|
||||||
|
setup->wLength = 2;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(ftdi_class->hport, setup, g_ftdi_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
memcpy(ftdi_class->modem_status, g_ftdi_buf, 2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
memcpy((uint8_t *)&ftdi_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate);
|
||||||
|
return usbh_ftdi_set_data_format(ftdi_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding)
|
||||||
|
{
|
||||||
|
memcpy(line_coding, (uint8_t *)&ftdi_class->line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (dtr) {
|
||||||
|
usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_HIGH);
|
||||||
|
} else {
|
||||||
|
usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rts) {
|
||||||
|
ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_HIGH);
|
||||||
|
} else {
|
||||||
|
ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_ftdi *ftdi_class = usbh_ftdi_class_alloc();
|
||||||
|
if (ftdi_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc ftdi_class\r\n");
|
||||||
|
return -USB_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdi_class->hport = hport;
|
||||||
|
ftdi_class->intf = intf;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = ftdi_class;
|
||||||
|
|
||||||
|
usbh_ftdi_reset(ftdi_class);
|
||||||
|
usbh_ftdi_set_flow_ctrl(ftdi_class, SIO_DISABLE_FLOW_CTRL);
|
||||||
|
usbh_ftdi_set_latency_timer(ftdi_class, 0x10);
|
||||||
|
usbh_ftdi_read_modem_status(ftdi_class);
|
||||||
|
USB_LOG_INFO("modem status:%02x:%02x\r\n", ftdi_class->modem_status[0], ftdi_class->modem_status[1]);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||||
|
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(ftdi_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(ftdi_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ftdi_class->minor);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register FTDI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
USB_LOG_INFO("Test ftdi rx and tx and rx for 5 times, baudrate is 115200\r\n");
|
||||||
|
|
||||||
|
struct cdc_line_coding linecoding;
|
||||||
|
uint8_t count = 5;
|
||||||
|
|
||||||
|
linecoding.dwDTERate = 115200;
|
||||||
|
linecoding.bDataBits = 8;
|
||||||
|
linecoding.bParityType = 0;
|
||||||
|
linecoding.bCharFormat = 0;
|
||||||
|
usbh_ftdi_set_line_coding(ftdi_class, &linecoding);
|
||||||
|
usbh_ftdi_set_line_state(ftdi_class, true, false);
|
||||||
|
|
||||||
|
memset(g_ftdi_buf, 'a', sizeof(g_ftdi_buf));
|
||||||
|
ret = usbh_ftdi_bulk_out_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("out ret:%d\r\n", ret);
|
||||||
|
while (count--) {
|
||||||
|
ret = usbh_ftdi_bulk_in_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff);
|
||||||
|
USB_LOG_RAW("in ret:%d\r\n", ret);
|
||||||
|
if (ret > 0) {
|
||||||
|
for (uint32_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", g_ftdi_buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
usbh_ftdi_run(ftdi_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_ftdi_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (ftdi_class) {
|
||||||
|
if (ftdi_class->bulkin) {
|
||||||
|
usbh_kill_urb(&ftdi_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdi_class->bulkout) {
|
||||||
|
usbh_kill_urb(&ftdi_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister FTDI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_ftdi_stop(ftdi_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbh_ftdi_class_free(ftdi_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &ftdi_class->bulkin_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_urb *urb = &ftdi_class->bulkout_urb;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver ftdi_class_driver = {
|
||||||
|
.driver_name = "ftdi",
|
||||||
|
.connect = usbh_ftdi_connect,
|
||||||
|
.disconnect = usbh_ftdi_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info ftdi1_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0xff,
|
||||||
|
.protocol = 0xff,
|
||||||
|
.vid = 0x0403,
|
||||||
|
.pid = 0x6001,
|
||||||
|
.class_driver = &ftdi_class_driver
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info ftdi2_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0xff,
|
||||||
|
.protocol = 0xff,
|
||||||
|
.vid = 0x0403,
|
||||||
|
.pid = 0x6010,
|
||||||
|
.class_driver = &ftdi_class_driver
|
||||||
|
};
|
||||||
74
class/vendor/serial/usbh_ftdi.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_FTDI_H
|
||||||
|
#define USBH_FTDI_H
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
/* Requests */
|
||||||
|
#define SIO_RESET_REQUEST 0x00 /* Reset the port */
|
||||||
|
#define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */
|
||||||
|
#define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */
|
||||||
|
#define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */
|
||||||
|
#define SIO_SET_DATA_REQUEST 0x04 /* Set the data characteristics of the port */
|
||||||
|
#define SIO_POLL_MODEM_STATUS_REQUEST 0x05
|
||||||
|
#define SIO_SET_EVENT_CHAR_REQUEST 0x06
|
||||||
|
#define SIO_SET_ERROR_CHAR_REQUEST 0x07
|
||||||
|
#define SIO_SET_LATENCY_TIMER_REQUEST 0x09
|
||||||
|
#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A
|
||||||
|
#define SIO_SET_BITMODE_REQUEST 0x0B
|
||||||
|
#define SIO_READ_PINS_REQUEST 0x0C
|
||||||
|
#define SIO_READ_EEPROM_REQUEST 0x90
|
||||||
|
#define SIO_WRITE_EEPROM_REQUEST 0x91
|
||||||
|
#define SIO_ERASE_EEPROM_REQUEST 0x92
|
||||||
|
|
||||||
|
#define SIO_DISABLE_FLOW_CTRL 0x0
|
||||||
|
#define SIO_RTS_CTS_HS (0x1 << 8)
|
||||||
|
#define SIO_DTR_DSR_HS (0x2 << 8)
|
||||||
|
#define SIO_XON_XOFF_HS (0x4 << 8)
|
||||||
|
|
||||||
|
#define SIO_SET_DTR_MASK 0x1
|
||||||
|
#define SIO_SET_DTR_HIGH (1 | (SIO_SET_DTR_MASK << 8))
|
||||||
|
#define SIO_SET_DTR_LOW (0 | (SIO_SET_DTR_MASK << 8))
|
||||||
|
#define SIO_SET_RTS_MASK 0x2
|
||||||
|
#define SIO_SET_RTS_HIGH (2 | (SIO_SET_RTS_MASK << 8))
|
||||||
|
#define SIO_SET_RTS_LOW (0 | (SIO_SET_RTS_MASK << 8))
|
||||||
|
|
||||||
|
#define SIO_RTS_CTS_HS (0x1 << 8)
|
||||||
|
|
||||||
|
struct usbh_ftdi {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usbh_urb bulkout_urb;
|
||||||
|
struct usbh_urb bulkin_urb;
|
||||||
|
|
||||||
|
struct cdc_line_coding line_coding;
|
||||||
|
|
||||||
|
uint8_t intf;
|
||||||
|
uint8_t minor;
|
||||||
|
uint8_t modem_status[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding);
|
||||||
|
int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts);
|
||||||
|
|
||||||
|
int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
|
||||||
|
void usbh_ftdi_run(struct usbh_ftdi *ftdi_class);
|
||||||
|
void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_FTDI_H */
|
||||||
@@ -18,9 +18,9 @@ struct usbd_video_priv {
|
|||||||
uint8_t power_mode;
|
uint8_t power_mode;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
struct video_entity_info info[3];
|
struct video_entity_info info[3];
|
||||||
} g_usbd_video;
|
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
|
||||||
|
|
||||||
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||||
|
|
||||||
@@ -60,13 +60,13 @@ static int usbd_video_control_request_handler(struct usb_setup_packet *setup, ui
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
|
uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
|
||||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
struct video_entity_info *entity_info = &g_usbd_video.info[i];
|
struct video_entity_info *entity_info = &g_usbd_video[busid].info[i];
|
||||||
if (entity_info->bEntityId == entity_id) {
|
if (entity_info->bEntityId == entity_id) {
|
||||||
switch (entity_info->bDescriptorSubtype) {
|
switch (entity_info->bDescriptorSubtype) {
|
||||||
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
|
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
|
||||||
@@ -546,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_usbd_video.error_code = 0x06;
|
g_usbd_video[busid].error_code = 0x06;
|
||||||
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
|
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -564,7 +564,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||||
|
|
||||||
@@ -572,10 +572,10 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
|||||||
case VIDEO_VS_PROBE_CONTROL:
|
case VIDEO_VS_PROBE_CONTROL:
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case VIDEO_REQUEST_SET_CUR:
|
case VIDEO_REQUEST_SET_CUR:
|
||||||
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
|
//memcpy((uint8_t *)&g_usbd_video[busid].probe, *data, setup->wLength);
|
||||||
break;
|
break;
|
||||||
case VIDEO_REQUEST_GET_CUR:
|
case VIDEO_REQUEST_GET_CUR:
|
||||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
|
||||||
*len = sizeof(struct video_probe_and_commit_controls);
|
*len = sizeof(struct video_probe_and_commit_controls);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -583,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_MAX:
|
||||||
case VIDEO_REQUEST_GET_RES:
|
case VIDEO_REQUEST_GET_RES:
|
||||||
case VIDEO_REQUEST_GET_DEF:
|
case VIDEO_REQUEST_GET_DEF:
|
||||||
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
|
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
|
||||||
*len = sizeof(struct video_probe_and_commit_controls);
|
*len = sizeof(struct video_probe_and_commit_controls);
|
||||||
break;
|
break;
|
||||||
case VIDEO_REQUEST_GET_LEN:
|
case VIDEO_REQUEST_GET_LEN:
|
||||||
@@ -604,17 +604,17 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
|||||||
case VIDEO_VS_COMMIT_CONTROL:
|
case VIDEO_VS_COMMIT_CONTROL:
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case VIDEO_REQUEST_SET_CUR:
|
case VIDEO_REQUEST_SET_CUR:
|
||||||
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
|
//memcpy((uint8_t *)&g_usbd_video[busid].commit, *data, setup->wLength);
|
||||||
break;
|
break;
|
||||||
case VIDEO_REQUEST_GET_CUR:
|
case VIDEO_REQUEST_GET_CUR:
|
||||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
|
||||||
*len = sizeof(struct video_probe_and_commit_controls);
|
*len = sizeof(struct video_probe_and_commit_controls);
|
||||||
break;
|
break;
|
||||||
case VIDEO_REQUEST_GET_MIN:
|
case VIDEO_REQUEST_GET_MIN:
|
||||||
case VIDEO_REQUEST_GET_MAX:
|
case VIDEO_REQUEST_GET_MAX:
|
||||||
case VIDEO_REQUEST_GET_RES:
|
case VIDEO_REQUEST_GET_RES:
|
||||||
case VIDEO_REQUEST_GET_DEF:
|
case VIDEO_REQUEST_GET_DEF:
|
||||||
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
|
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
|
||||||
*len = sizeof(struct video_probe_and_commit_controls);
|
*len = sizeof(struct video_probe_and_commit_controls);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -636,7 +636,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
|||||||
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
|
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case VIDEO_REQUEST_GET_CUR:
|
case VIDEO_REQUEST_GET_CUR:
|
||||||
(*data)[0] = g_usbd_video.error_code;
|
(*data)[0] = g_usbd_video[busid].error_code;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
case VIDEO_REQUEST_GET_INFO:
|
case VIDEO_REQUEST_GET_INFO:
|
||||||
@@ -655,7 +655,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int video_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int video_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("Video Class request: "
|
USB_LOG_DBG("Video Class request: "
|
||||||
"bRequest 0x%02x\r\n",
|
"bRequest 0x%02x\r\n",
|
||||||
@@ -666,30 +666,30 @@ static int video_class_interface_request_handler(struct usb_setup_packet *setup,
|
|||||||
|
|
||||||
if (intf_num == 0) { /* Video Control Interface */
|
if (intf_num == 0) { /* Video Control Interface */
|
||||||
if (entity_id == 0) {
|
if (entity_id == 0) {
|
||||||
return usbd_video_control_request_handler(setup, data, len); /* Interface Control Requests */
|
return usbd_video_control_request_handler(busid, setup, data, len); /* Interface Control Requests */
|
||||||
} else {
|
} else {
|
||||||
return usbd_video_control_unit_terminal_request_handler(setup, data, len); /* Unit and Terminal Requests */
|
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
|
||||||
}
|
}
|
||||||
} else if (intf_num == 1) { /* Video Stream Inteface */
|
} else if (intf_num == 1) { /* Video Stream Inteface */
|
||||||
return usbd_video_stream_request_handler(setup, data, len); /* Interface Stream Requests */
|
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_notify_handler(uint8_t event, void *arg)
|
static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
g_usbd_video.error_code = 0;
|
g_usbd_video[busid].error_code = 0;
|
||||||
g_usbd_video.power_mode = 0;
|
g_usbd_video[busid].power_mode = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBD_EVENT_SET_INTERFACE: {
|
case USBD_EVENT_SET_INTERFACE: {
|
||||||
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
|
||||||
if (intf->bAlternateSetting == 1) {
|
if (intf->bAlternateSetting == 1) {
|
||||||
usbd_video_open(intf->bInterfaceNumber);
|
usbd_video_open(busid, intf->bInterfaceNumber);
|
||||||
} else {
|
} else {
|
||||||
usbd_video_close(intf->bInterfaceNumber);
|
usbd_video_close(busid, intf->bInterfaceNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,46 +699,46 @@ 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)
|
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||||
{
|
{
|
||||||
g_usbd_video.probe.hintUnion.bmHint = 0x01;
|
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
|
||||||
g_usbd_video.probe.hintUnion1.bmHint = 0;
|
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
|
||||||
g_usbd_video.probe.bFormatIndex = 1;
|
g_usbd_video[busid].probe.bFormatIndex = 1;
|
||||||
g_usbd_video.probe.bFrameIndex = 1;
|
g_usbd_video[busid].probe.bFrameIndex = 1;
|
||||||
g_usbd_video.probe.dwFrameInterval = dwFrameInterval;
|
g_usbd_video[busid].probe.dwFrameInterval = dwFrameInterval;
|
||||||
g_usbd_video.probe.wKeyFrameRate = 0;
|
g_usbd_video[busid].probe.wKeyFrameRate = 0;
|
||||||
g_usbd_video.probe.wPFrameRate = 0;
|
g_usbd_video[busid].probe.wPFrameRate = 0;
|
||||||
g_usbd_video.probe.wCompQuality = 0;
|
g_usbd_video[busid].probe.wCompQuality = 0;
|
||||||
g_usbd_video.probe.wCompWindowSize = 0;
|
g_usbd_video[busid].probe.wCompWindowSize = 0;
|
||||||
g_usbd_video.probe.wDelay = 0;
|
g_usbd_video[busid].probe.wDelay = 0;
|
||||||
g_usbd_video.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
g_usbd_video[busid].probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||||
g_usbd_video.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
g_usbd_video[busid].probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||||
g_usbd_video.probe.dwClockFrequency = 0;
|
g_usbd_video[busid].probe.dwClockFrequency = 0;
|
||||||
g_usbd_video.probe.bmFramingInfo = 0;
|
g_usbd_video[busid].probe.bmFramingInfo = 0;
|
||||||
g_usbd_video.probe.bPreferedVersion = 0;
|
g_usbd_video[busid].probe.bPreferedVersion = 0;
|
||||||
g_usbd_video.probe.bMinVersion = 0;
|
g_usbd_video[busid].probe.bMinVersion = 0;
|
||||||
g_usbd_video.probe.bMaxVersion = 0;
|
g_usbd_video[busid].probe.bMaxVersion = 0;
|
||||||
|
|
||||||
g_usbd_video.commit.hintUnion.bmHint = 0x01;
|
g_usbd_video[busid].commit.hintUnion.bmHint = 0x01;
|
||||||
g_usbd_video.commit.hintUnion1.bmHint = 0;
|
g_usbd_video[busid].commit.hintUnion1.bmHint = 0;
|
||||||
g_usbd_video.commit.bFormatIndex = 1;
|
g_usbd_video[busid].commit.bFormatIndex = 1;
|
||||||
g_usbd_video.commit.bFrameIndex = 1;
|
g_usbd_video[busid].commit.bFrameIndex = 1;
|
||||||
g_usbd_video.commit.dwFrameInterval = dwFrameInterval;
|
g_usbd_video[busid].commit.dwFrameInterval = dwFrameInterval;
|
||||||
g_usbd_video.commit.wKeyFrameRate = 0;
|
g_usbd_video[busid].commit.wKeyFrameRate = 0;
|
||||||
g_usbd_video.commit.wPFrameRate = 0;
|
g_usbd_video[busid].commit.wPFrameRate = 0;
|
||||||
g_usbd_video.commit.wCompQuality = 0;
|
g_usbd_video[busid].commit.wCompQuality = 0;
|
||||||
g_usbd_video.commit.wCompWindowSize = 0;
|
g_usbd_video[busid].commit.wCompWindowSize = 0;
|
||||||
g_usbd_video.commit.wDelay = 0;
|
g_usbd_video[busid].commit.wDelay = 0;
|
||||||
g_usbd_video.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
g_usbd_video[busid].commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
|
||||||
g_usbd_video.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
g_usbd_video[busid].commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
|
||||||
g_usbd_video.commit.dwClockFrequency = 0;
|
g_usbd_video[busid].commit.dwClockFrequency = 0;
|
||||||
g_usbd_video.commit.bmFramingInfo = 0;
|
g_usbd_video[busid].commit.bmFramingInfo = 0;
|
||||||
g_usbd_video.commit.bPreferedVersion = 0;
|
g_usbd_video[busid].commit.bPreferedVersion = 0;
|
||||||
g_usbd_video.commit.bMinVersion = 0;
|
g_usbd_video[busid].commit.bMinVersion = 0;
|
||||||
g_usbd_video.commit.bMaxVersion = 0;
|
g_usbd_video[busid].commit.bMaxVersion = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||||
uint32_t dwFrameInterval,
|
uint32_t dwFrameInterval,
|
||||||
uint32_t dwMaxVideoFrameSize,
|
uint32_t dwMaxVideoFrameSize,
|
||||||
uint32_t dwMaxPayloadTransferSize)
|
uint32_t dwMaxPayloadTransferSize)
|
||||||
@@ -748,39 +748,39 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
|||||||
intf->vendor_handler = NULL;
|
intf->vendor_handler = NULL;
|
||||||
intf->notify_handler = video_notify_handler;
|
intf->notify_handler = video_notify_handler;
|
||||||
|
|
||||||
g_usbd_video.info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
g_usbd_video[busid].info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||||
g_usbd_video.info[0].bEntityId = 0x01;
|
g_usbd_video[busid].info[0].bEntityId = 0x01;
|
||||||
g_usbd_video.info[0].wTerminalType = VIDEO_ITT_CAMERA;
|
g_usbd_video[busid].info[0].wTerminalType = VIDEO_ITT_CAMERA;
|
||||||
g_usbd_video.info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
g_usbd_video[busid].info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
|
||||||
g_usbd_video.info[1].bEntityId = 0x03;
|
g_usbd_video[busid].info[1].bEntityId = 0x03;
|
||||||
g_usbd_video.info[1].wTerminalType = 0x00;
|
g_usbd_video[busid].info[1].wTerminalType = 0x00;
|
||||||
g_usbd_video.info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
|
g_usbd_video[busid].info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
|
||||||
g_usbd_video.info[2].bEntityId = 0x02;
|
g_usbd_video[busid].info[2].bEntityId = 0x02;
|
||||||
g_usbd_video.info[2].wTerminalType = 0x00;
|
g_usbd_video[busid].info[2].wTerminalType = 0x00;
|
||||||
|
|
||||||
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
|
usbd_video_probe_and_commit_controls_init(busid, dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
|
||||||
return intf;
|
return intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
|
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
|
||||||
{
|
{
|
||||||
uint32_t packets;
|
uint32_t packets;
|
||||||
uint32_t last_packet_size;
|
uint32_t last_packet_size;
|
||||||
uint32_t picture_pos = 0;
|
uint32_t picture_pos = 0;
|
||||||
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||||
|
|
||||||
packets = (input_len + (g_usbd_video.probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||||
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2));
|
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
|
||||||
|
|
||||||
for (size_t i = 0; i < packets; i++) {
|
for (size_t i = 0; i < packets; i++) {
|
||||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||||
if (i == (packets - 1)) {
|
if (i == (packets - 1)) {
|
||||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
||||||
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||||
} else {
|
} else {
|
||||||
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
|
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||||
picture_pos += g_usbd_video.probe.dwMaxPayloadTransferSize - 2;
|
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uvc_header[1] ^= 1;
|
uvc_header[1] ^= 1;
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init video interface driver */
|
/* Init video interface driver */
|
||||||
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
|
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||||
uint32_t dwFrameInterval,
|
uint32_t dwFrameInterval,
|
||||||
uint32_t dwMaxVideoFrameSize,
|
uint32_t dwMaxVideoFrameSize,
|
||||||
uint32_t dwMaxPayloadTransferSize);
|
uint32_t dwMaxPayloadTransferSize);
|
||||||
|
|
||||||
void usbd_video_open(uint8_t intf);
|
void usbd_video_open(uint8_t busid, uint8_t intf);
|
||||||
void usbd_video_close(uint8_t intf);
|
void usbd_video_close(uint8_t busid, uint8_t intf);
|
||||||
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
#include "usbh_video.h"
|
#include "usbh_video.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_video"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/video%d"
|
#define DEV_FORMAT "/dev/video%d"
|
||||||
|
|
||||||
/* general descriptor field offsets */
|
/* general descriptor field offsets */
|
||||||
|
|||||||
@@ -105,10 +105,10 @@ static void rndis_notify_rsp(void)
|
|||||||
{
|
{
|
||||||
memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
|
memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
|
||||||
NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
|
NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
|
||||||
usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
|
usbd_ep_start_write(0, rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||||||
@@ -426,7 +426,7 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rndis_notify_handler(uint8_t event, void *arg)
|
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -436,7 +436,7 @@ static void rndis_notify_handler(uint8_t event, void *arg)
|
|||||||
g_rndis_rx_data_length = 0;
|
g_rndis_rx_data_length = 0;
|
||||||
g_rndis_tx_data_length = 0;
|
g_rndis_tx_data_length = 0;
|
||||||
g_usbd_rndis.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));
|
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -444,14 +444,14 @@ static void rndis_notify_handler(uint8_t event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
|
void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
rndis_data_packet_t *hdr;
|
rndis_data_packet_t *hdr;
|
||||||
|
|
||||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||||
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
||||||
if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
|
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
|
||||||
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,17 +462,17 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
|
|||||||
usbd_rndis_data_recv_done();
|
usbd_rndis_data_recv_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
|
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
|
if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(ep, NULL, 0);
|
usbd_ep_start_write(0, ep, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
g_rndis_tx_data_length = 0;
|
g_rndis_tx_data_length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rndis_int_in(uint8_t ep, uint32_t nbytes)
|
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
//USB_LOG_DBG("len:%d\r\n", nbytes);
|
//USB_LOG_DBG("len:%d\r\n", nbytes);
|
||||||
}
|
}
|
||||||
@@ -496,7 +496,7 @@ struct pbuf *usbd_rndis_eth_rx(void)
|
|||||||
|
|
||||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
|
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
|
||||||
g_rndis_rx_data_length = 0;
|
g_rndis_rx_data_length = 0;
|
||||||
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -508,7 +508,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
|||||||
rndis_data_packet_t *hdr;
|
rndis_data_packet_t *hdr;
|
||||||
|
|
||||||
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||||
return 0;
|
return -USB_ERR_NOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_rndis_tx_data_length > 0) {
|
if (g_rndis_tx_data_length > 0) {
|
||||||
@@ -536,7 +536,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
|||||||
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
|
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||||
|
|
||||||
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
|
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
|
||||||
return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
|
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||||
@@ -557,9 +557,9 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
|||||||
rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
|
rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
|
||||||
rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
|
rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
|
||||||
|
|
||||||
usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
|
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_OUT_EP_IDX]);
|
||||||
usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
|
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_IN_EP_IDX]);
|
||||||
usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
|
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_INT_EP_IDX]);
|
||||||
|
|
||||||
intf->class_interface_handler = rndis_class_interface_request_handler;
|
intf->class_interface_handler = rndis_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
|
|||||||
399
class/wireless/usbh_bluetooth.c
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_bluetooth.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_bluetooth"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/bluetooth"
|
||||||
|
|
||||||
|
static struct usbh_bluetooth g_bluetooth_class;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||||
|
#else
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret = 0;
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
uint8_t mult;
|
||||||
|
uint16_t mps;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||||
|
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
if (intf != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
|
||||||
|
|
||||||
|
bluetooth_class->hport = hport;
|
||||||
|
bluetooth_class->intf = intf;
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
bluetooth_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
|
||||||
|
#endif
|
||||||
|
hport->config.intf[intf].priv = bluetooth_class;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(bluetooth_class->intin, ep_desc);
|
||||||
|
} else {
|
||||||
|
return -USB_ERR_NOTSUPP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
USBH_EP_INIT(bluetooth_class->bulkin, ep_desc);
|
||||||
|
} else {
|
||||||
|
USBH_EP_INIT(bluetooth_class->bulkout, ep_desc);
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
USB_LOG_INFO("Num of altsettings:%u\r\n", bluetooth_class->num_of_intf_altsettings);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < bluetooth_class->num_of_intf_altsettings; i++) {
|
||||||
|
USB_LOG_INFO("Altsetting:%u\r\n", i);
|
||||||
|
for (uint8_t j = 0; j < hport->config.intf[intf + 1].altsetting[i].intf_desc.bNumEndpoints; j++) {
|
||||||
|
ep_desc = &bluetooth_class->hport->config.intf[intf + 1].altsetting[i].ep[j].ep_desc;
|
||||||
|
|
||||||
|
mult = USB_GET_MULT(ep_desc->wMaxPacketSize);
|
||||||
|
mps = USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize);
|
||||||
|
|
||||||
|
USB_LOG_INFO("\tEp=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||||
|
ep_desc->bEndpointAddress,
|
||||||
|
ep_desc->bmAttributes,
|
||||||
|
mps,
|
||||||
|
ep_desc->bInterval,
|
||||||
|
mult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_set_interface(hport, intf, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
|
||||||
|
#endif
|
||||||
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT);
|
||||||
|
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_bluetooth_run(bluetooth_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_bluetooth *bluetooth_class = (struct usbh_bluetooth *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (hport->config.config_desc.bNumInterfaces == (intf + 1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bluetooth_class) {
|
||||||
|
if (bluetooth_class->bulkin) {
|
||||||
|
usbh_kill_urb(&bluetooth_class->bulkin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bluetooth_class->bulkout) {
|
||||||
|
usbh_kill_urb(&bluetooth_class->bulkout_urb);
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
if (bluetooth_class->intin) {
|
||||||
|
usbh_kill_urb(&bluetooth_class->intin_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (bluetooth_class->isoin) {
|
||||||
|
// usbh_kill_urb(&bluetooth_class->isoin_urb);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (bluetooth_class->isoin) {
|
||||||
|
// usbh_kill_urb(&bluetooth_class->isoinin_urb);
|
||||||
|
// }
|
||||||
|
#endif
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||||
|
USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
usbh_bluetooth_stop(bluetooth_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_LOG
|
||||||
|
static void usbh_bluetooth_hci_dump(uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("%02x ", data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define usbh_bluetooth_hci_dump(data, len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int usbh_bluetooth_hci_bulk_out(uint8_t *buffer, uint32_t buflen)
|
||||||
|
{
|
||||||
|
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||||
|
struct usbh_urb *urb = &bluetooth_class->bulkout_urb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(urb);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = urb->actual_length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
g_bluetooth_tx_buf[0] = hci_type;
|
||||||
|
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
|
||||||
|
ret = usbh_bluetooth_hci_bulk_out(g_bluetooth_tx_buf, buflen + 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_bluetooth_hci_rx_thread(void *argument)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t ep_mps;
|
||||||
|
uint8_t retry = 0;
|
||||||
|
uint16_t actual_len = 0;
|
||||||
|
|
||||||
|
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Create hc rx thread\r\n");
|
||||||
|
while (1) {
|
||||||
|
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -USB_ERR_SHUTDOWN) {
|
||||||
|
goto delete;
|
||||||
|
} else {
|
||||||
|
retry++;
|
||||||
|
if (retry == 3) {
|
||||||
|
retry = 0;
|
||||||
|
goto delete;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
|
||||||
|
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len);
|
||||||
|
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len);
|
||||||
|
actual_len = 0;
|
||||||
|
} else {
|
||||||
|
/* read continue util read short packet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
delete :
|
||||||
|
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||||
|
usb_osal_thread_delete(NULL);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen)
|
||||||
|
{
|
||||||
|
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||||
|
struct usb_setup_packet *setup = bluetooth_class->hport->setup;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
|
setup->bRequest = 0x00;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = bluetooth_class->intf;
|
||||||
|
setup->wLength = buflen;
|
||||||
|
|
||||||
|
return usbh_control_transfer(bluetooth_class->hport, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (hci_type == USB_BLUETOOTH_HCI_CMD) {
|
||||||
|
g_bluetooth_cmd_buf[0] = USB_BLUETOOTH_HCI_CMD;
|
||||||
|
memcpy(&g_bluetooth_cmd_buf[1], buffer, buflen);
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_cmd_buf, buflen + 1);
|
||||||
|
ret = usbh_bluetooth_hci_cmd(&g_bluetooth_cmd_buf[1], buflen);
|
||||||
|
} else if (hci_type == USB_BLUETOOTH_HCI_ACL) {
|
||||||
|
g_bluetooth_tx_buf[0] = USB_BLUETOOTH_HCI_ACL;
|
||||||
|
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
|
||||||
|
ret = usbh_bluetooth_hci_bulk_out(&g_bluetooth_tx_buf[1], buflen);
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t ep_mps;
|
||||||
|
uint32_t interval;
|
||||||
|
uint8_t retry = 0;
|
||||||
|
uint16_t actual_len = 0;
|
||||||
|
|
||||||
|
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.intin->wMaxPacketSize);
|
||||||
|
interval = g_bluetooth_class.intin->bInterval;
|
||||||
|
|
||||||
|
USB_LOG_INFO("Create hc event rx thread\r\n");
|
||||||
|
while (1) {
|
||||||
|
usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_evt_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_bluetooth_class.intin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -USB_ERR_SHUTDOWN) {
|
||||||
|
goto delete;
|
||||||
|
} else if (ret == -USB_ERR_NAK) {
|
||||||
|
usb_osal_msleep(interval);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
retry++;
|
||||||
|
if (retry == 3) {
|
||||||
|
retry = 0;
|
||||||
|
goto delete;
|
||||||
|
}
|
||||||
|
usb_osal_msleep(interval);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual_len += g_bluetooth_class.intin_urb.actual_length;
|
||||||
|
if (g_bluetooth_class.intin_urb.actual_length != ep_mps) {
|
||||||
|
g_bluetooth_evt_buf[0] = USB_BLUETOOTH_HCI_EVT;
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_evt_buf, actual_len + 1);
|
||||||
|
usbh_bluetooth_hci_read_callback(g_bluetooth_evt_buf, actual_len + 1);
|
||||||
|
actual_len = 0;
|
||||||
|
} else {
|
||||||
|
/* read continue util read short packet */
|
||||||
|
}
|
||||||
|
usb_osal_msleep(interval);
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
delete :
|
||||||
|
USB_LOG_INFO("Delete hc event rx thread\r\n");
|
||||||
|
usb_osal_thread_delete(NULL);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t ep_mps;
|
||||||
|
uint8_t retry = 0;
|
||||||
|
uint16_t actual_len = 0;
|
||||||
|
|
||||||
|
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Create hc acl rx thread\r\n");
|
||||||
|
while (1) {
|
||||||
|
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -USB_ERR_SHUTDOWN) {
|
||||||
|
goto delete;
|
||||||
|
} else {
|
||||||
|
retry++;
|
||||||
|
if (retry == 3) {
|
||||||
|
retry = 0;
|
||||||
|
goto delete;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
|
||||||
|
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
|
||||||
|
g_bluetooth_rx_buf[0] = USB_BLUETOOTH_HCI_ACL;
|
||||||
|
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len + 1);
|
||||||
|
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len + 1);
|
||||||
|
actual_len = 0;
|
||||||
|
} else {
|
||||||
|
/* read continue util read short packet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
delete :
|
||||||
|
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||||
|
usb_osal_thread_delete(NULL);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct usbh_class_driver bluetooth_class_driver = {
|
||||||
|
.driver_name = "bluetooth",
|
||||||
|
.connect = usbh_bluetooth_connect,
|
||||||
|
.disconnect = usbh_bluetooth_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0x00,
|
||||||
|
.protocol = 0x00,
|
||||||
|
.vid = 0x2fe3,
|
||||||
|
.pid = 0x000c,
|
||||||
|
.class_driver = &bluetooth_class_driver
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||||
|
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||||
|
.subclass = 0x01,
|
||||||
|
.protocol = 0x01,
|
||||||
|
.vid = 0x00,
|
||||||
|
.pid = 0x00,
|
||||||
|
.class_driver = &bluetooth_class_driver
|
||||||
|
};
|
||||||
|
#endif
|
||||||
54
class/wireless/usbh_bluetooth.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, sakumisu
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef USBH_BLUETOOTH_H
|
||||||
|
#define USBH_BLUETOOTH_H
|
||||||
|
|
||||||
|
#define USB_BLUETOOTH_HCI_NONE 0x00
|
||||||
|
#define USB_BLUETOOTH_HCI_CMD 0x01
|
||||||
|
#define USB_BLUETOOTH_HCI_ACL 0x02
|
||||||
|
#define USB_BLUETOOTH_HCI_SCO 0x03
|
||||||
|
#define USB_BLUETOOTH_HCI_EVT 0x04
|
||||||
|
#define USB_BLUETOOTH_HCI_ISO 0x05
|
||||||
|
|
||||||
|
struct usbh_bluetooth {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
uint8_t intf;
|
||||||
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||||
|
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||||
|
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||||
|
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
|
||||||
|
struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */
|
||||||
|
struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */
|
||||||
|
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||||
|
struct usbh_urb *isoin_urb; /* Bulk IN urb */
|
||||||
|
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
|
||||||
|
uint8_t num_of_intf_altsettings;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
|
||||||
|
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
|
||||||
|
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||||
|
void usbh_bluetooth_hci_rx_thread(void *argument);
|
||||||
|
#else
|
||||||
|
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
|
||||||
|
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);
|
||||||
|
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBH_BLUETOOTH_H */
|
||||||
@@ -7,6 +7,10 @@
|
|||||||
#include "usbh_rndis.h"
|
#include "usbh_rndis.h"
|
||||||
#include "rndis_protocol.h"
|
#include "rndis_protocol.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_rndis"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
#define DEV_FORMAT "/dev/rndis"
|
#define DEV_FORMAT "/dev/rndis"
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||||
@@ -185,7 +189,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t data[32];
|
uint8_t data[32];
|
||||||
@@ -196,9 +200,9 @@ static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||||
rndis_class->link_status = true;
|
rndis_class->connect_status = true;
|
||||||
} else {
|
} else {
|
||||||
rndis_class->link_status = false;
|
rndis_class->connect_status = false;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -326,9 +330,9 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||||||
goto query_errorout;
|
goto query_errorout;
|
||||||
}
|
}
|
||||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||||
rndis_class->link_status = true;
|
rndis_class->connect_status = true;
|
||||||
} else {
|
} else {
|
||||||
rndis_class->link_status = false;
|
rndis_class->connect_status = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||||
@@ -438,12 +442,12 @@ void usbh_rndis_rx_thread(void *argument)
|
|||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
find_class:
|
||||||
// clang-format on
|
// clang-format on
|
||||||
g_rndis_class.link_status = false;
|
g_rndis_class.connect_status = false;
|
||||||
if (usbh_find_class_instance("/dev/rndis") == NULL) {
|
if (usbh_find_class_instance("/dev/rndis") == NULL) {
|
||||||
goto delete;
|
goto delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (g_rndis_class.link_status == false) {
|
while (g_rndis_class.connect_status == false) {
|
||||||
ret = usbh_rndis_get_connect_status(&g_rndis_class);
|
ret = usbh_rndis_get_connect_status(&g_rndis_class);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
usb_osal_msleep(100);
|
usb_osal_msleep(100);
|
||||||
@@ -513,7 +517,7 @@ err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
|
|||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
rndis_data_packet_t *hdr;
|
rndis_data_packet_t *hdr;
|
||||||
|
|
||||||
if (g_rndis_class.link_status == false) {
|
if (g_rndis_class.connect_status == false) {
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ struct usbh_rndis {
|
|||||||
uint32_t request_id;
|
uint32_t request_id;
|
||||||
|
|
||||||
uint32_t link_speed;
|
uint32_t link_speed;
|
||||||
bool link_status;
|
bool connect_status;
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
|
|
||||||
ip_addr_t ipaddr;
|
ip_addr_t ipaddr;
|
||||||
@@ -39,6 +39,7 @@ struct usbh_rndis {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class);
|
||||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
||||||
|
|
||||||
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ extern "C" {
|
|||||||
* @brief init device controller registers.
|
* @brief init device controller registers.
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_dc_init(void);
|
int usb_dc_init(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief deinit device controller registers.
|
* @brief deinit device controller registers.
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_dc_deinit(void);
|
int usb_dc_deinit(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set USB device address
|
* @brief Set USB device address
|
||||||
@@ -31,7 +31,7 @@ int usb_dc_deinit(void);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_set_address(const uint8_t addr);
|
int usbd_set_address(uint8_t busid, const uint8_t addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get USB device speed
|
* @brief Get USB device speed
|
||||||
@@ -40,7 +40,7 @@ int usbd_set_address(const uint8_t addr);
|
|||||||
*
|
*
|
||||||
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
|
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
|
||||||
*/
|
*/
|
||||||
uint8_t usbd_get_port_speed(const uint8_t port);
|
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief configure and enable endpoint.
|
* @brief configure and enable endpoint.
|
||||||
@@ -49,7 +49,7 @@ uint8_t usbd_get_port_speed(const uint8_t port);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
|
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disable the selected endpoint
|
* @brief Disable the selected endpoint
|
||||||
@@ -58,7 +58,7 @@ int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_close(const uint8_t ep);
|
int usbd_ep_close(uint8_t busid, const uint8_t ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set stall condition for the selected endpoint
|
* @brief Set stall condition for the selected endpoint
|
||||||
@@ -68,7 +68,7 @@ int usbd_ep_close(const uint8_t ep);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_set_stall(const uint8_t ep);
|
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear stall condition for the selected endpoint
|
* @brief Clear stall condition for the selected endpoint
|
||||||
@@ -78,7 +78,7 @@ int usbd_ep_set_stall(const uint8_t ep);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_clear_stall(const uint8_t ep);
|
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the selected endpoint is stalled
|
* @brief Check if the selected endpoint is stalled
|
||||||
@@ -89,7 +89,7 @@ int usbd_ep_clear_stall(const uint8_t ep);
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
|
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Setup in ep transfer setting and start transfer.
|
* @brief Setup in ep transfer setting and start transfer.
|
||||||
@@ -108,7 +108,7 @@ int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
|
|||||||
* be zero for a zero length status packet.
|
* be zero for a zero length status packet.
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return 0 on success, negative errno code on fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len);
|
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Setup out ep transfer setting and start transfer.
|
* @brief Setup out ep transfer setting and start transfer.
|
||||||
@@ -127,40 +127,40 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
|
|||||||
*
|
*
|
||||||
* @return 0 on success, negative errno code on fail.
|
* @return 0 on success, negative errno code on fail.
|
||||||
*/
|
*/
|
||||||
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len);
|
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
|
||||||
|
|
||||||
/* usb dcd irq callback */
|
/* usb dcd irq callback */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb connect irq callback.
|
* @brief Usb connect irq callback.
|
||||||
*/
|
*/
|
||||||
void usbd_event_connect_handler(void);
|
void usbd_event_connect_handler(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb disconnect irq callback.
|
* @brief Usb disconnect irq callback.
|
||||||
*/
|
*/
|
||||||
void usbd_event_disconnect_handler(void);
|
void usbd_event_disconnect_handler(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb resume irq callback.
|
* @brief Usb resume irq callback.
|
||||||
*/
|
*/
|
||||||
void usbd_event_resume_handler(void);
|
void usbd_event_resume_handler(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb suspend irq callback.
|
* @brief Usb suspend irq callback.
|
||||||
*/
|
*/
|
||||||
void usbd_event_suspend_handler(void);
|
void usbd_event_suspend_handler(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb reset irq callback.
|
* @brief Usb reset irq callback.
|
||||||
*/
|
*/
|
||||||
void usbd_event_reset_handler(void);
|
void usbd_event_reset_handler(uint8_t busid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Usb setup packet recv irq callback.
|
* @brief Usb setup packet recv irq callback.
|
||||||
* @param[in] psetup setup packet.
|
* @param[in] psetup setup packet.
|
||||||
*/
|
*/
|
||||||
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
|
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief In ep transfer complete irq callback.
|
* @brief In ep transfer complete irq callback.
|
||||||
@@ -168,7 +168,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
|
|||||||
* listed in the device configuration table
|
* listed in the device configuration table
|
||||||
* @param[in] nbytes How many nbytes have transferred.
|
* @param[in] nbytes How many nbytes have transferred.
|
||||||
*/
|
*/
|
||||||
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
|
void usbd_event_ep_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Out ep transfer complete irq callback.
|
* @brief Out ep transfer complete irq callback.
|
||||||
@@ -176,7 +176,16 @@ void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
|
|||||||
* listed in the device configuration table
|
* listed in the device configuration table
|
||||||
* @param[in] nbytes How many nbytes have transferred.
|
* @param[in] nbytes How many nbytes have transferred.
|
||||||
*/
|
*/
|
||||||
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes);
|
void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||||
|
/**
|
||||||
|
* @brief Usb execute test mode
|
||||||
|
* @param[in] busid device busid
|
||||||
|
* @param[in] test_mode usb test mode
|
||||||
|
*/
|
||||||
|
void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ extern "C" {
|
|||||||
|
|
||||||
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
|
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
|
||||||
|
|
||||||
|
struct usbh_bus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USB Iso Configuration.
|
* @brief USB Iso Configuration.
|
||||||
*
|
*
|
||||||
@@ -36,6 +38,7 @@ struct usbh_urb {
|
|||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
struct usb_endpoint_descriptor *ep;
|
struct usb_endpoint_descriptor *ep;
|
||||||
uint8_t data_toggle;
|
uint8_t data_toggle;
|
||||||
|
uint8_t interval;
|
||||||
struct usb_setup_packet *setup;
|
struct usb_setup_packet *setup;
|
||||||
uint8_t *transfer_buffer;
|
uint8_t *transfer_buffer;
|
||||||
uint32_t transfer_buffer_length;
|
uint32_t transfer_buffer_length;
|
||||||
@@ -59,21 +62,21 @@ struct usbh_urb {
|
|||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_hc_init(void);
|
int usb_hc_init(struct usbh_bus *bus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usb host controller hardware deinit.
|
* @brief usb host controller hardware deinit.
|
||||||
*
|
*
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usb_hc_deinit(void);
|
int usb_hc_deinit(struct usbh_bus *bus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get frame number.
|
* @brief Get frame number.
|
||||||
*
|
*
|
||||||
* @return frame number.
|
* @return frame number.
|
||||||
*/
|
*/
|
||||||
uint16_t usbh_get_frame_number(void);
|
uint16_t usbh_get_frame_number(struct usbh_bus *bus);
|
||||||
/**
|
/**
|
||||||
* @brief control roothub.
|
* @brief control roothub.
|
||||||
*
|
*
|
||||||
@@ -81,7 +84,7 @@ uint16_t usbh_get_frame_number(void);
|
|||||||
* @param buf buf for reading response or write data.
|
* @param buf buf for reading response or write data.
|
||||||
* @return On success will return 0, and others indicate fail.
|
* @return On success will return 0, and others indicate fail.
|
||||||
*/
|
*/
|
||||||
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
|
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Submit a usb transfer request to an endpoint.
|
* @brief Submit a usb transfer request to an endpoint.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
|
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
|
||||||
|
|
||||||
@@ -16,6 +17,12 @@ typedef void *usb_osal_sem_t;
|
|||||||
typedef void *usb_osal_mutex_t;
|
typedef void *usb_osal_mutex_t;
|
||||||
typedef void *usb_osal_mq_t;
|
typedef void *usb_osal_mq_t;
|
||||||
typedef void (*usb_thread_entry_t)(void *argument);
|
typedef void (*usb_thread_entry_t)(void *argument);
|
||||||
|
typedef void (*usb_timer_handler_t)(void *argument);
|
||||||
|
struct usb_osal_timer {
|
||||||
|
usb_timer_handler_t handler;
|
||||||
|
void *argument;
|
||||||
|
void *timer;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Task with smaller priority value indicates higher task priority
|
* Task with smaller priority value indicates higher task priority
|
||||||
@@ -39,6 +46,11 @@ void usb_osal_mq_delete(usb_osal_mq_t mq);
|
|||||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
||||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
||||||
|
|
||||||
|
struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period);
|
||||||
|
void usb_osal_timer_delete(struct usb_osal_timer *timer);
|
||||||
|
void usb_osal_timer_start(struct usb_osal_timer *timer);
|
||||||
|
void usb_osal_timer_stop(struct usb_osal_timer *timer);
|
||||||
|
|
||||||
size_t usb_osal_enter_critical_section(void);
|
size_t usb_osal_enter_critical_section(void);
|
||||||
void usb_osal_leave_critical_section(size_t flag);
|
void usb_osal_leave_critical_section(size_t flag);
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||||
#ifndef __USED
|
#ifndef __USED
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __USED __attribute__((used))
|
#define __USED __attribute__((used))
|
||||||
#else
|
#else
|
||||||
#define __USED __root
|
#define __USED __root
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __WEAK
|
#ifndef __WEAK
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __WEAK __attribute__((weak))
|
#define __WEAK __attribute__((weak))
|
||||||
#else
|
#else
|
||||||
#define __WEAK _Pragma("__weak")
|
#define __WEAK _Pragma("__weak")
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __PACKED
|
#ifndef __PACKED
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __PACKED __attribute__((packed, aligned(1)))
|
#define __PACKED __attribute__((packed, aligned(1)))
|
||||||
#else
|
#else
|
||||||
/* Needs IAR language extensions */
|
/* Needs IAR language extensions */
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __PACKED_STRUCT
|
#ifndef __PACKED_STRUCT
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||||
#else
|
#else
|
||||||
/* Needs IAR language extensions */
|
/* Needs IAR language extensions */
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __PACKED_UNION
|
#ifndef __PACKED_UNION
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||||
#else
|
#else
|
||||||
/* Needs IAR language extensions */
|
/* Needs IAR language extensions */
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __ALIGNED
|
#ifndef __ALIGNED
|
||||||
#if defined(__ICCARM_V8) || defined (__ICCRISCV__)
|
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
|
||||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
#elif (__VER__ >= 7080000)
|
#elif (__VER__ >= 7080000)
|
||||||
/* Needs IAR language extensions */
|
/* Needs IAR language extensions */
|
||||||
@@ -205,4 +205,6 @@
|
|||||||
|
|
||||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||||
|
|
||||||
|
#define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
|
||||||
|
|
||||||
#endif /* USB_UTIL_H */
|
#endif /* USB_UTIL_H */
|
||||||
|
|||||||
525
core/usbd_core.c
@@ -38,12 +38,14 @@ enum usbd_event_type {
|
|||||||
USBD_EVENT_SET_INTERFACE, /** USB interface selected */
|
USBD_EVENT_SET_INTERFACE, /** USB interface selected */
|
||||||
USBD_EVENT_SET_REMOTE_WAKEUP, /** USB set remote wakeup */
|
USBD_EVENT_SET_REMOTE_WAKEUP, /** USB set remote wakeup */
|
||||||
USBD_EVENT_CLR_REMOTE_WAKEUP, /** USB clear remote wakeup */
|
USBD_EVENT_CLR_REMOTE_WAKEUP, /** USB clear remote wakeup */
|
||||||
|
USBD_EVENT_INIT, /** USB init done when call usbd_initialize */
|
||||||
|
USBD_EVENT_DEINIT, /** USB deinit done when call usbd_deinitialize */
|
||||||
USBD_EVENT_UNKNOWN
|
USBD_EVENT_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
|
typedef int (*usbd_request_handler)(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
|
||||||
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
|
typedef void (*usbd_endpoint_callback)(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||||
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
typedef void (*usbd_notify_handler)(uint8_t busid, uint8_t event, void *arg);
|
||||||
|
|
||||||
struct usbd_endpoint {
|
struct usbd_endpoint {
|
||||||
uint8_t ep_addr;
|
uint8_t ep_addr;
|
||||||
@@ -72,23 +74,32 @@ struct usb_descriptor {
|
|||||||
const struct usb_bos_descriptor *bos_descriptor;
|
const struct usb_bos_descriptor *bos_descriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
struct usbd_bus {
|
||||||
void usbd_desc_register(const struct usb_descriptor *desc);
|
uint8_t busid;
|
||||||
#else
|
uint32_t reg_base;
|
||||||
void usbd_desc_register(const uint8_t *desc);
|
};
|
||||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
|
|
||||||
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
|
extern struct usbd_bus g_usbdev_bus[];
|
||||||
void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
|
|
||||||
|
#ifdef USBD_IRQHandler
|
||||||
|
#error USBD_IRQHandler is obsolete, please call USBD_IRQHandler(xxx) in your irq
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usbd_add_interface(struct usbd_interface *intf);
|
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||||
void usbd_add_endpoint(struct usbd_endpoint *ep);
|
void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc);
|
||||||
|
#else
|
||||||
|
void usbd_desc_register(uint8_t busid, const uint8_t *desc);
|
||||||
|
void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc);
|
||||||
|
void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc);
|
||||||
|
void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool usb_device_is_configured(void);
|
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
|
||||||
int usbd_initialize(void);
|
void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
|
||||||
int usbd_deinitialize(void);
|
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event);
|
bool usb_device_is_configured(uint8_t busid);
|
||||||
|
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
|
||||||
|
int usbd_deinitialize(uint8_t busid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
298
core/usbh_core.c
@@ -5,36 +5,28 @@
|
|||||||
*/
|
*/
|
||||||
#include "usbh_core.h"
|
#include "usbh_core.h"
|
||||||
|
|
||||||
|
#undef USB_DBG_TAG
|
||||||
|
#define USB_DBG_TAG "usbh_core"
|
||||||
|
#include "usb_log.h"
|
||||||
|
|
||||||
struct usbh_class_info *usbh_class_info_table_begin = NULL;
|
struct usbh_class_info *usbh_class_info_table_begin = NULL;
|
||||||
struct usbh_class_info *usbh_class_info_table_end = NULL;
|
struct usbh_class_info *usbh_class_info_table_end = NULL;
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN];
|
usb_slist_t g_bus_head = USB_SLIST_OBJECT_INIT(g_bus_head);
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(CONFIG_USBHOST_REQUEST_BUFFER_LEN, CONFIG_USB_ALIGN_SIZE)];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup_buffer[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
|
||||||
|
|
||||||
|
struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
|
||||||
|
|
||||||
/* general descriptor field offsets */
|
/* general descriptor field offsets */
|
||||||
#define DESC_bLength 0 /** Length offset */
|
#define DESC_bLength 0 /** Length offset */
|
||||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||||
|
|
||||||
#define USB_DEV_ADDR_MAX 0x7f
|
#define USB_DEV_ADDR_MAX 0x7f
|
||||||
#define USB_DEV_ADDR_MARK_OFFSET 5
|
#define USB_DEV_ADDR_MARK_OFFSET 5
|
||||||
#define USB_DEV_ADDR_MARK_MASK 0x1f
|
#define USB_DEV_ADDR_MARK_MASK 0x1f
|
||||||
|
|
||||||
struct usbh_devaddr_map {
|
|
||||||
/**
|
|
||||||
* alloctab[0]:addr from 0~31
|
|
||||||
* alloctab[1]:addr from 32~63
|
|
||||||
* alloctab[2]:addr from 64~95
|
|
||||||
* alloctab[3]:addr from 96~127
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint8_t next; /* Next device address */
|
|
||||||
uint32_t alloctab[4]; /* Bit allocation table */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct usbh_bus {
|
|
||||||
struct usbh_devaddr_map devgen;
|
|
||||||
} g_usbh_bus;
|
|
||||||
|
|
||||||
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
|
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
|
||||||
{
|
{
|
||||||
uint8_t startaddr = devgen->next;
|
uint8_t startaddr = devgen->next;
|
||||||
@@ -93,31 +85,22 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
|
|||||||
struct usbh_class_info *index = NULL;
|
struct usbh_class_info *index = NULL;
|
||||||
|
|
||||||
for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
|
for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
|
||||||
if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
|
if ((index->match_flags & USB_CLASS_MATCH_VENDOR) && !(index->vid == vid)) {
|
||||||
(USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
|
continue;
|
||||||
if (index->vid == vid && index->pid == pid &&
|
|
||||||
index->class == class && index->subclass == subclass && index->protocol == protocol) {
|
|
||||||
return index->class_driver;
|
|
||||||
}
|
|
||||||
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
|
|
||||||
(USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
|
|
||||||
if (index->class == class && index->subclass == subclass && index->protocol == protocol) {
|
|
||||||
return index->class_driver;
|
|
||||||
}
|
|
||||||
} else if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) ==
|
|
||||||
(USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) {
|
|
||||||
if (index->vid == vid && index->pid == pid && index->class == class) {
|
|
||||||
return index->class_driver;
|
|
||||||
}
|
|
||||||
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) == (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) {
|
|
||||||
if (index->class == class && index->subclass == subclass) {
|
|
||||||
return index->class_driver;
|
|
||||||
}
|
|
||||||
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) == USB_CLASS_MATCH_INTF_CLASS) {
|
|
||||||
if (index->class == class) {
|
|
||||||
return index->class_driver;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if ((index->match_flags & USB_CLASS_MATCH_PRODUCT) && !(index->pid == pid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return index->class_driver;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -227,15 +210,18 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
|||||||
cur_ep = 0;
|
cur_ep = 0;
|
||||||
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
|
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
|
||||||
USB_LOG_ERR("Interface num overflow\r\n");
|
USB_LOG_ERR("Interface num overflow\r\n");
|
||||||
return -USB_ERR_NOMEM;
|
while (1) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
|
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
|
||||||
USB_LOG_ERR("Interface altsetting num overflow\r\n");
|
USB_LOG_ERR("Interface altsetting num overflow\r\n");
|
||||||
return -USB_ERR_NOMEM;
|
while (1) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
|
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
|
||||||
USB_LOG_ERR("Endpoint num overflow\r\n");
|
USB_LOG_ERR("Endpoint num overflow\r\n");
|
||||||
return -USB_ERR_NOMEM;
|
while (1) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
USB_LOG_DBG("Interface Descriptor:\r\n");
|
USB_LOG_DBG("Interface Descriptor:\r\n");
|
||||||
@@ -343,7 +329,7 @@ int usbh_free_devaddr(struct usbh_hubport *hport)
|
|||||||
{
|
{
|
||||||
#ifndef CONFIG_USBHOST_XHCI
|
#ifndef CONFIG_USBHOST_XHCI
|
||||||
if (hport->dev_addr > 0) {
|
if (hport->dev_addr > 0) {
|
||||||
__usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
|
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -368,12 +354,12 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
|
|||||||
setup->wIndex = 0x0409;
|
setup->wIndex = 0x0409;
|
||||||
setup->wLength = 255;
|
setup->wLength = 255;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
src = ep0_request_buffer;
|
src = ep0_request_buffer[hport->bus->busid];
|
||||||
dst = output;
|
dst = output;
|
||||||
len = src[0];
|
len = src[0];
|
||||||
|
|
||||||
@@ -407,9 +393,10 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
struct usb_endpoint_descriptor *ep;
|
struct usb_endpoint_descriptor *ep;
|
||||||
int dev_addr;
|
int dev_addr;
|
||||||
uint16_t ep_mps;
|
uint16_t ep_mps;
|
||||||
|
uint8_t config_value;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1];
|
hport->setup = &g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
|
||||||
setup = hport->setup;
|
setup = hport->setup;
|
||||||
ep = &hport->ep0;
|
ep = &hport->ep0;
|
||||||
|
|
||||||
@@ -431,16 +418,16 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = 8;
|
setup->wLength = 8;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, 8);
|
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
|
||||||
|
|
||||||
/* Extract the correct max packetsize from the device descriptor */
|
/* Extract the correct max packetsize from the device descriptor */
|
||||||
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer;
|
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
|
||||||
if (dev_desc->bcdUSB >= USB_3_0) {
|
if (dev_desc->bcdUSB >= USB_3_0) {
|
||||||
ep_mps = 1 << dev_desc->bMaxPacketSize0;
|
ep_mps = 1 << dev_desc->bMaxPacketSize0;
|
||||||
} else {
|
} else {
|
||||||
@@ -465,7 +452,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Assign a function address to the device connected to this port */
|
/* Assign a function address to the device connected to this port */
|
||||||
dev_addr = usbh_allocate_devaddr(&g_usbh_bus.devgen);
|
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
|
||||||
if (dev_addr < 0) {
|
if (dev_addr < 0) {
|
||||||
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -498,17 +485,17 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = USB_SIZEOF_DEVICE_DESC;
|
setup->wLength = USB_SIZEOF_DEVICE_DESC;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, USB_SIZEOF_DEVICE_DESC);
|
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
|
||||||
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
|
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
|
||||||
((struct usb_device_descriptor *)ep0_request_buffer)->idVendor,
|
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
|
||||||
((struct usb_device_descriptor *)ep0_request_buffer)->idProduct,
|
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
|
||||||
((struct usb_device_descriptor *)ep0_request_buffer)->bcdDevice);
|
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
|
||||||
|
|
||||||
/* Read the first 9 bytes of the config descriptor */
|
/* Read the first 9 bytes of the config descriptor */
|
||||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
@@ -517,16 +504,16 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = USB_SIZEOF_CONFIG_DESC;
|
setup->wLength = USB_SIZEOF_CONFIG_DESC;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, USB_SIZEOF_CONFIG_DESC);
|
parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_CONFIG_DESC);
|
||||||
|
|
||||||
/* Read the full size of the configuration data */
|
/* Read the full size of the configuration data */
|
||||||
uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer)->wTotalLength;
|
uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->wTotalLength;
|
||||||
|
|
||||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
@@ -534,25 +521,27 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = wTotalLength;
|
setup->wLength = wTotalLength;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, wTotalLength);
|
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
USB_LOG_ERR("Parse config fail\r\n");
|
USB_LOG_ERR("Parse config fail\r\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces);
|
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
|
||||||
hport->raw_config_desc = usb_malloc(wTotalLength);
|
hport->raw_config_desc = usb_malloc(wTotalLength);
|
||||||
if (hport->raw_config_desc == NULL) {
|
if (hport->raw_config_desc == NULL) {
|
||||||
ret = -USB_ERR_NOMEM;
|
ret = -USB_ERR_NOMEM;
|
||||||
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memcpy(hport->raw_config_desc, ep0_request_buffer, wTotalLength);
|
|
||||||
|
config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
|
||||||
|
memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
|
||||||
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
||||||
uint8_t string_buffer[128];
|
uint8_t string_buffer[128];
|
||||||
|
|
||||||
@@ -589,7 +578,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
/* Select device configuration 1 */
|
/* Select device configuration 1 */
|
||||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
|
setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
|
||||||
setup->wValue = 1;
|
setup->wValue = config_value;
|
||||||
setup->wIndex = 0;
|
setup->wIndex = 0;
|
||||||
setup->wLength = 0;
|
setup->wLength = 0;
|
||||||
|
|
||||||
@@ -606,7 +595,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wIndex = 0x0004;
|
setup->wIndex = 0x0004;
|
||||||
setup->wLength = 16;
|
setup->wLength = 16;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||||
if (ret < 0 && (ret != -EPERM)) {
|
if (ret < 0 && (ret != -EPERM)) {
|
||||||
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
|
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -640,9 +629,48 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_initialize(void)
|
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
|
struct usbh_hub *hub;
|
||||||
|
|
||||||
|
memset(bus, 0, sizeof(struct usbh_bus));
|
||||||
|
bus->busid = busid;
|
||||||
|
bus->hcd.hcd_id = busid;
|
||||||
|
bus->hcd.reg_base = reg_base;
|
||||||
|
|
||||||
|
/* devaddr 1 is for roothub */
|
||||||
|
bus->devgen.next = 2;
|
||||||
|
|
||||||
|
usb_slist_init(&bus->hub_list);
|
||||||
|
|
||||||
|
hub = &bus->hcd.roothub;
|
||||||
|
hub->connected = true;
|
||||||
|
hub->index = 1;
|
||||||
|
hub->is_roothub = true;
|
||||||
|
hub->parent = NULL;
|
||||||
|
hub->hub_addr = 1;
|
||||||
|
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
|
||||||
|
hub->int_buffer = bus->hcd.roothub_intbuf;
|
||||||
|
hub->bus = bus;
|
||||||
|
|
||||||
|
usb_slist_init(&bus->hub_list);
|
||||||
|
usb_slist_add_tail(&bus->hub_list, &hub->list);
|
||||||
|
usb_slist_add_tail(&g_bus_head, &bus->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_initialize(uint8_t busid, uint32_t reg_base)
|
||||||
|
{
|
||||||
|
struct usbh_bus *bus;
|
||||||
|
|
||||||
|
if (busid >= CONFIG_USBHOST_MAX_BUS) {
|
||||||
|
USB_LOG_ERR("bus overflow\r\n");
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bus = &g_usbhost_bus[busid];
|
||||||
|
|
||||||
|
usbh_bus_init(bus, busid, reg_base);
|
||||||
|
|
||||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||||
extern const int usbh_class_info$$Base;
|
extern const int usbh_class_info$$Base;
|
||||||
@@ -654,21 +682,26 @@ int usbh_initialize(void)
|
|||||||
extern uint32_t __usbh_class_info_end__;
|
extern uint32_t __usbh_class_info_end__;
|
||||||
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
|
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
|
||||||
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
|
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
|
||||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||||
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin("usbh_class_info");
|
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin(".usbh_class_info");
|
||||||
usbh_class_info_table_end = (struct usbh_class_info *)__section_end("usbh_class_info");
|
usbh_class_info_table_end = (struct usbh_class_info *)__section_end(".usbh_class_info");
|
||||||
#endif
|
#endif
|
||||||
|
usbh_hub_initialize(bus);
|
||||||
/* devaddr 1 is for roothub */
|
|
||||||
g_usbh_bus.devgen.next = 2;
|
|
||||||
|
|
||||||
usbh_hub_initialize();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_deinitialize(void)
|
int usbh_deinitialize(uint8_t busid)
|
||||||
{
|
{
|
||||||
return usbh_hub_deinitialize();
|
struct usbh_bus *bus;
|
||||||
|
|
||||||
|
bus = &g_usbhost_bus[busid];
|
||||||
|
|
||||||
|
usbh_hub_deinitialize(bus);
|
||||||
|
|
||||||
|
usb_slist_init(&bus->hub_list);
|
||||||
|
usb_slist_remove(&g_bus_head, &bus->list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||||
@@ -695,16 +728,21 @@ void *usbh_find_class_instance(const char *devname)
|
|||||||
{
|
{
|
||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
usb_slist_t *hub_list;
|
usb_slist_t *hub_list;
|
||||||
|
usb_slist_t *bus_list;
|
||||||
|
|
||||||
usb_slist_for_each(hub_list, &hub_class_head)
|
usb_slist_for_each(bus_list, &g_bus_head)
|
||||||
{
|
{
|
||||||
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
usb_slist_for_each(hub_list, &bus->hub_list)
|
||||||
hport = &hub->child[port];
|
{
|
||||||
if (hport->connected) {
|
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
hport = &hub->child[port];
|
||||||
return hport->config.intf[itf].priv;
|
if (hport->connected) {
|
||||||
|
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||||
|
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
||||||
|
return hport->config.intf[itf].priv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,7 +752,8 @@ void *usbh_find_class_instance(const char *devname)
|
|||||||
|
|
||||||
int lsusb(int argc, char **argv)
|
int lsusb(int argc, char **argv)
|
||||||
{
|
{
|
||||||
usb_slist_t *i;
|
usb_slist_t *hub_list;
|
||||||
|
usb_slist_t *bus_list;
|
||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@@ -739,30 +778,38 @@ int lsusb(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(argv[1], "-t") == 0) {
|
if (strcmp(argv[1], "-t") == 0) {
|
||||||
usb_slist_for_each(i, &hub_class_head)
|
usb_slist_for_each(bus_list, &g_bus_head)
|
||||||
{
|
{
|
||||||
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
|
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||||
|
usb_slist_for_each(hub_list, &bus->hub_list)
|
||||||
|
{
|
||||||
|
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||||
|
|
||||||
if (hub->is_roothub) {
|
if (hub->is_roothub) {
|
||||||
USB_LOG_RAW("/: Hub %02u, ports=%u, is roothub\r\n", hub->index, hub->hub_desc.bNbrPorts);
|
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
|
||||||
} else {
|
bus->busid,
|
||||||
USB_LOG_RAW("/: Hub %02u, ports=%u, mounted on Hub %02u:Port %u\r\n",
|
hub->index,
|
||||||
hub->index,
|
hub->hub_desc.bNbrPorts);
|
||||||
hub->hub_desc.bNbrPorts,
|
} else {
|
||||||
hub->parent->parent->index,
|
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, mounted on Hub %02u:Port %u\r\n",
|
||||||
hub->parent->port);
|
bus->busid,
|
||||||
}
|
hub->index,
|
||||||
|
hub->hub_desc.bNbrPorts,
|
||||||
|
hub->parent->parent->index,
|
||||||
|
hub->parent->port);
|
||||||
|
}
|
||||||
|
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
hport = &hub->child[port];
|
hport = &hub->child[port];
|
||||||
if (hport->connected) {
|
if (hport->connected) {
|
||||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||||
if (hport->config.intf[i].class_driver->driver_name) {
|
if (hport->config.intf[i].class_driver->driver_name) {
|
||||||
USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n",
|
USB_LOG_RAW("\t|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
|
||||||
hport->port,
|
hport->port,
|
||||||
hport->dev_addr,
|
hport->dev_addr,
|
||||||
i,
|
i,
|
||||||
hport->config.intf[i].class_driver->driver_name);
|
hport->config.intf[i].class_driver->driver_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -771,19 +818,24 @@ int lsusb(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(argv[1], "-v") == 0) {
|
if (strcmp(argv[1], "-v") == 0) {
|
||||||
usb_slist_for_each(i, &hub_class_head)
|
usb_slist_for_each(bus_list, &g_bus_head)
|
||||||
{
|
{
|
||||||
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
|
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
usb_slist_for_each(hub_list, &bus->hub_list)
|
||||||
hport = &hub->child[port];
|
{
|
||||||
if (hport->connected) {
|
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||||
USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n",
|
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||||
hub->index,
|
hport = &hub->child[port];
|
||||||
hport->port,
|
if (hport->connected) {
|
||||||
hport->dev_addr,
|
USB_LOG_RAW("Bus %u, Hub %02u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
|
||||||
hport->device_desc.idVendor,
|
bus->busid,
|
||||||
hport->device_desc.idProduct);
|
hub->index,
|
||||||
usbh_print_hubport_info(hport);
|
hport->port,
|
||||||
|
hport->dev_addr,
|
||||||
|
hport->device_desc.idVendor,
|
||||||
|
hport->device_desc.idProduct);
|
||||||
|
usbh_print_hubport_info(hport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,18 +31,20 @@ extern "C" {
|
|||||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||||
|
|
||||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||||
|
|
||||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||||
#pragma section = "usbh_class_info"
|
#pragma section = ".usbh_class_info"
|
||||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval: (1 << (interval - 1)))
|
||||||
|
|
||||||
#define USBH_EP_INIT(ep, ep_desc) \
|
#define USBH_EP_INIT(ep, ep_desc) \
|
||||||
do { \
|
do { \
|
||||||
ep = ep_desc; \
|
ep = ep_desc; \
|
||||||
@@ -106,6 +108,7 @@ struct usbh_hubport {
|
|||||||
uint8_t *raw_config_desc;
|
uint8_t *raw_config_desc;
|
||||||
struct usb_setup_packet *setup;
|
struct usb_setup_packet *setup;
|
||||||
struct usbh_hub *parent;
|
struct usbh_hub *parent;
|
||||||
|
struct usbh_bus *bus;
|
||||||
#ifdef CONFIG_USBHOST_XHCI
|
#ifdef CONFIG_USBHOST_XHCI
|
||||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||||
#endif
|
#endif
|
||||||
@@ -123,9 +126,40 @@ struct usbh_hub {
|
|||||||
struct usb_hub_descriptor hub_desc;
|
struct usb_hub_descriptor hub_desc;
|
||||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||||
struct usbh_hubport *parent;
|
struct usbh_hubport *parent;
|
||||||
|
struct usbh_bus *bus;
|
||||||
struct usb_endpoint_descriptor *intin;
|
struct usb_endpoint_descriptor *intin;
|
||||||
struct usbh_urb intin_urb;
|
struct usbh_urb intin_urb;
|
||||||
uint8_t *int_buffer;
|
uint8_t *int_buffer;
|
||||||
|
struct usb_osal_timer *int_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbh_devaddr_map {
|
||||||
|
/**
|
||||||
|
* alloctab[0]:addr from 0~31
|
||||||
|
* alloctab[1]:addr from 32~63
|
||||||
|
* alloctab[2]:addr from 64~95
|
||||||
|
* alloctab[3]:addr from 96~127
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t next; /* Next device address */
|
||||||
|
uint32_t alloctab[4]; /* Bit allocation table */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbh_hcd {
|
||||||
|
uint32_t reg_base;
|
||||||
|
uint8_t hcd_id;
|
||||||
|
uint8_t roothub_intbuf[1];
|
||||||
|
struct usbh_hub roothub;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbh_bus {
|
||||||
|
usb_slist_t list;
|
||||||
|
uint8_t busid;
|
||||||
|
struct usbh_hcd hcd;
|
||||||
|
struct usbh_devaddr_map devgen;
|
||||||
|
usb_osal_thread_t hub_thread;
|
||||||
|
usb_osal_mq_t hub_mq;
|
||||||
|
usb_slist_t hub_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||||
@@ -183,8 +217,14 @@ static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
|||||||
urb->timeout = timeout;
|
urb->timeout = timeout;
|
||||||
urb->complete = complete;
|
urb->complete = complete;
|
||||||
urb->arg = arg;
|
urb->arg = arg;
|
||||||
|
urb->interval = USBH_GET_URB_INTERVAL(ep->bInterval, hport->speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct usbh_bus g_usbhost_bus[];
|
||||||
|
#ifdef USBH_IRQHandler
|
||||||
|
#error USBH_IRQHandler is obsolete, please call USBH_IRQHandler(xxx) in your irq
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Submit an control transfer to an endpoint.
|
* @brief Submit an control transfer to an endpoint.
|
||||||
* This is a blocking method; this method will not return until the transfer has completed.
|
* This is a blocking method; this method will not return until the transfer has completed.
|
||||||
@@ -225,8 +265,8 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
|
|||||||
*/
|
*/
|
||||||
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
|
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
|
||||||
|
|
||||||
int usbh_initialize(void);
|
int usbh_initialize(uint8_t busid, uint32_t reg_base);
|
||||||
int usbh_deinitialize(void);
|
int usbh_deinitialize(uint8_t busid);
|
||||||
void *usbh_find_class_instance(const char *devname);
|
void *usbh_find_class_instance(const char *devname);
|
||||||
|
|
||||||
int lsusb(int argc, char **argv);
|
int lsusb(int argc, char **argv);
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ const uint8_t audio_v1_descriptor[] = {
|
|||||||
volatile bool tx_flag = 0;
|
volatile bool tx_flag = 0;
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -173,19 +173,21 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
tx_flag = 1;
|
tx_flag = 1;
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
USB_LOG_RAW("OPEN\r\n");
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("CLOSE\r\n");
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
tx_flag = 0;
|
tx_flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_iso_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
@@ -205,25 +207,25 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_IN_EP },
|
.ep = AUDIO_IN_EP },
|
||||||
};
|
};
|
||||||
|
|
||||||
void audio_v1_init(void)
|
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(audio_v1_descriptor);
|
usbd_desc_register(busid, audio_v1_descriptor);
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 1));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 1));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
|
||||||
usbd_add_endpoint(&audio_in_ep);
|
usbd_add_endpoint(busid, &audio_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
||||||
|
|
||||||
void audio_test()
|
void audio_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||||
ep_tx_busy_flag = true;
|
ep_tx_busy_flag = true;
|
||||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||||
while (ep_tx_busy_flag) {
|
while (ep_tx_busy_flag) {
|
||||||
if (tx_flag == false) {
|
if (tx_flag == false) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ volatile bool tx_flag = 0;
|
|||||||
volatile bool rx_flag = 0;
|
volatile bool rx_flag = 0;
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -172,23 +172,25 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
if (intf == 1) {
|
if (intf == 1) {
|
||||||
rx_flag = 1;
|
rx_flag = 1;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
printf("OPEN1\r\n");
|
printf("OPEN1\r\n");
|
||||||
} else {
|
} else {
|
||||||
tx_flag = 1;
|
tx_flag = 1;
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
printf("OPEN2\r\n");
|
printf("OPEN2\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
if (intf == 1) {
|
if (intf == 1) {
|
||||||
rx_flag = 1;
|
rx_flag = 1;
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
printf("CLOSE1\r\n");
|
printf("CLOSE1\r\n");
|
||||||
} else {
|
} else {
|
||||||
tx_flag = 0;
|
tx_flag = 0;
|
||||||
@@ -196,13 +198,13 @@ void usbd_audio_close(uint8_t intf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
@@ -231,24 +233,24 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_OUT_EP },
|
.ep = AUDIO_OUT_EP },
|
||||||
};
|
};
|
||||||
|
|
||||||
void audio_v1_init(void)
|
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(audio_v1_descriptor);
|
usbd_desc_register(busid, audio_v1_descriptor);
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 2));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
|
||||||
usbd_add_endpoint(&audio_in_ep);
|
usbd_add_endpoint(busid, &audio_in_ep);
|
||||||
usbd_add_endpoint(&audio_out_ep);
|
usbd_add_endpoint(busid, &audio_out_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_v1_test(void)
|
void audio_v1_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
memset(write_buffer, 'a', AUDIO_IN_PACKET);
|
||||||
ep_tx_busy_flag = true;
|
ep_tx_busy_flag = true;
|
||||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
|
||||||
while (ep_tx_busy_flag) {
|
while (ep_tx_busy_flag) {
|
||||||
if (tx_flag == false) {
|
if (tx_flag == false) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ static const uint8_t mic_default_sampling_freq_table[] = {
|
|||||||
|
|
||||||
volatile bool tx_flag = 0;
|
volatile bool tx_flag = 0;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -184,26 +184,26 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
tx_flag = 1;
|
tx_flag = 1;
|
||||||
USB_LOG_RAW("OPEN\r\n");
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("CLOSE\r\n");
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
tx_flag = 0;
|
tx_flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
if (ep == AUDIO_IN_EP) {
|
if (ep == AUDIO_IN_EP) {
|
||||||
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,17 +224,17 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_IN_EP },
|
.ep = AUDIO_IN_EP },
|
||||||
};
|
};
|
||||||
|
|
||||||
void audio_v2_init(void)
|
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(audio_v2_descriptor);
|
usbd_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
|
||||||
usbd_add_endpoint(&audio_in_ep);
|
usbd_add_endpoint(busid, &audio_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_v2_test(void)
|
void audio_v2_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
|
|||||||
volatile bool tx_flag = 0;
|
volatile bool tx_flag = 0;
|
||||||
volatile bool rx_flag = 0;
|
volatile bool rx_flag = 0;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -254,12 +254,12 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
if (intf == 1) {
|
if (intf == 1) {
|
||||||
rx_flag = 1;
|
rx_flag = 1;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
USB_LOG_RAW("OPEN1\r\n");
|
USB_LOG_RAW("OPEN1\r\n");
|
||||||
} else {
|
} else {
|
||||||
tx_flag = 1;
|
tx_flag = 1;
|
||||||
@@ -267,7 +267,7 @@ void usbd_audio_open(uint8_t intf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
if (intf == 1) {
|
if (intf == 1) {
|
||||||
rx_flag = 1;
|
rx_flag = 1;
|
||||||
@@ -278,7 +278,7 @@ void usbd_audio_close(uint8_t intf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
if (ep == AUDIO_OUT_EP) {
|
if (ep == AUDIO_OUT_EP) {
|
||||||
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
|
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
|
||||||
@@ -288,7 +288,7 @@ void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_tabl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
|
||||||
{
|
{
|
||||||
uint16_t packet_size = 0;
|
uint16_t packet_size = 0;
|
||||||
if (ep == AUDIO_OUT_EP) {
|
if (ep == AUDIO_OUT_EP) {
|
||||||
@@ -302,13 +302,13 @@ void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,19 +341,19 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_IN_EP },
|
.ep = AUDIO_IN_EP },
|
||||||
};
|
};
|
||||||
|
|
||||||
void audio_v2_init(void)
|
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(audio_v2_descriptor);
|
usbd_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
|
||||||
usbd_add_endpoint(&audio_in_ep);
|
usbd_add_endpoint(busid, &audio_in_ep);
|
||||||
usbd_add_endpoint(&audio_out_ep);
|
usbd_add_endpoint(busid, &audio_out_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_v2_test(void)
|
void audio_v2_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
|
|||||||
|
|
||||||
volatile bool rx_flag = 0;
|
volatile bool rx_flag = 0;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -198,31 +198,31 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
rx_flag = 1;
|
rx_flag = 1;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
USB_LOG_RAW("OPEN\r\n");
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("CLOSE\r\n");
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
rx_flag = 0;
|
rx_flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
|
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
if (ep == AUDIO_OUT_EP) {
|
if (ep == AUDIO_OUT_EP) {
|
||||||
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usbd_endpoint audio_out_ep = {
|
static struct usbd_endpoint audio_out_ep = {
|
||||||
@@ -242,17 +242,17 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_OUT_EP },
|
.ep = AUDIO_OUT_EP },
|
||||||
};
|
};
|
||||||
|
|
||||||
void audio_v2_init(void)
|
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(audio_v2_descriptor);
|
usbd_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||||
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
|
||||||
usbd_add_endpoint(&audio_out_ep);
|
usbd_add_endpoint(busid, &audio_out_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_v2_test(void)
|
void audio_v2_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (rx_flag) {
|
if (rx_flag) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ static struct hid_mouse mouse_cfg;
|
|||||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
/* function ------------------------------------------------------------------*/
|
/* function ------------------------------------------------------------------*/
|
||||||
static void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
|
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
hid_state = HID_STATE_IDLE;
|
hid_state = HID_STATE_IDLE;
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ static struct usbd_endpoint hid_in_ep = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||||
|
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ volatile bool ep_tx_busy_flag = false;
|
|||||||
#define CDC_MAX_MPS 64
|
#define CDC_MAX_MPS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -252,8 +252,10 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
|
hid_state = HID_STATE_IDLE;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -265,20 +267,20 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
}
|
}
|
||||||
@@ -300,19 +302,19 @@ struct usbd_interface intf1;
|
|||||||
struct usbd_interface intf2;
|
struct usbd_interface intf2;
|
||||||
struct usbd_interface intf3;
|
struct usbd_interface intf3;
|
||||||
|
|
||||||
void cdc_acm_hid_msc_descriptor_init(void)
|
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(cdc_acm_hid_msc_descriptor);
|
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
|
||||||
|
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||||
usbd_add_endpoint(&cdc_out_ep);
|
usbd_add_endpoint(busid, &cdc_out_ep);
|
||||||
usbd_add_endpoint(&cdc_in_ep);
|
usbd_add_endpoint(busid, &cdc_in_ep);
|
||||||
|
|
||||||
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
|
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
|
||||||
|
|
||||||
usbd_add_interface(usbd_hid_init_intf(&intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||||
usbd_add_endpoint(&hid_in_ep);
|
usbd_add_endpoint(busid, &hid_in_ep);
|
||||||
|
|
||||||
/*!< init mouse report data */
|
/*!< init mouse report data */
|
||||||
mouse_cfg.buttons = 0;
|
mouse_cfg.buttons = 0;
|
||||||
@@ -320,7 +322,7 @@ void cdc_acm_hid_msc_descriptor_init(void)
|
|||||||
mouse_cfg.x = 0;
|
mouse_cfg.x = 0;
|
||||||
mouse_cfg.y = 0;
|
mouse_cfg.y = 0;
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -329,12 +331,12 @@ void cdc_acm_hid_msc_descriptor_init(void)
|
|||||||
* @param[in] none
|
* @param[in] none
|
||||||
* @retval none
|
* @retval none
|
||||||
*/
|
*/
|
||||||
void hid_mouse_test(void)
|
void hid_mouse_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
/*!< move mouse pointer */
|
/*!< move mouse pointer */
|
||||||
mouse_cfg.x += 10;
|
mouse_cfg.x += 10;
|
||||||
mouse_cfg.y = 0;
|
mouse_cfg.y = 0;
|
||||||
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -345,7 +347,7 @@ void hid_mouse_test(void)
|
|||||||
|
|
||||||
volatile uint8_t dtr_enable = 0;
|
volatile uint8_t dtr_enable = 0;
|
||||||
|
|
||||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||||
{
|
{
|
||||||
if (dtr) {
|
if (dtr) {
|
||||||
dtr_enable = 1;
|
dtr_enable = 1;
|
||||||
@@ -354,12 +356,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_acm_data_send_with_dtr_test(void)
|
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (dtr_enable) {
|
if (dtr_enable) {
|
||||||
memset(&write_buffer[10], 'a', 2038);
|
memset(&write_buffer[10], 'a', 2038);
|
||||||
ep_tx_busy_flag = true;
|
ep_tx_busy_flag = true;
|
||||||
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
|
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
|
||||||
while (ep_tx_busy_flag) {
|
while (ep_tx_busy_flag) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,19 +377,19 @@ typedef struct
|
|||||||
|
|
||||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||||
|
|
||||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||||
{
|
{
|
||||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||||
*block_size = BLOCK_SIZE;
|
*block_size = BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < 10)
|
if (sector < 10)
|
||||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < 10)
|
if (sector < 10)
|
||||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ static const uint8_t cdc_msc_descriptor[] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||||
|
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ volatile bool ep_tx_busy_flag = false;
|
|||||||
#define CDC_MAX_MPS 64
|
#define CDC_MAX_MPS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -263,8 +263,9 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -276,20 +277,20 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
}
|
}
|
||||||
@@ -310,25 +311,25 @@ struct usbd_interface intf0;
|
|||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
struct usbd_interface intf2;
|
struct usbd_interface intf2;
|
||||||
|
|
||||||
void cdc_acm_msc_init(void)
|
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||||
usbd_desc_register(&cdc_msc_descriptor);
|
usbd_desc_register(busid, &cdc_msc_descriptor);
|
||||||
#else
|
#else
|
||||||
usbd_desc_register(cdc_msc_descriptor);
|
usbd_desc_register(busid, cdc_msc_descriptor);
|
||||||
#endif
|
#endif
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||||
usbd_add_endpoint(&cdc_out_ep);
|
usbd_add_endpoint(busid, &cdc_out_ep);
|
||||||
usbd_add_endpoint(&cdc_in_ep);
|
usbd_add_endpoint(busid, &cdc_in_ep);
|
||||||
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
|
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile uint8_t dtr_enable = 0;
|
volatile uint8_t dtr_enable = 0;
|
||||||
|
|
||||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||||
{
|
{
|
||||||
if (dtr) {
|
if (dtr) {
|
||||||
dtr_enable = 1;
|
dtr_enable = 1;
|
||||||
@@ -337,12 +338,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_acm_data_send_with_dtr_test(void)
|
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (dtr_enable) {
|
if (dtr_enable) {
|
||||||
memset(&write_buffer[10], 'a', 2038);
|
memset(&write_buffer[10], 'a', 2038);
|
||||||
ep_tx_busy_flag = true;
|
ep_tx_busy_flag = true;
|
||||||
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
|
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
|
||||||
while (ep_tx_busy_flag) {
|
while (ep_tx_busy_flag) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,19 +359,19 @@ typedef struct
|
|||||||
|
|
||||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||||
|
|
||||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||||
{
|
{
|
||||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||||
*block_size = BLOCK_SIZE;
|
*block_size = BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < 10)
|
if (sector < 10)
|
||||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < 10)
|
if (sector < 10)
|
||||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ static const uint8_t cdc_descriptor[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[4][2048];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[4][2048];
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048];
|
||||||
|
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ volatile bool ep_tx_busy_flag = false;
|
|||||||
#define CDC_MAX_MPS 64
|
#define CDC_MAX_MPS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -139,11 +139,12 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP2, read_buffer, 2048);
|
||||||
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP3, read_buffer, 2048);
|
||||||
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP4, read_buffer, 2048);
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -155,14 +156,14 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
@@ -223,29 +224,29 @@ struct usbd_interface intf5;
|
|||||||
struct usbd_interface intf6;
|
struct usbd_interface intf6;
|
||||||
struct usbd_interface intf7;
|
struct usbd_interface intf7;
|
||||||
|
|
||||||
void cdc_acm_multi_init(void)
|
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(cdc_descriptor);
|
usbd_desc_register(busid, cdc_descriptor);
|
||||||
|
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||||
usbd_add_endpoint(&cdc_out_ep1);
|
usbd_add_endpoint(busid, &cdc_out_ep1);
|
||||||
usbd_add_endpoint(&cdc_in_ep1);
|
usbd_add_endpoint(busid, &cdc_in_ep1);
|
||||||
|
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf3));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf3));
|
||||||
usbd_add_endpoint(&cdc_out_ep2);
|
usbd_add_endpoint(busid, &cdc_out_ep2);
|
||||||
usbd_add_endpoint(&cdc_in_ep2);
|
usbd_add_endpoint(busid, &cdc_in_ep2);
|
||||||
|
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf4));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf4));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf5));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf5));
|
||||||
usbd_add_endpoint(&cdc_out_ep3);
|
usbd_add_endpoint(busid, &cdc_out_ep3);
|
||||||
usbd_add_endpoint(&cdc_in_ep3);
|
usbd_add_endpoint(busid, &cdc_in_ep3);
|
||||||
|
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf6));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf6));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf7));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf7));
|
||||||
usbd_add_endpoint(&cdc_out_ep4);
|
usbd_add_endpoint(busid, &cdc_out_ep4);
|
||||||
usbd_add_endpoint(&cdc_in_ep4);
|
usbd_add_endpoint(busid, &cdc_in_ep4);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ volatile bool ep_tx_busy_flag = false;
|
|||||||
#define CDC_MAX_MPS 64
|
#define CDC_MAX_MPS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -124,8 +124,9 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -137,7 +138,7 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
// for (int i = 0; i < 100; i++) {
|
// for (int i = 0; i < 100; i++) {
|
||||||
@@ -145,16 +146,16 @@ void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
|||||||
// }
|
// }
|
||||||
// printf("\r\n");
|
// printf("\r\n");
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
}
|
}
|
||||||
@@ -174,24 +175,24 @@ struct usbd_endpoint cdc_in_ep = {
|
|||||||
static struct usbd_interface intf0;
|
static struct usbd_interface intf0;
|
||||||
static struct usbd_interface intf1;
|
static struct usbd_interface intf1;
|
||||||
|
|
||||||
void cdc_acm_init(void)
|
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||||
|
|
||||||
memcpy(&write_buffer[0], data, 10);
|
memcpy(&write_buffer[0], data, 10);
|
||||||
memset(&write_buffer[10], 'a', 2038);
|
memset(&write_buffer[10], 'a', 2038);
|
||||||
|
|
||||||
usbd_desc_register(cdc_descriptor);
|
usbd_desc_register(busid, cdc_descriptor);
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
|
||||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||||
usbd_add_endpoint(&cdc_out_ep);
|
usbd_add_endpoint(busid, &cdc_out_ep);
|
||||||
usbd_add_endpoint(&cdc_in_ep);
|
usbd_add_endpoint(busid, &cdc_in_ep);
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile uint8_t dtr_enable = 0;
|
volatile uint8_t dtr_enable = 0;
|
||||||
|
|
||||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||||
{
|
{
|
||||||
if (dtr) {
|
if (dtr) {
|
||||||
dtr_enable = 1;
|
dtr_enable = 1;
|
||||||
@@ -200,11 +201,11 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_acm_data_send_with_dtr_test(void)
|
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
if (dtr_enable) {
|
if (dtr_enable) {
|
||||||
ep_tx_busy_flag = true;
|
ep_tx_busy_flag = true;
|
||||||
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
|
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
|
||||||
while (ep_tx_busy_flag) {
|
while (ep_tx_busy_flag) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ void cdc_ecm_lwip_init(void)
|
|||||||
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_cdc_ecm_data_recv_done(void)
|
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ void cdc_ecm_input_poll(void)
|
|||||||
cdc_ecm_if_input(&cdc_ecm_netif);
|
cdc_ecm_if_input(&cdc_ecm_netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -263,12 +263,12 @@ struct usbd_interface intf1;
|
|||||||
* sudo ifconfig enxaabbccddeeff up
|
* sudo ifconfig enxaabbccddeeff up
|
||||||
* sudo dhcpclient enxaabbccddeeff
|
* sudo dhcpclient enxaabbccddeeff
|
||||||
*/
|
*/
|
||||||
void cdc_ecm_init(void)
|
void cdc_ecm_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
cdc_ecm_lwip_init();
|
cdc_ecm_lwip_init();
|
||||||
|
|
||||||
usbd_desc_register(cdc_ecm_descriptor);
|
usbd_desc_register(busid, cdc_ecm_descriptor);
|
||||||
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
||||||
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
@@ -263,7 +263,7 @@ void rndis_input_poll(void)
|
|||||||
}
|
}
|
||||||
#endif /* RT_USING_LWIP */
|
#endif /* RT_USING_LWIP */
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -294,15 +294,15 @@ void usbd_event_handler(uint8_t event)
|
|||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
void cdc_rndis_init(void)
|
void cdc_rndis_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
#ifdef RT_USING_LWIP
|
#ifdef RT_USING_LWIP
|
||||||
rt_usbd_rndis_init();
|
rt_usbd_rndis_init();
|
||||||
#else
|
#else
|
||||||
rndis_lwip_init();
|
rndis_lwip_init();
|
||||||
#endif
|
#endif
|
||||||
usbd_desc_register(cdc_descriptor);
|
usbd_desc_register(busid, cdc_descriptor);
|
||||||
usbd_add_interface(usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
|
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
|
||||||
usbd_add_interface(usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
|
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ const uint8_t dfu_flash_descriptor[] = {
|
|||||||
0x00
|
0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -164,9 +164,9 @@ void usbd_event_handler(uint8_t event)
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
|
|
||||||
void dfu_flash_init(void)
|
void dfu_flash_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(dfu_flash_descriptor);
|
usbd_desc_register(busid, dfu_flash_descriptor);
|
||||||
usbd_add_interface(usbd_dfu_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 HPMicro
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_hid.h"
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
|
||||||
/*!< hidraw in endpoint */
|
/*!< hidraw in endpoint */
|
||||||
#define HIDRAW_IN_EP 0x81
|
#define HIDRAW_IN_EP 0x81
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define HIDRAW_IN_EP_SIZE 1024
|
||||||
|
#define HIDRAW_IN_INTERVAL 4
|
||||||
|
#else
|
||||||
#define HIDRAW_IN_EP_SIZE 64
|
#define HIDRAW_IN_EP_SIZE 64
|
||||||
#define HIDRAW_IN_INTERVAL 10
|
#define HIDRAW_IN_INTERVAL 10
|
||||||
|
#endif
|
||||||
/*!< hidraw out endpoint */
|
/*!< hidraw out endpoint */
|
||||||
#define HIDRAW_OUT_EP 0x02
|
#define HIDRAW_OUT_EP 0x02
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define HIDRAW_OUT_EP_SIZE 1024
|
||||||
|
#define HIDRAW_OUT_EP_INTERVAL 4
|
||||||
|
#else
|
||||||
#define HIDRAW_OUT_EP_SIZE 64
|
#define HIDRAW_OUT_EP_SIZE 64
|
||||||
#define HIDRAW_OUT_EP_INTERVAL 10
|
#define HIDRAW_OUT_EP_INTERVAL 10
|
||||||
|
#endif
|
||||||
#define USBD_VID 0xffff
|
|
||||||
#define USBD_PID 0xffff
|
|
||||||
#define USBD_MAX_POWER 100
|
|
||||||
#define USBD_LANGID_STRING 1033
|
|
||||||
|
|
||||||
/*!< config descriptor size */
|
/*!< config descriptor size */
|
||||||
#define USB_HID_CONFIG_DESC_SIZ (9 + 9 + 9 + 7 + 7)
|
#define USB_HID_CONFIG_DESC_SIZ (9 + 9 + 9 + 7 + 7)
|
||||||
@@ -51,7 +63,7 @@ static const uint8_t hid_descriptor[] = {
|
|||||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
0x03, /* bmAttributes: Interrupt endpoint */
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
WBVAL(HIDRAW_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
WBVAL(HIDRAW_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
|
||||||
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||||
/******************** Descriptor of Custom out endpoint ********************/
|
/******************** Descriptor of Custom out endpoint ********************/
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
@@ -137,6 +149,29 @@ static const uint8_t hid_descriptor[] = {
|
|||||||
|
|
||||||
/*!< custom hid report descriptor */
|
/*!< custom hid report descriptor */
|
||||||
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
/* USER CODE BEGIN 0 */
|
||||||
|
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, 0x02, /* USAGE (Vendor Usage 1) */
|
||||||
|
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||||
|
0x25, 0xff, /*LOGICAL_MAXIMUM (255) */
|
||||||
|
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||||
|
0x96, 0xff, 0x03, /* REPORT_COUNT (63) */
|
||||||
|
0x81, 0x02, /* INPUT (Data,Var,Abs) */
|
||||||
|
/* <___________________________________________________> */
|
||||||
|
0x85, 0x01, /* REPORT ID (0x01) */
|
||||||
|
0x09, 0x03, /* USAGE (Vendor Usage 1) */
|
||||||
|
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||||
|
0x25, 0xff, /* LOGICAL_MAXIMUM (255) */
|
||||||
|
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||||
|
0x96, 0xff, 0x03, /* REPORT_COUNT (63) */
|
||||||
|
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
||||||
|
/* USER CODE END 0 */
|
||||||
|
0xC0 /* END_COLLECTION */
|
||||||
|
#else
|
||||||
/* USER CODE BEGIN 0 */
|
/* USER CODE BEGIN 0 */
|
||||||
0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Defined Page 1) */
|
0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Defined Page 1) */
|
||||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||||
@@ -158,6 +193,7 @@ static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
|||||||
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
0xC0 /* END_COLLECTION */
|
0xC0 /* END_COLLECTION */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[HIDRAW_OUT_EP_SIZE];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[HIDRAW_OUT_EP_SIZE];
|
||||||
@@ -169,45 +205,47 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t send_buffer[HIDRAW_IN_EP_SIZE];
|
|||||||
/*!< hid state ! Data can be sent only when state is idle */
|
/*!< hid state ! Data can be sent only when state is idle */
|
||||||
static volatile uint8_t custom_state;
|
static volatile uint8_t custom_state;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONNECTED:
|
case USBD_EVENT_CONNECTED:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_DISCONNECTED:
|
case USBD_EVENT_DISCONNECTED:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_RESUME:
|
case USBD_EVENT_RESUME:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
|
usbd_ep_start_read(busid, HIDRAW_OUT_EP, read_buffer, HIDRAW_OUT_EP_SIZE);
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbd_hid_custom_in_callback(uint8_t ep, uint32_t nbytes)
|
static void usbd_hid_custom_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
custom_state = HID_STATE_IDLE;
|
custom_state = HID_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbd_hid_custom_out_callback(uint8_t ep, uint32_t nbytes)
|
static void usbd_hid_custom_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
usbd_ep_start_read(HIDRAW_OUT_EP, read_buffer, 64);
|
usbd_ep_start_read(busid, ep, read_buffer, HIDRAW_IN_EP_SIZE);
|
||||||
read_buffer[0] = 0x02; /* IN: report id */
|
read_buffer[0] = 0x02; /* IN: report id */
|
||||||
usbd_ep_start_write(HIDRAW_IN_EP, read_buffer, nbytes);
|
usbd_ep_start_write(busid, HIDRAW_IN_EP, read_buffer, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usbd_endpoint custom_in_ep = {
|
static struct usbd_endpoint custom_in_ep = {
|
||||||
@@ -229,12 +267,12 @@ static struct usbd_endpoint custom_out_ep = {
|
|||||||
*/
|
*/
|
||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
|
|
||||||
void hid_custom_init(void)
|
void hid_custom_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(hid_descriptor);
|
usbd_desc_register(busid, hid_descriptor);
|
||||||
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||||
usbd_add_endpoint(&custom_in_ep);
|
usbd_add_endpoint(busid, &custom_in_ep);
|
||||||
usbd_add_endpoint(&custom_out_ep);
|
usbd_add_endpoint(busid, &custom_out_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,13 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
|||||||
0xc0 // END_COLLECTION
|
0xc0 // END_COLLECTION
|
||||||
};
|
};
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
#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 hid_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -186,6 +192,7 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
hid_state = HID_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -197,13 +204,7 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HID_STATE_IDLE 0
|
void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
#define HID_STATE_BUSY 1
|
|
||||||
|
|
||||||
/*!< hid state ! Data can be sent only when state is idle */
|
|
||||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
|
||||||
|
|
||||||
void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
|
|
||||||
{
|
{
|
||||||
hid_state = HID_STATE_IDLE;
|
hid_state = HID_STATE_IDLE;
|
||||||
}
|
}
|
||||||
@@ -215,23 +216,23 @@ static struct usbd_endpoint hid_in_ep = {
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
|
|
||||||
void hid_keyboard_init(void)
|
void hid_keyboard_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(hid_descriptor);
|
usbd_desc_register(busid, hid_descriptor);
|
||||||
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||||
usbd_add_endpoint(&hid_in_ep);
|
usbd_add_endpoint(busid, &hid_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
|
||||||
|
|
||||||
void hid_keyboard_test(void)
|
void hid_keyboard_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
memcpy(write_buffer, sendbuffer, 8);
|
memcpy(write_buffer, sendbuffer, 8);
|
||||||
int ret = usbd_ep_start_write(HID_INT_EP, write_buffer, 8);
|
int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
|
|||||||
/*!< hid state ! Data can be sent only when state is idle */
|
/*!< hid state ! Data can be sent only when state is idle */
|
||||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -208,6 +208,7 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
hid_state = HID_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -220,7 +221,7 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* function ------------------------------------------------------------------*/
|
/* function ------------------------------------------------------------------*/
|
||||||
static void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
|
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
hid_state = HID_STATE_IDLE;
|
hid_state = HID_STATE_IDLE;
|
||||||
}
|
}
|
||||||
@@ -233,13 +234,13 @@ static struct usbd_endpoint hid_in_ep = {
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
|
|
||||||
void hid_mouse_init(void)
|
void hid_mouse_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(hid_descriptor);
|
usbd_desc_register(busid, hid_descriptor);
|
||||||
usbd_add_interface(usbd_hid_init_intf(&intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||||
usbd_add_endpoint(&hid_in_ep);
|
usbd_add_endpoint(busid, &hid_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
|
|
||||||
/*!< init mouse report data */
|
/*!< init mouse report data */
|
||||||
mouse_cfg.buttons = 0;
|
mouse_cfg.buttons = 0;
|
||||||
@@ -254,7 +255,7 @@ void hid_mouse_init(void)
|
|||||||
* @param[in] none
|
* @param[in] none
|
||||||
* @retval none
|
* @retval none
|
||||||
*/
|
*/
|
||||||
void hid_mouse_test(void)
|
void hid_mouse_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (counter < 1000) {
|
while (counter < 1000) {
|
||||||
@@ -262,7 +263,7 @@ void hid_mouse_test(void)
|
|||||||
mouse_cfg.x += 40;
|
mouse_cfg.x += 40;
|
||||||
mouse_cfg.y += 0;
|
mouse_cfg.y += 0;
|
||||||
|
|
||||||
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ const uint8_t midi_descriptor[] = {
|
|||||||
0x00
|
0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -171,11 +171,11 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_midi_bulk_out(uint8_t ep, uint32_t nbytes)
|
void usbd_midi_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_midi_bulk_in(uint8_t ep, uint32_t nbytes)
|
void usbd_midi_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,13 +192,13 @@ struct usbd_endpoint midi_in_ep = {
|
|||||||
.ep_cb = usbd_midi_bulk_in
|
.ep_cb = usbd_midi_bulk_in
|
||||||
};
|
};
|
||||||
|
|
||||||
void midi_init(void)
|
void midi_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(midi_descriptor);
|
usbd_desc_register(busid, midi_descriptor);
|
||||||
usbd_add_interface(&intf0);
|
usbd_add_interface(busid, &intf0);
|
||||||
usbd_add_interface(&intf1);
|
usbd_add_interface(busid, &intf1);
|
||||||
usbd_add_endpoint(&midi_out_ep);
|
usbd_add_endpoint(busid, &midi_out_ep);
|
||||||
usbd_add_endpoint(&midi_in_ep);
|
usbd_add_endpoint(busid, &midi_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ const uint8_t msc_ram_descriptor[] = {
|
|||||||
0x00
|
0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -130,19 +130,19 @@ typedef struct
|
|||||||
|
|
||||||
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||||
|
|
||||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||||
{
|
{
|
||||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||||
*block_size = BLOCK_SIZE;
|
*block_size = BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < BLOCK_COUNT)
|
if (sector < BLOCK_COUNT)
|
||||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
if (sector < BLOCK_COUNT)
|
if (sector < BLOCK_COUNT)
|
||||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||||
@@ -151,10 +151,10 @@ int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
|
|
||||||
void msc_ram_init(void)
|
void msc_ram_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(msc_ram_descriptor);
|
usbd_desc_register(busid, msc_ram_descriptor);
|
||||||
usbd_add_interface(usbd_msc_init_intf(&intf0, MSC_OUT_EP, MSC_IN_EP));
|
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ struct usbd_interface intf0;
|
|||||||
#define BLOCK_COUNT 0x1024U * 0x1024U
|
#define BLOCK_COUNT 0x1024U * 0x1024U
|
||||||
static rt_device_t blk_dev = RT_NULL;
|
static rt_device_t blk_dev = RT_NULL;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -131,25 +131,25 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||||
{
|
{
|
||||||
*block_num = BLOCK_COUNT;
|
*block_num = BLOCK_COUNT;
|
||||||
*block_size = BLOCK_SIZE;
|
*block_size = BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msc_storage_init(void)
|
void msc_storage_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
rt_err_t res;
|
rt_err_t res;
|
||||||
|
|
||||||
@@ -159,9 +159,9 @@ void msc_storage_init(void)
|
|||||||
res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
|
res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
|
||||||
RT_ASSERT(res == RT_EOK);
|
RT_ASSERT(res == RT_EOK);
|
||||||
|
|
||||||
usbd_desc_register(msc_storage_descriptor);
|
usbd_desc_register(busid, msc_storage_descriptor);
|
||||||
usbd_add_interface(usbd_msc_init_intf(&intf0, MSC_OUT_EP, MSC_IN_EP));
|
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
#include "usbd_core.h"
|
|
||||||
#include "usbd_mtp.h"
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
/* MTP */
|
|
||||||
'M', 'T', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, /* cCID_8 */
|
|
||||||
/* */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = NULL,
|
|
||||||
.comp_id_property_len = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!< endpoint address */
|
|
||||||
#define CDC_IN_EP 0x81
|
|
||||||
#define CDC_OUT_EP 0x02
|
|
||||||
#define CDC_INT_EP 0x83
|
|
||||||
|
|
||||||
#define USBD_VID 0xFFFE
|
|
||||||
#define USBD_PID 0xFFFF
|
|
||||||
#define USBD_MAX_POWER 100
|
|
||||||
#define USBD_LANGID_STRING 1033
|
|
||||||
|
|
||||||
/*!< 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, MTP_MAX_MPS, 0x02),
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// string0 descriptor
|
|
||||||
///////////////////////////////////////
|
|
||||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// string1 descriptor
|
|
||||||
///////////////////////////////////////
|
|
||||||
0x14, /* bLength */
|
|
||||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
|
||||||
'C', 0x00, /* wcChar0 */
|
|
||||||
'h', 0x00, /* wcChar1 */
|
|
||||||
'e', 0x00, /* wcChar2 */
|
|
||||||
'r', 0x00, /* wcChar3 */
|
|
||||||
'r', 0x00, /* wcChar4 */
|
|
||||||
'y', 0x00, /* wcChar5 */
|
|
||||||
'U', 0x00, /* wcChar6 */
|
|
||||||
'S', 0x00, /* wcChar7 */
|
|
||||||
'B', 0x00, /* wcChar8 */
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// string2 descriptor
|
|
||||||
///////////////////////////////////////
|
|
||||||
0x26, /* bLength */
|
|
||||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
|
||||||
'C', 0x00, /* wcChar0 */
|
|
||||||
'h', 0x00, /* wcChar1 */
|
|
||||||
'e', 0x00, /* wcChar2 */
|
|
||||||
'r', 0x00, /* wcChar3 */
|
|
||||||
'r', 0x00, /* wcChar4 */
|
|
||||||
'y', 0x00, /* wcChar5 */
|
|
||||||
'U', 0x00, /* wcChar6 */
|
|
||||||
'S', 0x00, /* wcChar7 */
|
|
||||||
'B', 0x00, /* wcChar8 */
|
|
||||||
' ', 0x00, /* wcChar9 */
|
|
||||||
'M', 0x00, /* wcChar10 */
|
|
||||||
'T', 0x00, /* wcChar11 */
|
|
||||||
'P', 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 */
|
|
||||||
'1', 0x00, /* wcChar3 */
|
|
||||||
'0', 0x00, /* wcChar4 */
|
|
||||||
'3', 0x00, /* wcChar5 */
|
|
||||||
'1', 0x00, /* wcChar6 */
|
|
||||||
'0', 0x00, /* wcChar7 */
|
|
||||||
'0', 0x00, /* wcChar8 */
|
|
||||||
'0', 0x00, /* wcChar9 */
|
|
||||||
#ifdef CONFIG_USB_HS
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// device qualifier descriptor
|
|
||||||
///////////////////////////////////////
|
|
||||||
0x0a,
|
|
||||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
|
||||||
0x00,
|
|
||||||
0x02,
|
|
||||||
0x02,
|
|
||||||
0x02,
|
|
||||||
0x01,
|
|
||||||
0x40,
|
|
||||||
0x01,
|
|
||||||
0x00,
|
|
||||||
#endif
|
|
||||||
0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t bos_descriptor[] = {
|
|
||||||
0x05, 0x0f, 0x16, 0x00, 0x02,
|
|
||||||
0x07, 0x10, 0x02, 0x06, 0x00, 0x00, 0x00,
|
|
||||||
0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
|
||||||
{
|
|
||||||
switch (event) {
|
|
||||||
case USBD_EVENT_RESET:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_CONNECTED:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_DISCONNECTED:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_RESUME:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_SUSPEND:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_CONFIGURED:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
|
||||||
break;
|
|
||||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct usbd_interface intf0;
|
|
||||||
|
|
||||||
struct usb_bos_descriptor bos_desc = {
|
|
||||||
.string = bos_descriptor,
|
|
||||||
.string_len = 22
|
|
||||||
};
|
|
||||||
|
|
||||||
void mtp_init(void)
|
|
||||||
{
|
|
||||||
usbd_desc_register(mtp_descriptor);
|
|
||||||
usbd_msosv1_desc_register(&msosv1_desc);
|
|
||||||
usbd_bos_desc_register(&bos_desc);
|
|
||||||
usbd_add_interface(usbd_mtp_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP));
|
|
||||||
usbd_initialize();
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
#include "usbd_core.h"
|
|
||||||
#include "usb_printer.h"
|
|
||||||
|
|
||||||
/*!< endpoint address */
|
|
||||||
#define PRINTER_IN_EP 0x81
|
|
||||||
#define PRINTER_IN_EP_SIZE 0x40
|
|
||||||
#define PRINTER_OUT_EP 0x02
|
|
||||||
#define PRINTER_OUT_EP_SIZE 0x40
|
|
||||||
|
|
||||||
#define USBD_VID 0x5A5A
|
|
||||||
#define USBD_PID 0xA5A5
|
|
||||||
#define USBD_MAX_POWER 100
|
|
||||||
#define USBD_LANGID_STRING 0x0409
|
|
||||||
|
|
||||||
/*!< config descriptor size */
|
|
||||||
#define USB_CONFIG_SIZE (32)
|
|
||||||
|
|
||||||
/*!< global descriptor */
|
|
||||||
static const uint8_t printer_descriptor[] = {
|
|
||||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0000, 0x01),
|
|
||||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
|
|
||||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0x07, 0x01, 0x02, 0x00),
|
|
||||||
USB_ENDPOINT_DESCRIPTOR_INIT(PRINTER_IN_EP, 0x02, PRINTER_IN_EP_SIZE, 0x00),
|
|
||||||
USB_ENDPOINT_DESCRIPTOR_INIT(PRINTER_OUT_EP, 0x02, PRINTER_OUT_EP_SIZE, 0x00),
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// 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
|
|
||||||
///////////////////////////////////////
|
|
||||||
0x2A, /* 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 */
|
|
||||||
'P', 0x00, /* wcChar10 */
|
|
||||||
'R', 0x00, /* wcChar11 */
|
|
||||||
'I', 0x00, /* wcChar12 */
|
|
||||||
'N', 0x00, /* wcChar13 */
|
|
||||||
'T', 0x00, /* wcChar14 */
|
|
||||||
' ', 0x00, /* wcChar15 */
|
|
||||||
'D', 0x00, /* wcChar16 */
|
|
||||||
'E', 0x00, /* wcChar17 */
|
|
||||||
'M', 0x00, /* wcChar18 */
|
|
||||||
'O', 0x00, /* wcChar19 */
|
|
||||||
///////////////////////////////////////
|
|
||||||
/// 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,
|
|
||||||
0x02,
|
|
||||||
0x02,
|
|
||||||
0x01,
|
|
||||||
0x40,
|
|
||||||
0x01,
|
|
||||||
0x00,
|
|
||||||
#endif
|
|
||||||
0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
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_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:
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
/* setup next out ep read transfer */
|
|
||||||
usbd_ep_start_read(PRINTER_OUT_EP, read_buffer, PRINTER_OUT_EP_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbd_printer_bulk_in(uint8_t ep, uint32_t nbytes)
|
|
||||||
{
|
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
|
||||||
|
|
||||||
if ((nbytes % PRINTER_IN_EP_SIZE) == 0 && nbytes) {
|
|
||||||
/* send zlp */
|
|
||||||
usbd_ep_start_write(PRINTER_IN_EP, NULL, 0);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!< endpoint call back */
|
|
||||||
struct usbd_endpoint printer_out_ep = {
|
|
||||||
.ep_addr = PRINTER_OUT_EP,
|
|
||||||
.ep_cb = usbd_printer_bulk_out
|
|
||||||
};
|
|
||||||
|
|
||||||
struct usbd_endpoint printer_in_ep = {
|
|
||||||
.ep_addr = PRINTER_IN_EP,
|
|
||||||
.ep_cb = usbd_printer_bulk_in
|
|
||||||
};
|
|
||||||
|
|
||||||
struct usbd_interface intf0;
|
|
||||||
|
|
||||||
static const uint8_t printer_device_id[] =
|
|
||||||
{
|
|
||||||
0x00, 51,
|
|
||||||
'M','F','G',':','C','B','M',';',
|
|
||||||
'C','M','D',':','G','D','I',';',
|
|
||||||
'M','D','L',':','C','B','M','1','0','0','0',';',
|
|
||||||
'C','L','S',':','P','R','I','N','T','E','R',';',
|
|
||||||
'M','O','D','E',':','G','D','I',';'
|
|
||||||
};
|
|
||||||
|
|
||||||
void printer_init(void)
|
|
||||||
{
|
|
||||||
usbd_desc_register(printer_descriptor);
|
|
||||||
usbd_add_interface(usbd_printer_init_intf(&intf0, printer_device_id, sizeof(printer_device_id)));
|
|
||||||
usbd_add_endpoint(&printer_out_ep);
|
|
||||||
usbd_add_endpoint(&printer_in_ep);
|
|
||||||
|
|
||||||
usbd_initialize();
|
|
||||||
}
|
|
||||||
386
demo/usb_host.c
@@ -6,23 +6,28 @@
|
|||||||
#include "usbh_audio.h"
|
#include "usbh_audio.h"
|
||||||
|
|
||||||
#define TEST_USBH_CDC_ACM 1
|
#define TEST_USBH_CDC_ACM 1
|
||||||
|
#define TEST_USBH_CDC_SPEED 0
|
||||||
#define TEST_USBH_HID 1
|
#define TEST_USBH_HID 1
|
||||||
#define TEST_USBH_MSC 1
|
#define TEST_USBH_MSC 1
|
||||||
#define TEST_USBH_MSC_FATFS 0
|
#define TEST_USBH_MSC_FATFS 0
|
||||||
#define TEST_USBH_AUDIO 0
|
#define TEST_USBH_AUDIO 0
|
||||||
#define TEST_USBH_VIDEO 0
|
#define TEST_USBH_VIDEO 0
|
||||||
|
#define TEST_USBH_CDC_ECM 0
|
||||||
#if __has_include("lwip/pbuf.h")
|
#define TEST_USBH_CDC_NCM 0
|
||||||
#define TEST_USBH_CDC_ECM 1
|
#define TEST_USBH_RNDIS 0
|
||||||
#define TEST_USBH_RNDIS 1
|
#define TEST_USBH_ASIX 0
|
||||||
#else
|
#define TEST_USBH_RTL8152 0
|
||||||
#define TEST_USBH_CDC_ECM 0
|
|
||||||
#define TEST_USBH_RNDIS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TEST_USBH_CDC_ACM
|
#if TEST_USBH_CDC_ACM
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
|
||||||
|
|
||||||
|
#if TEST_USBH_CDC_SPEED
|
||||||
|
#define TEST_LEN (16 * 1024)
|
||||||
|
#define TEST_COUNT (10240)
|
||||||
|
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_speed_buffer[TEST_LEN];
|
||||||
|
#endif
|
||||||
|
|
||||||
void usbh_cdc_acm_callback(void *arg, int nbytes)
|
void usbh_cdc_acm_callback(void *arg, int nbytes)
|
||||||
{
|
{
|
||||||
//struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
|
//struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
|
||||||
@@ -46,7 +51,25 @@ find_class:
|
|||||||
while ((cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0")) == NULL) {
|
while ((cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0")) == NULL) {
|
||||||
goto delete;
|
goto delete;
|
||||||
}
|
}
|
||||||
|
#if TEST_USBH_CDC_SPEED
|
||||||
|
const uint32_t test_len[] = { 512, 1 * 1024, 2 * 1024, 4 * 1024, 8 * 1024, 16 * 1024 };
|
||||||
|
|
||||||
|
memset(cdc_speed_buffer, 0xAA, TEST_LEN);
|
||||||
|
|
||||||
|
for (uint8_t j = 0; j < 6; j++) {
|
||||||
|
uint32_t start_time = (uint32_t)bflb_mtimer_get_time_ms();
|
||||||
|
for (uint32_t i = 0; i < TEST_COUNT; i++) {
|
||||||
|
usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, cdc_speed_buffer, test_len[j], 0XFFFFFFF, NULL, NULL);
|
||||||
|
ret = usbh_submit_urb(&cdc_acm_class->bulkout_urb);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||||
|
while (1) {}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("per packet len:%d, out speed:%d MB/S\r\n", test_len[j], (test_len[j] * TEST_COUNT / 1024 / 1024) * 1000 / ((uint32_t)bflb_mtimer_get_time_ms() - start_time));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
memset(cdc_buffer, 0, 512);
|
memset(cdc_buffer, 0, 512);
|
||||||
|
|
||||||
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||||
@@ -87,6 +110,9 @@ void usbh_hid_callback(void *arg, int nbytes)
|
|||||||
}
|
}
|
||||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||||
usbh_submit_urb(&hid_class->intin_urb);
|
usbh_submit_urb(&hid_class->intin_urb);
|
||||||
|
} else if (nbytes == -USB_ERR_NAK) { /* for dwc2 */
|
||||||
|
usbh_submit_urb(&hid_class->intin_urb);
|
||||||
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +372,7 @@ void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostre
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
|
#if TEST_USBH_CDC_ECM || TEST_USBH_CDC_NCM || TEST_USBH_RNDIS || TEST_USBH_ASIX || TEST_USBH_RTL8152
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
@@ -358,10 +384,6 @@ void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostre
|
|||||||
|
|
||||||
#ifdef __RTTHREAD__
|
#ifdef __RTTHREAD__
|
||||||
|
|
||||||
#ifndef RT_USING_TIMER_SOFT
|
|
||||||
#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <rtdevice.h>
|
#include <rtdevice.h>
|
||||||
#include <netif/ethernetif.h>
|
#include <netif/ethernetif.h>
|
||||||
@@ -508,6 +530,118 @@ void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_USBH_CDC_NCM
|
||||||
|
#include "usbh_cdc_ncm.h"
|
||||||
|
|
||||||
|
struct netif g_cdc_ncm_netif;
|
||||||
|
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
static struct eth_device cdc_ncm_dev;
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_cdc_ncm_control(rt_device_t dev, int cmd, void *args)
|
||||||
|
{
|
||||||
|
struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)dev->user_data;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case NIOCTL_GADDR:
|
||||||
|
|
||||||
|
/* get mac address */
|
||||||
|
if (args)
|
||||||
|
rt_memcpy(args, cdc_ncm_class->mac, 6);
|
||||||
|
else
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_cdc_ncm_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||||
|
{
|
||||||
|
return usbh_cdc_ncm_linkoutput(NULL, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static err_t usbh_cdc_ncm_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||||
|
|
||||||
|
netif->mtu = 1500;
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||||
|
netif->state = NULL;
|
||||||
|
netif->name[0] = 'E';
|
||||||
|
netif->name[1] = 'X';
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = usbh_cdc_ncm_linkoutput;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
struct netdev *netdev;
|
||||||
|
|
||||||
|
memset(&cdc_ncm_dev, 0, sizeof(struct eth_device));
|
||||||
|
|
||||||
|
cdc_ncm_dev.parent.control = rt_usbh_cdc_ncm_control;
|
||||||
|
cdc_ncm_dev.eth_rx = NULL;
|
||||||
|
cdc_ncm_dev.eth_tx = rt_usbh_cdc_ncm_eth_tx;
|
||||||
|
cdc_ncm_dev.parent.user_data = cdc_ncm_class;
|
||||||
|
|
||||||
|
eth_device_init(&cdc_ncm_dev, "u0");
|
||||||
|
eth_device_linkchange(&cdc_ncm_dev, RT_TRUE);
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, cdc_ncm_dev.netif);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_cdc_ncm_netif;
|
||||||
|
|
||||||
|
netif->hwaddr_len = 6;
|
||||||
|
memcpy(netif->hwaddr, cdc_ncm_class->mac, 6);
|
||||||
|
|
||||||
|
IP4_ADDR(&cdc_ncm_class->ipaddr, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&cdc_ncm_class->netmask, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&cdc_ncm_class->gateway, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
netif = netif_add(netif, &cdc_ncm_class->ipaddr, &cdc_ncm_class->netmask, &cdc_ncm_class->gateway, NULL, usbh_cdc_ncm_if_init, tcpip_input);
|
||||||
|
netif_set_default(netif);
|
||||||
|
while (!netif_is_up(netif)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||||
|
if (dhcp_handle1 == NULL) {
|
||||||
|
USB_LOG_ERR("timer creation failed! \r\n");
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, netif);
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_start(netif);
|
||||||
|
xTimerStart(dhcp_handle1, 0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
eth_device_deinit(&cdc_ncm_dev);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_cdc_ncm_netif;
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_stop(netif);
|
||||||
|
dhcp_cleanup(netif);
|
||||||
|
#endif
|
||||||
|
netif_set_down(netif);
|
||||||
|
netif_remove(netif);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TEST_USBH_RNDIS
|
#if TEST_USBH_RNDIS
|
||||||
#include "usbh_rndis.h"
|
#include "usbh_rndis.h"
|
||||||
|
|
||||||
@@ -670,6 +804,230 @@ void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEST_USBH_ASIX
|
||||||
|
#include "usbh_asix.h"
|
||||||
|
|
||||||
|
struct netif g_asix_netif;
|
||||||
|
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
static struct eth_device asix_dev;
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
|
||||||
|
{
|
||||||
|
struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case NIOCTL_GADDR:
|
||||||
|
|
||||||
|
/* get mac address */
|
||||||
|
if (args)
|
||||||
|
rt_memcpy(args, asix_class->mac, 6);
|
||||||
|
else
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||||
|
{
|
||||||
|
return usbh_asix_linkoutput(NULL, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static err_t usbh_asix_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||||
|
|
||||||
|
netif->mtu = 1500;
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||||
|
netif->state = NULL;
|
||||||
|
netif->name[0] = 'E';
|
||||||
|
netif->name[1] = 'X';
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = usbh_asix_linkoutput;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_asix_run(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
struct netdev *netdev;
|
||||||
|
|
||||||
|
memset(&asix_dev, 0, sizeof(struct eth_device));
|
||||||
|
|
||||||
|
asix_dev.parent.control = rt_usbh_asix_control;
|
||||||
|
asix_dev.eth_rx = NULL;
|
||||||
|
asix_dev.eth_tx = rt_usbh_asix_eth_tx;
|
||||||
|
asix_dev.parent.user_data = asix_class;
|
||||||
|
|
||||||
|
eth_device_init(&asix_dev, "u2");
|
||||||
|
eth_device_linkchange(&asix_dev, RT_TRUE);
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, asix_dev.netif);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_asix_netif;
|
||||||
|
|
||||||
|
netif->hwaddr_len = 6;
|
||||||
|
memcpy(netif->hwaddr, asix_class->mac, 6);
|
||||||
|
|
||||||
|
IP4_ADDR(&asix_class->ipaddr, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&asix_class->netmask, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&asix_class->gateway, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
netif = netif_add(netif, &asix_class->ipaddr, &asix_class->netmask, &asix_class->gateway, NULL, usbh_asix_if_init, tcpip_input);
|
||||||
|
netif_set_default(netif);
|
||||||
|
while (!netif_is_up(netif)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||||
|
if (dhcp_handle1 == NULL) {
|
||||||
|
USB_LOG_ERR("timer creation failed! \r\n");
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, netif);
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_start(netif);
|
||||||
|
xTimerStart(dhcp_handle1, 0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_asix_stop(struct usbh_asix *asix_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
eth_device_deinit(&asix_dev);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_asix_netif;
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_stop(netif);
|
||||||
|
dhcp_cleanup(netif);
|
||||||
|
#endif
|
||||||
|
netif_set_down(netif);
|
||||||
|
netif_remove(netif);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TEST_USBH_RTL8152
|
||||||
|
#include "usbh_rtl8152.h"
|
||||||
|
|
||||||
|
struct netif g_rtl8152_netif;
|
||||||
|
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
static struct eth_device rtl8152_dev;
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_rtl8152_control(rt_device_t dev, int cmd, void *args)
|
||||||
|
{
|
||||||
|
struct usbh_rtl8152 *rtl8152_class = (struct usbh_rtl8152 *)dev->user_data;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case NIOCTL_GADDR:
|
||||||
|
|
||||||
|
/* get mac address */
|
||||||
|
if (args)
|
||||||
|
rt_memcpy(args, rtl8152_class->mac, 6);
|
||||||
|
else
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t rt_usbh_rtl8152_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||||
|
{
|
||||||
|
return usbh_rtl8152_linkoutput(NULL, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static err_t usbh_rtl8152_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||||
|
|
||||||
|
netif->mtu = 1500;
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||||
|
netif->state = NULL;
|
||||||
|
netif->name[0] = 'E';
|
||||||
|
netif->name[1] = 'X';
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = usbh_rtl8152_linkoutput;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
struct netdev *netdev;
|
||||||
|
|
||||||
|
memset(&rtl8152_dev, 0, sizeof(struct eth_device));
|
||||||
|
|
||||||
|
rtl8152_dev.parent.control = rt_usbh_rtl8152_control;
|
||||||
|
rtl8152_dev.eth_rx = NULL;
|
||||||
|
rtl8152_dev.eth_tx = rt_usbh_rtl8152_eth_tx;
|
||||||
|
rtl8152_dev.parent.user_data = rtl8152_class;
|
||||||
|
|
||||||
|
eth_device_init(&rtl8152_dev, "u0");
|
||||||
|
eth_device_linkchange(&rtl8152_dev, RT_TRUE);
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, rtl8152_dev.netif);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_rtl8152_netif;
|
||||||
|
|
||||||
|
netif->hwaddr_len = 6;
|
||||||
|
memcpy(netif->hwaddr, rtl8152_class->mac, 6);
|
||||||
|
|
||||||
|
IP4_ADDR(&rtl8152_class->ipaddr, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&rtl8152_class->netmask, 0, 0, 0, 0);
|
||||||
|
IP4_ADDR(&rtl8152_class->gateway, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
netif = netif_add(netif, &rtl8152_class->ipaddr, &rtl8152_class->netmask, &rtl8152_class->gateway, NULL, usbh_rtl8152_if_init, tcpip_input);
|
||||||
|
netif_set_default(netif);
|
||||||
|
while (!netif_is_up(netif)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||||
|
if (dhcp_handle1 == NULL) {
|
||||||
|
USB_LOG_ERR("timer creation failed! \r\n");
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_thread_create("usbh_rtl8152_rx", 2048, 20, usbh_rtl8152_rx_thread, netif);
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_start(netif);
|
||||||
|
xTimerStart(dhcp_handle1, 0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
|
||||||
|
{
|
||||||
|
#ifdef __RTTHREAD__
|
||||||
|
eth_device_deinit(&rtl8152_dev);
|
||||||
|
#else
|
||||||
|
struct netif *netif = &g_rtl8152_netif;
|
||||||
|
#if LWIP_DHCP
|
||||||
|
dhcp_stop(netif);
|
||||||
|
dhcp_cleanup(netif);
|
||||||
|
#endif
|
||||||
|
netif_set_down(netif);
|
||||||
|
netif_remove(netif);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||||
{
|
{
|
||||||
#if TEST_USBH_CDC_ACM
|
#if TEST_USBH_CDC_ACM
|
||||||
@@ -734,7 +1092,7 @@ void usbh_class_test(void)
|
|||||||
#ifdef __RTTHREAD__
|
#ifdef __RTTHREAD__
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
#else
|
#else
|
||||||
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
|
#if TEST_USBH_CDC_ECM || TEST_USBH_CDC_NCM || TEST_USBH_RNDIS || TEST_USBH_ASIX || TEST_USBH_RTL8152
|
||||||
/* Initialize the LwIP stack */
|
/* Initialize the LwIP stack */
|
||||||
tcpip_init(NULL, NULL);
|
tcpip_init(NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -141,7 +141,10 @@ const uint8_t video_descriptor[] = {
|
|||||||
0x00
|
0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
volatile bool tx_flag = 0;
|
||||||
|
volatile bool iso_tx_busy = false;
|
||||||
|
|
||||||
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -155,6 +158,8 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
tx_flag = 0;
|
||||||
|
iso_tx_busy = false;
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
break;
|
break;
|
||||||
@@ -166,23 +171,20 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile bool tx_flag = 0;
|
void usbd_video_open(uint8_t busid, uint8_t intf)
|
||||||
volatile bool iso_tx_busy = false;
|
|
||||||
|
|
||||||
void usbd_video_open(uint8_t intf)
|
|
||||||
{
|
{
|
||||||
tx_flag = 1;
|
tx_flag = 1;
|
||||||
USB_LOG_RAW("OPEN\r\n");
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
iso_tx_busy = false;
|
iso_tx_busy = false;
|
||||||
}
|
}
|
||||||
void usbd_video_close(uint8_t intf)
|
void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("CLOSE\r\n");
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
tx_flag = 0;
|
tx_flag = 0;
|
||||||
iso_tx_busy = false;
|
iso_tx_busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_video_iso_callback(uint8_t ep, uint32_t nbytes)
|
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
iso_tx_busy = false;
|
iso_tx_busy = false;
|
||||||
@@ -196,29 +198,29 @@ static struct usbd_endpoint video_in_ep = {
|
|||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
void video_init()
|
void video_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(video_descriptor);
|
usbd_desc_register(busid, video_descriptor);
|
||||||
usbd_add_interface(usbd_video_init_intf(&intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
usbd_add_interface(usbd_video_init_intf(&intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
usbd_add_endpoint(&video_in_ep);
|
usbd_add_endpoint(busid, &video_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[10 * 1024];
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[10 * 1024];
|
||||||
|
|
||||||
void video_test()
|
void video_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
uint32_t out_len;
|
uint32_t out_len;
|
||||||
uint32_t packets;
|
uint32_t packets;
|
||||||
memset(packet_buffer, 0, 10 * 1024);
|
memset(packet_buffer, 0, 10 * 1024);
|
||||||
while (1) {
|
while (1) {
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
|
packets = usbd_video_mjpeg_payload_fill(busid, (uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
|
||||||
#if 0
|
#if 0
|
||||||
iso_tx_busy = true;
|
iso_tx_busy = true;
|
||||||
usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len);
|
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
|
||||||
while (iso_tx_busy) {
|
while (iso_tx_busy) {
|
||||||
if (tx_flag == 0) {
|
if (tx_flag == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -229,7 +231,7 @@ void video_test()
|
|||||||
for (uint32_t i = 0; i < packets; i++) {
|
for (uint32_t i = 0; i < packets; i++) {
|
||||||
if (i == (packets - 1)) {
|
if (i == (packets - 1)) {
|
||||||
iso_tx_busy = true;
|
iso_tx_busy = true;
|
||||||
usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
|
||||||
while (iso_tx_busy) {
|
while (iso_tx_busy) {
|
||||||
if (tx_flag == 0) {
|
if (tx_flag == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -237,7 +239,7 @@ void video_test()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iso_tx_busy = true;
|
iso_tx_busy = true;
|
||||||
usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
|
||||||
while (iso_tx_busy) {
|
while (iso_tx_busy) {
|
||||||
if (tx_flag == 0) {
|
if (tx_flag == 0) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ const uint8_t winusb_descriptor[] = {
|
|||||||
'E', 0x00, /* wcChar18 */
|
'E', 0x00, /* wcChar18 */
|
||||||
'M', 0x00, /* wcChar19 */
|
'M', 0x00, /* wcChar19 */
|
||||||
'O', 0x00, /* wcChar20 */
|
'O', 0x00, /* wcChar20 */
|
||||||
' ', 0x00, /* wcChar16 */
|
' ', 0x00, /* wcChar16 */
|
||||||
'1', 0x00, /* wcChar21 */
|
'1', 0x00, /* wcChar21 */
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
/// string5 descriptor
|
/// string5 descriptor
|
||||||
@@ -309,7 +309,7 @@ const uint8_t winusb_descriptor[] = {
|
|||||||
'E', 0x00, /* wcChar18 */
|
'E', 0x00, /* wcChar18 */
|
||||||
'M', 0x00, /* wcChar19 */
|
'M', 0x00, /* wcChar19 */
|
||||||
'O', 0x00, /* wcChar20 */
|
'O', 0x00, /* wcChar20 */
|
||||||
' ', 0x00, /* wcChar16 */
|
' ', 0x00, /* wcChar16 */
|
||||||
'2', 0x00, /* wcChar21 */
|
'2', 0x00, /* wcChar21 */
|
||||||
#ifdef CONFIG_USB_HS
|
#ifdef CONFIG_USB_HS
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
@@ -334,7 +334,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
|||||||
|
|
||||||
volatile bool ep_tx_busy_flag = false;
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
void usbd_event_handler(uint8_t event)
|
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
@@ -348,10 +348,11 @@ void usbd_event_handler(uint8_t event)
|
|||||||
case USBD_EVENT_SUSPEND:
|
case USBD_EVENT_SUSPEND:
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_CONFIGURED:
|
case USBD_EVENT_CONFIGURED:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
/* setup first out ep read transfer */
|
/* setup first out ep read transfer */
|
||||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
#if DOUBLE_WINUSB == 1
|
#if DOUBLE_WINUSB == 1
|
||||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
usbd_ep_start_read(busid, WINUSB_OUT_EP2, read_buffer, 2048);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
@@ -364,25 +365,25 @@ void usbd_event_handler(uint8_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_winusb_out(uint8_t ep, uint32_t nbytes)
|
void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
// for (int i = 0; i < 100; i++) {
|
// for (int i = 0; i < 100; i++) {
|
||||||
// printf("%02x ", read_buffer[i]);
|
// printf("%02x ", read_buffer[i]);
|
||||||
// }
|
// }
|
||||||
// printf("\r\n");
|
// printf("\r\n");
|
||||||
usbd_ep_start_write(WINUSB_IN_EP, read_buffer, nbytes);
|
usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(WINUSB_OUT_EP, read_buffer, 2048);
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_winusb_in(uint8_t ep, uint32_t nbytes)
|
void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(WINUSB_IN_EP, NULL, 0);
|
usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
}
|
}
|
||||||
@@ -402,25 +403,25 @@ struct usbd_interface intf0;
|
|||||||
|
|
||||||
#if DOUBLE_WINUSB == 1
|
#if DOUBLE_WINUSB == 1
|
||||||
|
|
||||||
void usbd_winusb_out2(uint8_t ep, uint32_t nbytes)
|
void usbd_winusb_out2(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||||
// for (int i = 0; i < 100; i++) {
|
// for (int i = 0; i < 100; i++) {
|
||||||
// printf("%02x ", read_buffer[i]);
|
// printf("%02x ", read_buffer[i]);
|
||||||
// }
|
// }
|
||||||
// printf("\r\n");
|
// printf("\r\n");
|
||||||
usbd_ep_start_write(WINUSB_IN_EP2, read_buffer, nbytes);
|
usbd_ep_start_write(busid, WINUSB_IN_EP2, read_buffer, nbytes);
|
||||||
/* setup next out ep read transfer */
|
/* setup next out ep read transfer */
|
||||||
usbd_ep_start_read(WINUSB_OUT_EP2, read_buffer, 2048);
|
usbd_ep_start_read(busid, WINUSB_OUT_EP2, read_buffer, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_winusb_in2(uint8_t ep, uint32_t nbytes)
|
void usbd_winusb_in2(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||||
|
|
||||||
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
|
||||||
/* send zlp */
|
/* send zlp */
|
||||||
usbd_ep_start_write(WINUSB_IN_EP2, NULL, 0);
|
usbd_ep_start_write(busid, WINUSB_IN_EP2, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
ep_tx_busy_flag = false;
|
ep_tx_busy_flag = false;
|
||||||
}
|
}
|
||||||
@@ -440,17 +441,17 @@ struct usbd_interface intf1;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void winusb_init(void)
|
void winusb_init(uint8_t busid, uint32_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(winusb_descriptor);
|
usbd_desc_register(busid, winusb_descriptor);
|
||||||
usbd_msosv1_desc_register(&msosv1_desc);
|
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
||||||
usbd_add_interface(&intf0);
|
usbd_add_interface(busid, &intf0);
|
||||||
usbd_add_endpoint(&winusb_out_ep1);
|
usbd_add_endpoint(busid, &winusb_out_ep1);
|
||||||
usbd_add_endpoint(&winusb_in_ep1);
|
usbd_add_endpoint(busid, &winusb_in_ep1);
|
||||||
#if DOUBLE_WINUSB == 1
|
#if DOUBLE_WINUSB == 1
|
||||||
usbd_add_interface(&intf1);
|
usbd_add_interface(busid, &intf1);
|
||||||
usbd_add_endpoint(&winusb_out_ep2);
|
usbd_add_endpoint(busid, &winusb_out_ep2);
|
||||||
usbd_add_endpoint(&winusb_in_ep2);
|
usbd_add_endpoint(busid, &winusb_in_ep2);
|
||||||
#endif
|
#endif
|
||||||
usbd_initialize();
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
}
|
}
|
||||||
334
demo/winusb2.0_cdc_template.c
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_cdc.h"
|
||||||
|
|
||||||
|
#define WINUSB_IN_EP 0x81
|
||||||
|
#define WINUSB_OUT_EP 0x02
|
||||||
|
|
||||||
|
#define CDC_IN_EP 0x83
|
||||||
|
#define CDC_OUT_EP 0x04
|
||||||
|
#define CDC_INT_EP 0x85
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFE
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 500
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + CDC_ACM_DESCRIPTOR_LEN)
|
||||||
|
#define INTF_NUM 3
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define WINUSB_EP_MPS 512
|
||||||
|
#else
|
||||||
|
#define WINUSB_EP_MPS 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USBD_WINUSB_VENDOR_CODE 0x20
|
||||||
|
|
||||||
|
#define USBD_WEBUSB_ENABLE 0
|
||||||
|
#define USBD_BULK_ENABLE 1
|
||||||
|
#define USBD_WINUSB_ENABLE 1
|
||||||
|
|
||||||
|
/* WinUSB Microsoft OS 2.0 descriptor sizes */
|
||||||
|
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
|
||||||
|
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
|
||||||
|
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
|
||||||
|
|
||||||
|
#define FUNCTION_SUBSET_LEN 160
|
||||||
|
#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
|
||||||
|
|
||||||
|
#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
|
||||||
|
WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
|
||||||
|
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||||
|
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||||
|
#if (USBD_WEBUSB_ENABLE)
|
||||||
|
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
|
||||||
|
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
|
||||||
|
0, // bFirstInterface USBD_WINUSB_IF_NUM
|
||||||
|
0, // bReserved
|
||||||
|
WBVAL(FUNCTION_SUBSET_LEN), // wSubsetLength
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), // wLength
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), // wDescriptorType
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, // CompatibleId
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // SubCompatibleId
|
||||||
|
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
|
||||||
|
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType
|
||||||
|
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
|
||||||
|
WBVAL(42), // wPropertyNameLength
|
||||||
|
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||||
|
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||||
|
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||||
|
WBVAL(80), // wPropertyDataLength
|
||||||
|
'{', 0,
|
||||||
|
'9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
|
||||||
|
'9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
|
||||||
|
'4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
|
||||||
|
'9', 0, '3', 0, '3', 0, 'B', 0, '-',
|
||||||
|
0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
|
||||||
|
'}', 0, 0, 0, 0, 0
|
||||||
|
#endif
|
||||||
|
#if USBD_BULK_ENABLE
|
||||||
|
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
|
||||||
|
0, /* bFirstInterface USBD_BULK_IF_NUM*/
|
||||||
|
0, /* bReserved */
|
||||||
|
WBVAL(FUNCTION_SUBSET_LEN), /* wSubsetLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), /* wDescriptorType */
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, /* CompatibleId*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, /* SubCompatibleId*/
|
||||||
|
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), /* wDescriptorType */
|
||||||
|
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
|
||||||
|
WBVAL(42), /* wPropertyNameLength */
|
||||||
|
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||||
|
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||||
|
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||||
|
WBVAL(80), /* wPropertyDataLength */
|
||||||
|
'{', 0,
|
||||||
|
'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
|
||||||
|
'2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
|
||||||
|
'4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
|
||||||
|
'A', 0, 'A', 0, '3', 0, '6', 0, '-',
|
||||||
|
0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
|
||||||
|
'}', 0, 0, 0, 0, 0
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
|
||||||
|
|
||||||
|
#define USBD_WEBUSB_DESC_LEN 24
|
||||||
|
#define USBD_WINUSB_DESC_LEN 28
|
||||||
|
|
||||||
|
#define USBD_BOS_WTOTALLENGTH (0x05 + \
|
||||||
|
USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
|
||||||
|
USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
|
||||||
|
0x05, /* bLength */
|
||||||
|
0x0f, /* bDescriptorType */
|
||||||
|
WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
|
||||||
|
USBD_NUM_DEV_CAPABILITIES, /* bNumDeviceCaps */
|
||||||
|
#if (USBD_WEBUSB_ENABLE)
|
||||||
|
USBD_WEBUSB_DESC_LEN, /* bLength */
|
||||||
|
0x10, /* bDescriptorType */
|
||||||
|
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||||
|
0x00, /* bReserved */
|
||||||
|
0x38, 0xB6, 0x08, 0x34, /* PlatformCapabilityUUID */
|
||||||
|
0xA9, 0x09, 0xA0, 0x47,
|
||||||
|
0x8B, 0xFD, 0xA0, 0x76,
|
||||||
|
0x88, 0x15, 0xB6, 0x65,
|
||||||
|
WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
|
||||||
|
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||||
|
0, /* iLandingPage */
|
||||||
|
#endif
|
||||||
|
#if (USBD_WINUSB_ENABLE)
|
||||||
|
USBD_WINUSB_DESC_LEN, /* bLength */
|
||||||
|
0x10, /* bDescriptorType */
|
||||||
|
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||||
|
0x00, /* bReserved */
|
||||||
|
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||||
|
0x89, 0x45, 0xC7, 0x4C,
|
||||||
|
0x9C, 0xD2, 0x65, 0x9D,
|
||||||
|
0x9E, 0x64, 0x8A, 0x9F,
|
||||||
|
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||||
|
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||||
|
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||||
|
0, /* bAltEnumCode */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t winusbv2_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
/* Configuration 0 */
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
/* Interface 0 */
|
||||||
|
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||||
|
/* Endpoint OUT 2 */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||||
|
/* Endpoint IN 1 */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 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) */
|
||||||
|
0x2C, /* 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 */
|
||||||
|
/* 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 read_buffer[2048];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||||
|
|
||||||
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
|
static void usbd_event_handler(uint8_t busid, 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:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
|
/* setup first out ep read transfer */
|
||||||
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
|
break;
|
||||||
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
|
break;
|
||||||
|
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_winusb_out(uint8_t busid, 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(busid, WINUSB_IN_EP, read_buffer, nbytes);
|
||||||
|
/* setup next out ep read transfer */
|
||||||
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_winusb_in(uint8_t busid, 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(busid, WINUSB_IN_EP, NULL, 0);
|
||||||
|
} else {
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usbd_endpoint winusb_out_ep1 = {
|
||||||
|
.ep_addr = WINUSB_OUT_EP,
|
||||||
|
.ep_cb = usbd_winusb_out
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbd_endpoint winusb_in_ep1 = {
|
||||||
|
.ep_addr = WINUSB_IN_EP,
|
||||||
|
.ep_cb = usbd_winusb_in
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usbd_endpoint cdc_out_ep = {
|
||||||
|
.ep_addr = CDC_OUT_EP,
|
||||||
|
.ep_cb = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usbd_endpoint cdc_in_ep = {
|
||||||
|
.ep_addr = CDC_IN_EP,
|
||||||
|
.ep_cb = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbd_interface winusb_intf;
|
||||||
|
struct usbd_interface intf1;
|
||||||
|
struct usbd_interface intf2;
|
||||||
|
|
||||||
|
struct usb_msosv2_descriptor msosv2_desc = {
|
||||||
|
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||||
|
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||||
|
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_bos_descriptor bos_desc = {
|
||||||
|
.string = USBD_BinaryObjectStoreDescriptor,
|
||||||
|
.string_len = USBD_BOS_WTOTALLENGTH
|
||||||
|
};
|
||||||
|
|
||||||
|
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||||
|
{
|
||||||
|
usbd_desc_register(busid, winusbv2_descriptor);
|
||||||
|
usbd_bos_desc_register(busid, &bos_desc);
|
||||||
|
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||||
|
|
||||||
|
/*!< winusb */
|
||||||
|
usbd_add_interface(busid, &winusb_intf);
|
||||||
|
usbd_add_endpoint(busid, &winusb_out_ep1);
|
||||||
|
usbd_add_endpoint(busid, &winusb_in_ep1);
|
||||||
|
|
||||||
|
/*!< cdc acm */
|
||||||
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||||
|
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
|
||||||
|
usbd_add_endpoint(busid, &cdc_out_ep);
|
||||||
|
usbd_add_endpoint(busid, &cdc_in_ep);
|
||||||
|
|
||||||
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
|
}
|
||||||
435
demo/winusb2.0_hid_template.c
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
#define WINUSB_IN_EP 0x81
|
||||||
|
#define WINUSB_OUT_EP 0x02
|
||||||
|
|
||||||
|
/*!< endpoint address */
|
||||||
|
#define HID_INT_EP 0x83
|
||||||
|
#define HID_INT_EP_SIZE 4
|
||||||
|
#define HID_INT_EP_INTERVAL 10
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFE
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 500
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + 9 + 9 + 7)
|
||||||
|
#define INTF_NUM 2
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||||
|
/*!< report descriptor size */
|
||||||
|
#define HID_MOUSE_REPORT_DESC_SIZE 74
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define WINUSB_EP_MPS 512
|
||||||
|
#else
|
||||||
|
#define WINUSB_EP_MPS 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USBD_WINUSB_VENDOR_CODE 0x20
|
||||||
|
|
||||||
|
#define USBD_WEBUSB_ENABLE 0
|
||||||
|
#define USBD_BULK_ENABLE 1
|
||||||
|
#define USBD_WINUSB_ENABLE 1
|
||||||
|
|
||||||
|
/* WinUSB Microsoft OS 2.0 descriptor sizes */
|
||||||
|
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
|
||||||
|
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
|
||||||
|
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
|
||||||
|
|
||||||
|
#define FUNCTION_SUBSET_LEN 160
|
||||||
|
#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
|
||||||
|
|
||||||
|
#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
|
||||||
|
WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
|
||||||
|
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||||
|
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||||
|
#if (USBD_WEBUSB_ENABLE)
|
||||||
|
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
|
||||||
|
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
|
||||||
|
0, // bFirstInterface USBD_WINUSB_IF_NUM
|
||||||
|
0, // bReserved
|
||||||
|
WBVAL(FUNCTION_SUBSET_LEN), // wSubsetLength
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), // wLength
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), // wDescriptorType
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, // CompatibleId
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // SubCompatibleId
|
||||||
|
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
|
||||||
|
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType
|
||||||
|
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
|
||||||
|
WBVAL(42), // wPropertyNameLength
|
||||||
|
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||||
|
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||||
|
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||||
|
WBVAL(80), // wPropertyDataLength
|
||||||
|
'{', 0,
|
||||||
|
'9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
|
||||||
|
'9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
|
||||||
|
'4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
|
||||||
|
'9', 0, '3', 0, '3', 0, 'B', 0, '-',
|
||||||
|
0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
|
||||||
|
'}', 0, 0, 0, 0, 0
|
||||||
|
#endif
|
||||||
|
#if USBD_BULK_ENABLE
|
||||||
|
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
|
||||||
|
0, /* bFirstInterface USBD_BULK_IF_NUM*/
|
||||||
|
0, /* bReserved */
|
||||||
|
WBVAL(FUNCTION_SUBSET_LEN), /* wSubsetLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), /* wLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), /* wDescriptorType */
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, /* CompatibleId*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, /* SubCompatibleId*/
|
||||||
|
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
|
||||||
|
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), /* wDescriptorType */
|
||||||
|
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
|
||||||
|
WBVAL(42), /* wPropertyNameLength */
|
||||||
|
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||||
|
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||||
|
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||||
|
WBVAL(80), /* wPropertyDataLength */
|
||||||
|
'{', 0,
|
||||||
|
'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
|
||||||
|
'2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
|
||||||
|
'4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
|
||||||
|
'A', 0, 'A', 0, '3', 0, '6', 0, '-',
|
||||||
|
0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
|
||||||
|
'}', 0, 0, 0, 0, 0
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
|
||||||
|
|
||||||
|
#define USBD_WEBUSB_DESC_LEN 24
|
||||||
|
#define USBD_WINUSB_DESC_LEN 28
|
||||||
|
|
||||||
|
#define USBD_BOS_WTOTALLENGTH (0x05 + \
|
||||||
|
USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
|
||||||
|
USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
|
||||||
|
0x05, /* bLength */
|
||||||
|
0x0f, /* bDescriptorType */
|
||||||
|
WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
|
||||||
|
USBD_NUM_DEV_CAPABILITIES, /* bNumDeviceCaps */
|
||||||
|
#if (USBD_WEBUSB_ENABLE)
|
||||||
|
USBD_WEBUSB_DESC_LEN, /* bLength */
|
||||||
|
0x10, /* bDescriptorType */
|
||||||
|
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||||
|
0x00, /* bReserved */
|
||||||
|
0x38, 0xB6, 0x08, 0x34, /* PlatformCapabilityUUID */
|
||||||
|
0xA9, 0x09, 0xA0, 0x47,
|
||||||
|
0x8B, 0xFD, 0xA0, 0x76,
|
||||||
|
0x88, 0x15, 0xB6, 0x65,
|
||||||
|
WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
|
||||||
|
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||||
|
0, /* iLandingPage */
|
||||||
|
#endif
|
||||||
|
#if (USBD_WINUSB_ENABLE)
|
||||||
|
USBD_WINUSB_DESC_LEN, /* bLength */
|
||||||
|
0x10, /* bDescriptorType */
|
||||||
|
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||||
|
0x00, /* bReserved */
|
||||||
|
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||||
|
0x89, 0x45, 0xC7, 0x4C,
|
||||||
|
0x9C, 0xD2, 0x65, 0x9D,
|
||||||
|
0x9E, 0x64, 0x8A, 0x9F,
|
||||||
|
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||||
|
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||||
|
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||||
|
0, /* bAltEnumCode */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t winusbv2_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
/* Configuration 0 */
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
/* Interface 0 */
|
||||||
|
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||||
|
/* Endpoint OUT 2 */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||||
|
/* Endpoint IN 1 */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||||
|
/************** Descriptor of Joystick Mouse interface ****************/
|
||||||
|
/* 09 */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||||
|
0x01, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x01, /* bNumEndpoints */
|
||||||
|
0x03, /* bInterfaceClass: HID */
|
||||||
|
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||||
|
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||||
|
0, /* iInterface: Index of string descriptor */
|
||||||
|
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||||
|
/* 18 */
|
||||||
|
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_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
/******************** Descriptor of Mouse endpoint ********************/
|
||||||
|
/* 27 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/* 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) */
|
||||||
|
0x2C, /* 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 */
|
||||||
|
/* 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 read_buffer[2048];
|
||||||
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||||
|
|
||||||
|
volatile bool ep_tx_busy_flag = false;
|
||||||
|
|
||||||
|
static void usbd_event_handler(uint8_t busid, 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:
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
|
/* setup first out ep read transfer */
|
||||||
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
|
break;
|
||||||
|
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||||
|
break;
|
||||||
|
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_winusb_out(uint8_t busid, 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(busid, WINUSB_IN_EP, read_buffer, nbytes);
|
||||||
|
/* setup next out ep read transfer */
|
||||||
|
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_winusb_in(uint8_t busid, 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(busid, WINUSB_IN_EP, NULL, 0);
|
||||||
|
} else {
|
||||||
|
ep_tx_busy_flag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usbd_endpoint winusb_out_ep1 = {
|
||||||
|
.ep_addr = WINUSB_OUT_EP,
|
||||||
|
.ep_cb = usbd_winusb_out
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbd_endpoint winusb_in_ep1 = {
|
||||||
|
.ep_addr = WINUSB_IN_EP,
|
||||||
|
.ep_cb = usbd_winusb_in
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< hid mouse report descriptor */
|
||||||
|
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x02, // USAGE (Mouse)
|
||||||
|
0xA1, 0x01, // COLLECTION (Application)
|
||||||
|
0x09, 0x01, // USAGE (Pointer)
|
||||||
|
|
||||||
|
0xA1, 0x00, // COLLECTION (Physical)
|
||||||
|
0x05, 0x09, // USAGE_PAGE (Button)
|
||||||
|
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||||
|
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||||
|
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (3)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x05, // REPORT_SIZE (5)
|
||||||
|
0x81, 0x01, // INPUT (Cnst,Var,Abs)
|
||||||
|
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x30, // USAGE (X)
|
||||||
|
0x09, 0x31, // USAGE (Y)
|
||||||
|
0x09, 0x38,
|
||||||
|
|
||||||
|
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||||
|
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (2)
|
||||||
|
|
||||||
|
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||||
|
0xC0, 0x09,
|
||||||
|
0x3c, 0x05,
|
||||||
|
0xff, 0x09,
|
||||||
|
|
||||||
|
0x01, 0x15,
|
||||||
|
0x00, 0x25,
|
||||||
|
0x01, 0x75,
|
||||||
|
0x01, 0x95,
|
||||||
|
|
||||||
|
0x02, 0xb1,
|
||||||
|
0x22, 0x75,
|
||||||
|
0x06, 0x95,
|
||||||
|
0x01, 0xb1,
|
||||||
|
|
||||||
|
0x01, 0xc0 // END_COLLECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< mouse report struct */
|
||||||
|
struct hid_mouse {
|
||||||
|
uint8_t buttons;
|
||||||
|
int8_t x;
|
||||||
|
int8_t y;
|
||||||
|
int8_t wheel;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< mouse report */
|
||||||
|
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
|
||||||
|
|
||||||
|
#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 hid_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
|
{
|
||||||
|
hid_state = HID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
static struct usbd_endpoint hid_in_ep = {
|
||||||
|
.ep_cb = usbd_hid_int_callback,
|
||||||
|
.ep_addr = HID_INT_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbd_interface winusb_intf;
|
||||||
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
|
struct usb_msosv2_descriptor msosv2_desc = {
|
||||||
|
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||||
|
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||||
|
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_bos_descriptor bos_desc = {
|
||||||
|
.string = USBD_BinaryObjectStoreDescriptor,
|
||||||
|
.string_len = USBD_BOS_WTOTALLENGTH
|
||||||
|
};
|
||||||
|
|
||||||
|
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||||
|
{
|
||||||
|
usbd_desc_register(busid, winusbv2_descriptor);
|
||||||
|
usbd_bos_desc_register(busid, &bos_desc);
|
||||||
|
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||||
|
|
||||||
|
/*!< winusb */
|
||||||
|
usbd_add_interface(busid, &winusb_intf);
|
||||||
|
usbd_add_endpoint(busid, &winusb_out_ep1);
|
||||||
|
usbd_add_endpoint(busid, &winusb_in_ep1);
|
||||||
|
|
||||||
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf1, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||||
|
usbd_add_endpoint(busid, &hid_in_ep);
|
||||||
|
|
||||||
|
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 40 KiB |
@@ -51,12 +51,11 @@ CONFIG_USBDEV_TEST_MODE
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
使能或者关闭 usb test mode
|
使能或者关闭 usb test mode
|
||||||
|
|
||||||
CONFIG_USBDEV_MSC_BLOCK_SIZE
|
CONFIG_USBDEV_MSC_MAX_BUFSIZE
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
msc 临时缓存的大小,缓存越大,msc 的速度越高,默认等于 1个内存介质的扇区大小(例如 sd卡 512,flash 4K),更改时需要是内存介质扇区的倍数。
|
msc 缓存的最大长度,缓存越大,USB 的速度越高,因为介质一般多个 block 读写速度比单个 block 高很多,比如 sd 卡。
|
||||||
|
默认 512 ,如果是 flash 需要改成 4K, 缓存的大小需要是 介质的一个 block size 的整数倍。
|
||||||
虽然名字叫 block size,但是跟内存介质的 block size不是一个意思。
|
|
||||||
|
|
||||||
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
CONFIG_USBDEV_MSC_MANUFACTURER_STRING
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
CORE
|
CORE
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
.. note:: 请注意,v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
|
||||||
|
|
||||||
端点结构体
|
端点结构体
|
||||||
""""""""""""""""""""""""""""""""""""
|
""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,11 @@ usbh_initialize
|
|||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
int usbh_initialize(void);
|
int usbh_initialize(uint8_t busid, uint32_t reg_base);
|
||||||
|
|
||||||
|
- **busid** bus id,从 0开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
|
||||||
|
- **reg_base** hcd 寄存器基地址
|
||||||
|
- **return** 0 表示正常其他表示错误
|
||||||
|
|
||||||
usbh_find_class_instance
|
usbh_find_class_instance
|
||||||
""""""""""""""""""""""""""""""""""""
|
""""""""""""""""""""""""""""""""""""
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
Porting
|
Porting
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
.. note:: 请注意,v1.1 版本开始增加 busid 形参,其余保持不变,所以 API 说明不做更新
|
||||||
|
|
||||||
device controller(dcd)
|
device controller(dcd)
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
# -- Project information
|
# -- Project information
|
||||||
|
|
||||||
project = 'CherryUSB'
|
project = 'CherryUSB'
|
||||||
copyright = '2022, sakumisu'
|
copyright = '2024, sakumisu'
|
||||||
author = 'sakumisu'
|
author = 'sakumisu'
|
||||||
|
|
||||||
release = '1.0.0'
|
release = '1.2.0'
|
||||||
version = '1.0.0'
|
version = '1.2.0'
|
||||||
|
|
||||||
# -- General configuration
|
# -- General configuration
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ USB 模拟 U 盘
|
|||||||
}
|
}
|
||||||
|
|
||||||
- 实现三个接口即可使用 msc,读写操作如果没有 os 则是在中断中
|
- 实现三个接口即可使用 msc,读写操作如果没有 os 则是在中断中
|
||||||
- `CONFIG_USBDEV_MSC_BLOCK_SIZE` 可以为 512 的整数倍,更改此项,可以增加 msc 的读写速度,当然,也会消耗更多的 ram
|
- `CONFIG_USBDEV_MSC_MAX_BUFSIZE` 可以为 512 的整数倍,更改此项,可以增加 msc 的读写速度,当然,也会消耗更多的 ram
|
||||||
|
|
||||||
|
|
||||||
.. note:: MSC 一般配合 rtos 使用,因为读写操作是阻塞的,放中断是不合适的, `CONFIG_USBDEV_MSC_THREAD` 则是使能 os 管理
|
.. note:: MSC 一般配合 rtos 使用,因为读写操作是阻塞的,放中断是不合适的, `CONFIG_USBDEV_MSC_THREAD` 则是使能 os 管理
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
|
|||||||
**其他相关链接**
|
**其他相关链接**
|
||||||
|
|
||||||
- **CherryUSB 大纲** https://www.bilibili.com/video/BV1st4y1H7K2
|
- **CherryUSB 大纲** https://www.bilibili.com/video/BV1st4y1H7K2
|
||||||
- **从机协议栈视频教程** https://www.bilibili.com/video/BV1Ef4y1t73d
|
- **CherryUSB 从机协议栈视频教程** https://www.bilibili.com/video/BV1Ef4y1t73d
|
||||||
- **主机协议栈视频教程** TODO
|
- **CherryUSB 腾讯会议** https://www.bilibili.com/video/BV16x421y7mM
|
||||||
- **github** https://github.com/sakumisu/CherryUSB
|
- **github** https://github.com/sakumisu/CherryUSB
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|||||||
@@ -216,17 +216,17 @@ EHCI 是 intel 制定的标准主机控制器接口,任何厂家都必须实
|
|||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
//Host Controller Capability Register BASE
|
//Host Controller Operational Register BASE 距离基地址的偏移
|
||||||
#define CONFIG_USB_EHCI_HCCR_BASE (0xxx)
|
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x14)
|
||||||
//Host Controller Operational Register BASE
|
|
||||||
#define CONFIG_USB_EHCI_HCOR_BASE (0xxx)
|
|
||||||
//是否打印 ehci 配置信息
|
//是否打印 ehci 配置信息
|
||||||
#define CONFIG_USB_EHCI_INFO_ENABLE
|
#define CONFIG_USB_EHCI_INFO_ENABLE
|
||||||
//是否关闭保留寄存器的占位,默认保留 9 个双字的占位
|
//是否关闭保留寄存器的占位,默认保留 9 个双字的占位
|
||||||
#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
|
#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||||
//是否使能 configflag 寄存器中的 bit0
|
//是否使能 configflag 寄存器中的 bit0
|
||||||
#define CONFIG_USB_EHCI_CONFIGFLAG
|
#define CONFIG_USB_EHCI_CONFIGFLAG
|
||||||
//是否使能 port power bit
|
//是否使能 port power bit
|
||||||
#define CONFIG_USB_EHCI_PORT_POWER
|
#define CONFIG_USB_EHCI_PORT_POWER
|
||||||
|
//是否查看 ehci 配置信息
|
||||||
|
#define CONFIG_USB_EHCI_PRINT_HW_PARAM
|
||||||
|
|
||||||
同时由于 EHCI 只是主机控制器并且只支持高速,一般配合一个 otg 控制器和一个低速全速兼容控制单元,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。
|
同时由于 EHCI 只是主机控制器并且只支持高速,一般配合一个 otg 控制器和一个低速全速兼容控制单元,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。
|
||||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 24 KiB |
@@ -4,7 +4,6 @@
|
|||||||
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
|
在学习 USB 或者是学习 CherryUSB 代码之前,我们需要先基于现有的 demo 进行快速验证,为什么?是为了提升对 USB 的兴趣,能有信心进行下一步的动作,如果 demo 都跑不起来,或者自己摸索写代码,或者先看 USB 基本概念,结果看到最后,
|
||||||
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
|
发现一点都看不懂,概念好多,根本记不住,从而丧失对 USB 的兴趣。因此,先跑 demo 非常重要。下面我将给大家罗列目前支持的 demo 仓库。
|
||||||
|
|
||||||
|
|
||||||
基于 bouffalolab 系列芯片
|
基于 bouffalolab 系列芯片
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
@@ -100,23 +99,38 @@ USB Device 移植要点
|
|||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
||||||
#define USBD_IRQHandler OTG_HS_IRQHandler // pa11/pa12 引脚使用 OTG_FS_IRQHandler
|
// 需要根据硬件实际的 fifo 深度进行修改,默认是最基础的配置
|
||||||
#define USBD_BASE (0x40040000UL) // pa11/pa12 引脚一般使用 50000000UL,STM32F7/H7 使用 0x40080000UL
|
#define CONFIG_USBDEV_EP_NUM 6
|
||||||
#define CONFIG_USBDEV_EP_NUM 6 // pa11/pa12 引脚使用 4
|
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1012 - 16 * 6)
|
||||||
#define CONFIG_USB_DWC2_RAM_SIZE 4096 // pa11/pa12 引脚使用 1280
|
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (64 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (64 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
|
||||||
|
|
||||||
|
- 如果使用 fsdev ip,在 `usb_config.h` 中实现以下宏:
|
||||||
|
|
||||||
|
.. code-block:: C
|
||||||
|
|
||||||
|
#define CONFIG_USBDEV_EP_NUM 8
|
||||||
|
#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2
|
||||||
|
|
||||||
- 编译器推荐使用 **AC6**。勾选 **Microlib**,并实现 **printf** ,方便后续查看 log。
|
- 编译器推荐使用 **AC6**。勾选 **Microlib**,并实现 **printf** ,方便后续查看 log。
|
||||||
|
|
||||||
.. figure:: img/stm32_10.png
|
.. figure:: img/stm32_10.png
|
||||||
.. figure:: img/stm32_11.png
|
.. figure:: img/stm32_11.png
|
||||||
|
|
||||||
- 拷贝 **xxx_msp.c** 中的 **HAL_PCD_MspInit** 函数中的内容到 **usb_dc_low_level_init** 函数中,屏蔽 st 生成的 usb 中断函数和 usb 初始化
|
- 拷贝 **xxx_msp.c** 中的 **HAL_PCD_MspInit** 函数中的内容到 **usb_dc_low_level_init** 函数中,屏蔽 st 生成的 usb 初始化
|
||||||
|
|
||||||
.. figure:: img/stm32_12.png
|
.. figure:: img/stm32_12.png
|
||||||
.. figure:: img/stm32_13.png
|
|
||||||
.. figure:: img/stm32_14.png
|
.. figure:: img/stm32_14.png
|
||||||
|
|
||||||
- 调用 template 的内容初始化,就可以使用了
|
- 在中断函数中调用 `USBD_IRQHandler`,并传入 `busid`
|
||||||
|
|
||||||
|
.. figure:: img/stm32_13.png
|
||||||
|
|
||||||
|
- 调用 template 的内容初始化,并填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
|
||||||
|
|
||||||
.. figure:: img/stm32_15.png
|
.. figure:: img/stm32_15.png
|
||||||
|
|
||||||
@@ -134,12 +148,6 @@ USB Host 移植要点
|
|||||||
.. figure:: img/stm32_10.png
|
.. figure:: img/stm32_10.png
|
||||||
.. figure:: img/stm32_11.png
|
.. figure:: img/stm32_11.png
|
||||||
|
|
||||||
- 拷贝 **xxx_msp.c** 中的 **HAL_HCD_MspInit** 函数中的内容到 **usb_hc_low_level_init** 函数中,屏蔽 st 生成的 usb 中断函数和 usb 初始化
|
|
||||||
|
|
||||||
.. figure:: img/stm32_18.png
|
|
||||||
.. figure:: img/stm32_13.png
|
|
||||||
.. figure:: img/stm32_19.png
|
|
||||||
|
|
||||||
- 复制一份 **cherryusb_config_template.h**,放到 `Core/Inc` 目录下,并命名为 `usb_config.h`
|
- 复制一份 **cherryusb_config_template.h**,放到 `Core/Inc` 目录下,并命名为 `usb_config.h`
|
||||||
|
|
||||||
- 增加 **usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
|
- 增加 **usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
|
||||||
@@ -147,13 +155,19 @@ USB Host 移植要点
|
|||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
||||||
#define USBH_BASE (0x40040000UL)
|
// 需要根据硬件实际的 fifo 深度进行修改,默认是最基础的配置
|
||||||
#define USBH_IRQHandler OTG_HS_IRQHandler
|
|
||||||
#define CONFIG_USBHOST_PIPE_NUM 12
|
#define CONFIG_USBHOST_PIPE_NUM 12
|
||||||
|
#define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
|
||||||
|
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE) / 4)
|
||||||
|
|
||||||
- 调用 **usbh_initialize** 以及 os 需要的启动线程的函数即可使用
|
- 拷贝 **xxx_msp.c** 中的 `HAL_HCD_MspInit` 函数中的内容到 `usb_hc_low_level_init` 函数中,屏蔽 st 生成的 usb 初始化
|
||||||
|
- 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`
|
||||||
|
- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
|
||||||
|
- 启动线程
|
||||||
|
|
||||||
.. figure:: img/stm32_20.png
|
.. figure:: img/stm32_18.png
|
||||||
|
.. figure:: img/stm32_19.png
|
||||||
|
|
||||||
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
|
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
|
||||||
|
|
||||||
|
|||||||