Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7df43ba6a2 | ||
|
|
e58a78c070 | ||
|
|
1492b8cca9 | ||
|
|
67a3bbe02e | ||
|
|
65b2de960b | ||
|
|
019c9cff6e | ||
|
|
2662a3497d | ||
|
|
7f7add7cec | ||
|
|
fa2900d4cd | ||
|
|
d30d08ca3a | ||
|
|
02685793aa | ||
|
|
8cd31e6be0 | ||
|
|
56c2b34131 | ||
|
|
f68a86ea89 | ||
|
|
8a831cdaa5 | ||
|
|
44e9c1cf4f | ||
|
|
e201439722 | ||
|
|
01f9025b6b | ||
|
|
bb709437aa | ||
|
|
7b936db889 | ||
|
|
6db1ef3a40 | ||
|
|
8f991699cb | ||
|
|
29d45ef5c7 | ||
|
|
a1ed27523c | ||
|
|
ce2a438c99 | ||
|
|
297852ce16 | ||
|
|
b1e95f0ca3 | ||
|
|
14f1f597f1 | ||
|
|
48730e20be | ||
|
|
11e389f922 | ||
|
|
82cd79989c | ||
|
|
fe18d36fe0 | ||
|
|
d414fd21d8 | ||
|
|
c8a11be013 | ||
|
|
fb6a463cc1 | ||
|
|
7e3795c191 | ||
|
|
22d60b4300 | ||
|
|
85e73197f9 | ||
|
|
c90f273e24 | ||
|
|
b14976dd56 | ||
|
|
9cd88c0ca3 | ||
|
|
3440e0cc1d | ||
|
|
849ea98853 | ||
|
|
b5f0c043e7 | ||
|
|
84299ce80b | ||
|
|
8e0c5b4e7e | ||
|
|
8ae4453ca4 | ||
|
|
86c7e435a3 | ||
|
|
074f30a7b4 | ||
|
|
50e1cd3471 | ||
|
|
b7d02b7125 | ||
|
|
5b32482c3e | ||
|
|
18eed18413 | ||
|
|
98c6ac25ec | ||
|
|
af1484882d | ||
|
|
e3c9fdbb86 | ||
|
|
03db11f4af | ||
|
|
d6bd89f274 | ||
|
|
9ea2121c7c | ||
|
|
bbcb433564 | ||
|
|
7989708bfe | ||
|
|
07fa211f40 | ||
|
|
73eb69bfa2 | ||
|
|
a08097c90e | ||
|
|
5bbe2a97f2 |
61
README.md
61
README.md
@@ -70,7 +70,7 @@ CherryUSB Device Stack has the following functions:
|
||||
- Support USB2.0 full and high speed, USB3.0 super speed
|
||||
- Support endpoint irq callback register by users, let users do whatever they wants in endpoint irq callback.
|
||||
- Support Composite Device
|
||||
- Support Communication Device Class (CDC)
|
||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB VIDEO CLASS (UVC1.0、UVC1.5)
|
||||
@@ -103,36 +103,38 @@ CherryUSB Host Stack has the following functions:
|
||||
- Support blocking transfers and asynchronous transfers
|
||||
- Support Composite Device
|
||||
- Multi-level HUB support, expandable up to 7 levels
|
||||
- Support Communication Device Class (CDC)
|
||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support Vendor class
|
||||
- Support USB modeswitch
|
||||
|
||||
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
|
||||
|
||||
CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
@@ -144,8 +146,6 @@ x is affected by the following macros:
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## Documentation Tutorial
|
||||
@@ -162,22 +162,19 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|
||||
|
||||
## Demo Repo
|
||||
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url |Current version|
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Phytium | PhytiumPI | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|
||||
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
61
README_zh.md
61
README_zh.md
@@ -68,7 +68,7 @@ CherryUSB Device 协议栈当前实现以下功能:
|
||||
- 支持 USB2.0 全速和高速设备,USB3.0 超速设备
|
||||
- 支持端点中断注册功能,porting 给用户自己处理中断里的数据
|
||||
- 支持复合设备
|
||||
- 支持 Communication Device Class (CDC)
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- 支持 Human Interface Device (HID)
|
||||
- 支持 Mass Storage Class (MSC)
|
||||
- 支持 USB VIDEO CLASS (UVC1.0、UVC1.5)
|
||||
@@ -101,36 +101,38 @@ CherryUSB Host 协议栈当前实现以下功能:
|
||||
- 支持阻塞式传输和异步传输
|
||||
- 支持复合设备
|
||||
- 支持多级 HUB,最高可拓展到 7 级
|
||||
- 支持 Communication Device Class (CDC)
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- 支持 Human Interface Device (HID)
|
||||
- 支持 Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 USB modeswitch
|
||||
|
||||
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||
|
||||
CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|
||||
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|
||||
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|
||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
@@ -142,8 +144,6 @@ x 受以下宏影响:
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
```
|
||||
|
||||
## 文档教程
|
||||
@@ -160,22 +160,19 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
|
||||
|
||||
## 示例仓库
|
||||
|
||||
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 当前版本 |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.10.1 |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|≤ v0.10.1 |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)| v0.10.1 |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|≤ v0.10.1 |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|≤ v0.10.1 |
|
||||
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Phytium | e2000 | pusb2 |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.1 |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|≤ v0.10.1 |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|≤ v0.10.1 |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|≤ v0.10.1 |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|≤ v0.10.1 |
|
||||
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
25
SConscript
25
SConscript
@@ -62,14 +62,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_FS']):
|
||||
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=FS_PORT']
|
||||
elif GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_HS']):
|
||||
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=HS_PORT']
|
||||
if GetDepend(['SOC_SERIES_STM32F7']):
|
||||
CPPDEFINES += ['STM32F7']
|
||||
elif GetDepend(['SOC_SERIES_STM32H7']):
|
||||
CPPDEFINES += ['STM32H7']
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_STM32']):
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
@@ -107,10 +101,13 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
src += Glob('class/msc/usbh_msc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
|
||||
src += Glob('class/wireless/usbh_rndis.c')
|
||||
src += Glob('third_party/rt-thread-4.1.1/rndis_host/rndis_host.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')
|
||||
@@ -135,13 +132,11 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
||||
src += Glob('demo/usb_host.c')
|
||||
|
||||
if GetDepend('RT_USING_DFS'):
|
||||
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
|
||||
path += [cwd + '/class/vendor/cp201x']
|
||||
src += Glob('class/vendor/cp201x/usbh_cp210x.c')
|
||||
src += Glob('third_party/rt-thread-4.1.1/dfs/drv_usbh_cp210x_rtt.c')
|
||||
|
||||
src += Glob('third_party/rt-thread-4.1.1/msh_cmd.c')
|
||||
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
|
||||
|
||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
|
||||
5
VERSION
Normal file
5
VERSION
Normal file
@@ -0,0 +1,5 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
PATCHLEVEL = 99
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
@@ -6,7 +6,8 @@
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x001002
|
||||
#define CHERRYUSB_VERSION 0x010000
|
||||
#define CHERRYUSB_VERSION_STR "v1.0.0"
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
@@ -93,8 +94,8 @@
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
@@ -106,7 +107,7 @@
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
||||
#ifndef CONFIG_USBHOST_PSC_PRIO
|
||||
#define CONFIG_USBHOST_PSC_PRIO 4
|
||||
#define CONFIG_USBHOST_PSC_PRIO 0
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
|
||||
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
|
||||
@@ -130,13 +131,15 @@
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
//#define USBD_IRQHandler USBD_IRQHandler
|
||||
//#define USB_BASE (0x40080000UL)
|
||||
//#define USB_NUM_BIDIR_ENDPOINTS 4
|
||||
#define USBD_IRQHandler USBD_IRQHandler
|
||||
#define USBD_BASE (0)
|
||||
#define CONFIG_USBDEV_EP_NUM 4
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
|
||||
#define CONFIG_USBHOST_PIPE_NUM 10
|
||||
// #define USBH_IRQHandler USBH_IRQHandler
|
||||
// #define USBH_BASE (0)
|
||||
// #define CONFIG_USBHOST_PIPE_NUM 10
|
||||
|
||||
/* ================ EHCI Configuration ================ */
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
|
||||
uint8_t altsetting = 1;
|
||||
|
||||
if (audio_class->is_opened) {
|
||||
return -EMFILE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->module_num; i++) {
|
||||
@@ -79,7 +79,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
|
||||
freq_found:
|
||||
|
||||
@@ -89,7 +89,7 @@ freq_found:
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ freq_found:
|
||||
setup->wLength = 3;
|
||||
|
||||
memcpy(g_audio_buf, &samp_freq, 3);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -112,10 +112,10 @@ freq_found:
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
audio_class->isoin_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&audio_class->isoin, audio_class->hport, ep_desc);
|
||||
USBH_EP_INIT(audio_class->isoin, ep_desc);
|
||||
} else {
|
||||
audio_class->isoout_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&audio_class->isoout, audio_class->hport, ep_desc);
|
||||
USBH_EP_INIT(audio_class->isoout, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
|
||||
@@ -138,7 +138,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Close audio module :%s\r\n", name);
|
||||
@@ -147,12 +147,10 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
if (audio_class->isoin) {
|
||||
usbh_pipe_free(audio_class->isoin);
|
||||
audio_class->isoin = NULL;
|
||||
}
|
||||
} else {
|
||||
if (audio_class->isoout) {
|
||||
usbh_pipe_free(audio_class->isoout);
|
||||
audio_class->isoout = NULL;
|
||||
}
|
||||
}
|
||||
@@ -163,7 +161,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -184,7 +182,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -196,7 +194,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
|
||||
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
|
||||
|
||||
memcpy(g_audio_buf, &volume_hex, 2);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -216,7 +214,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -226,7 +224,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
|
||||
setup->wLength = 1;
|
||||
|
||||
memcpy(g_audio_buf, &mute, 1);
|
||||
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -277,7 +275,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_audio *audio_class = usbh_audio_class_alloc();
|
||||
if (audio_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc audio_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
audio_class->hport = hport;
|
||||
@@ -386,7 +384,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
|
||||
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
audio_class->module_num = input_offset;
|
||||
@@ -416,11 +414,9 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (audio_class) {
|
||||
if (audio_class->isoin) {
|
||||
usbh_pipe_free(audio_class->isoin);
|
||||
}
|
||||
|
||||
if (audio_class->isoout) {
|
||||
usbh_pipe_free(audio_class->isoout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
|
||||
@@ -40,11 +40,11 @@ struct usbh_audio_module {
|
||||
|
||||
struct usbh_audio {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t isoin; /* ISO IN endpoint */
|
||||
usbh_pipe_t isoout; /* ISO OUT endpoint */
|
||||
uint16_t isoin_mps;
|
||||
uint16_t isoout_mps;
|
||||
bool is_opened;
|
||||
|
||||
@@ -19,9 +19,9 @@ static struct usbd_endpoint cdc_ecm_ep_data[3];
|
||||
#define CDC_ECM_MAX_PACKET_SIZE 64
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
|
||||
|
||||
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
|
||||
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
|
||||
@@ -186,7 +186,7 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
|
||||
uint8_t *buffer;
|
||||
|
||||
if (g_cdc_ecm_tx_data_length > 0) {
|
||||
return -EBUSY;
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
|
||||
|
||||
@@ -50,7 +50,7 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
|
||||
memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
@@ -64,7 +64,7 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
setup->wIndex = cdc_acm_class->ctrl_intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
|
||||
cdc_acm_class->dtr = dtr;
|
||||
cdc_acm_class->rts = rts;
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@@ -96,7 +96,7 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
|
||||
if (cdc_acm_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
cdc_acm_class->hport = hport;
|
||||
@@ -124,15 +124,15 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&cdc_acm_class->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
|
||||
#endif
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_acm_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_acm_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_acm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,13 +152,19 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (cdc_acm_class) {
|
||||
if (cdc_acm_class->bulkin) {
|
||||
usbh_pipe_free(cdc_acm_class->bulkin);
|
||||
usbh_kill_urb(&cdc_acm_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (cdc_acm_class->bulkout) {
|
||||
usbh_pipe_free(cdc_acm_class->bulkout);
|
||||
usbh_kill_urb(&cdc_acm_class->bulkout_urb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
if (cdc_acm_class->intin) {
|
||||
usbh_kill_urb(&cdc_acm_class->intin_urb);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_cdc_acm_stop(cdc_acm_class);
|
||||
@@ -170,6 +176,32 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_acm_class->bulkout_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
struct usbh_cdc_acm {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb intin_urb;
|
||||
|
||||
struct cdc_line_coding linecoding;
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
@@ -17,11 +23,6 @@ struct usbh_cdc_acm {
|
||||
bool dtr;
|
||||
bool rts;
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -32,6 +33,9 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
|
||||
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
|
||||
|
||||
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class);
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class);
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
|
||||
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
|
||||
|
||||
static struct usbh_cdc_ecm g_cdc_ecm_class;
|
||||
|
||||
@@ -36,21 +36,25 @@ static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class
|
||||
setup->wIndex = cdc_ecm_class->ctrl_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(cdc_ecm_class->hport->ep0, 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 ret;
|
||||
|
||||
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->hport, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_ecm_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
|
||||
cdc_ecm_class->connect_status = g_cdc_ecm_inttx_buffer[2];
|
||||
if (g_cdc_ecm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
|
||||
cdc_ecm_class->connect_status = true;
|
||||
} else {
|
||||
cdc_ecm_class->connect_status = false;
|
||||
}
|
||||
} else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
|
||||
memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8);
|
||||
}
|
||||
@@ -69,6 +73,8 @@ static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
struct usbh_cdc_ecm *cdc_ecm_class = &g_cdc_ecm_class;
|
||||
|
||||
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
|
||||
|
||||
cdc_ecm_class->hport = hport;
|
||||
cdc_ecm_class->ctrl_intf = intf;
|
||||
cdc_ecm_class->data_intf = intf + 1;
|
||||
@@ -105,7 +111,7 @@ get_mac:
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mac_buffer, 0, 8);
|
||||
memset(mac_buffer, 0, 12);
|
||||
ret = usbh_get_string_desc(cdc_ecm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -137,7 +143,7 @@ get_mac:
|
||||
|
||||
/* enable int ep */
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_ecm_class->intin, ep_desc);
|
||||
|
||||
if (hport->config.intf[intf + 1].altsetting_num > 1) {
|
||||
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
|
||||
@@ -146,9 +152,9 @@ get_mac:
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +165,9 @@ get_mac:
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,15 +200,15 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (cdc_ecm_class) {
|
||||
if (cdc_ecm_class->bulkin) {
|
||||
usbh_pipe_free(cdc_ecm_class->bulkin);
|
||||
usbh_kill_urb(&cdc_ecm_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->bulkout) {
|
||||
usbh_pipe_free(cdc_ecm_class->bulkout);
|
||||
usbh_kill_urb(&cdc_ecm_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (cdc_ecm_class->intin) {
|
||||
usbh_pipe_free(cdc_ecm_class->intin);
|
||||
usbh_kill_urb(&cdc_ecm_class->intin_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
@@ -216,37 +222,34 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usbh_cdc_ecm_rx_thread(void *argument)
|
||||
void usbh_cdc_ecm_rx_thread(void *argument)
|
||||
{
|
||||
uint32_t g_cdc_ecm_rx_length;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
uint16_t ep_mps;
|
||||
|
||||
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
while (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
|
||||
usb_osal_msleep(1000);
|
||||
g_cdc_ecm_class.connect_status = false;
|
||||
if (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
|
||||
while (g_cdc_ecm_class.connect_status == false) {
|
||||
ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_class.hport->speed == USB_SPEED_FULL) {
|
||||
ep_mps = 64;
|
||||
} else {
|
||||
ep_mps = 512;
|
||||
}
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
@@ -254,13 +257,14 @@ find_class:
|
||||
|
||||
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
|
||||
|
||||
if (g_cdc_ecm_rx_length % ep_mps) {
|
||||
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
@@ -272,6 +276,11 @@ find_class:
|
||||
} else {
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete cdc ecm rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
@@ -280,7 +289,7 @@ err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer = g_cdc_ecm_tx_buffer;
|
||||
|
||||
if (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) {
|
||||
if (g_cdc_ecm_class.connect_status == false) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
@@ -291,7 +300,7 @@ err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
|
||||
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
@@ -300,11 +309,6 @@ err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif)
|
||||
{
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, netif);
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,20 +13,21 @@
|
||||
|
||||
struct usbh_cdc_ecm {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
|
||||
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
|
||||
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
|
||||
uint8_t mac[6];
|
||||
uint32_t max_segment_size;
|
||||
uint8_t connect_status;
|
||||
bool connect_status;
|
||||
uint16_t max_segment_size;
|
||||
uint32_t speed[2];
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint */
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb intin_urb;
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
@@ -41,7 +42,7 @@ void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
void usbh_cdc_ecm_lwip_thread_init(struct netif *netif);
|
||||
void usbh_cdc_ecm_rx_thread(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 128;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hid_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
@@ -81,7 +81,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hid_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@@ -110,7 +110,7 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||
if (hid_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hid_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
hid_class->hport = hport;
|
||||
@@ -137,9 +137,9 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&hid_class->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(hid_class->intin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&hid_class->intout, hport, ep_desc);
|
||||
USBH_EP_INIT(hid_class->intout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,11 +159,11 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (hid_class) {
|
||||
if (hid_class->intin) {
|
||||
usbh_pipe_free(hid_class->intin);
|
||||
usbh_kill_urb(&hid_class->intin_urb);
|
||||
}
|
||||
|
||||
if (hid_class->intout) {
|
||||
usbh_pipe_free(hid_class->intout);
|
||||
usbh_kill_urb(&hid_class->intout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
|
||||
struct usbh_hid {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||
|
||||
uint8_t report_desc[128];
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t intin; /* INTR IN endpoint */
|
||||
usbh_pipe_t intout; /* INTR OUT endpoint */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/hub%d"
|
||||
#define DEV_FORMAT "/dev/hub%d"
|
||||
|
||||
#define HUB_DEBOUNCE_TIMEOUT 1500
|
||||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 100
|
||||
#define DELAY_TIME_AFTER_RESET 200
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
|
||||
@@ -24,10 +25,8 @@ usb_osal_mq_t hub_mq;
|
||||
|
||||
struct usbh_hub roothub;
|
||||
|
||||
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_free_devaddr(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
|
||||
|
||||
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
@@ -101,7 +100,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -122,7 +121,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -145,7 +144,7 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 4;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -165,7 +164,7 @@ static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t fea
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
@@ -180,7 +179,7 @@ static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t f
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
@@ -195,7 +194,7 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
@@ -240,7 +239,7 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -258,7 +257,7 @@ static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feat
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -294,13 +293,33 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
|
||||
}
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_free_devaddr(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_kill_urb(&child->ep0_urb);
|
||||
usb_osal_mutex_delete(child->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
|
||||
if (nbytes > 0)
|
||||
{
|
||||
if (nbytes > 0) {
|
||||
usbh_hub_thread_wakeup(hub);
|
||||
}
|
||||
}
|
||||
@@ -314,7 +333,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_hub *hub = usbh_hub_class_alloc();
|
||||
if (hub == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc hub_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
hub->hub_addr = hport->dev_addr;
|
||||
@@ -336,7 +355,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&hub->intin, hport, ep_desc);
|
||||
USBH_EP_INIT(hub->intin, ep_desc);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -376,7 +395,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
hub->int_buffer = g_hub_intbuf[hub->index - 1];
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
return 0;
|
||||
}
|
||||
@@ -390,19 +409,12 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (hub) {
|
||||
if (hub->intin) {
|
||||
usbh_pipe_free(hub->intin);
|
||||
usbh_kill_urb(&hub->intin_urb);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
child = &hub->child[port];
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_hubport_release(child);
|
||||
child->parent = NULL;
|
||||
}
|
||||
|
||||
@@ -417,27 +429,10 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hubport_enumerate_thread(void *argument)
|
||||
{
|
||||
struct usbh_hubport *child = (struct usbh_hubport *)argument;
|
||||
|
||||
/* Configure EP0 with the default maximum packet size */
|
||||
usbh_hport_activate_ep0(child);
|
||||
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
@@ -604,11 +599,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
child->connected = true;
|
||||
child->port = port + 1;
|
||||
child->speed = speed;
|
||||
child->mutex = usb_osal_mutex_create();
|
||||
|
||||
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
|
||||
|
||||
/* create disposable thread to enumerate device on current hport, do not block hub thread */
|
||||
child->thread = usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
||||
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
@@ -651,6 +647,8 @@ static void usbh_hub_thread(void *argument)
|
||||
|
||||
static void usbh_roothub_register(void)
|
||||
{
|
||||
usb_slist_init(&hub_class_head);
|
||||
|
||||
memset(&roothub, 0, sizeof(struct usbh_hub));
|
||||
|
||||
roothub.connected = true;
|
||||
@@ -662,11 +660,6 @@ static void usbh_roothub_register(void)
|
||||
usbh_hub_register(&roothub);
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
|
||||
}
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint8_t port)
|
||||
{
|
||||
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
|
||||
@@ -689,6 +682,36 @@ int usbh_hub_initialize(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hub_deinitialize(void)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
struct usbh_hubport *hport;
|
||||
size_t flags;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
usb_slist_for_each(i, &hub_class_head)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
|
||||
usbh_hubport_release(hport);
|
||||
}
|
||||
}
|
||||
|
||||
usb_hc_deinit();
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
usb_osal_mq_delete(hub_mq);
|
||||
usb_osal_thread_delete(hub_thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
const struct usbh_class_driver hub_class_driver = {
|
||||
.driver_name = "hub",
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#ifndef USBH_HUB_H
|
||||
#define USBH_HUB_H
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_hub.h"
|
||||
|
||||
#define USBH_HUB_MAX_PORTS 4
|
||||
@@ -14,12 +13,20 @@
|
||||
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
||||
|
||||
extern usb_slist_t hub_class_head;
|
||||
extern struct usbh_hub roothub;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint8_t port);
|
||||
|
||||
int usbh_hub_initialize(void);
|
||||
int usbh_hub_deinitialize(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -50,7 +50,7 @@ static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
|
||||
setup->wIndex = msc_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
return usbh_control_transfer(msc_class->hport->ep0, setup, buffer);
|
||||
return usbh_control_transfer(msc_class->hport, setup, buffer);
|
||||
}
|
||||
|
||||
static void usbh_msc_cbw_dump(struct CBW *cbw)
|
||||
@@ -87,9 +87,8 @@ static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &msc_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
@@ -101,9 +100,8 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &msc_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
@@ -111,7 +109,7 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
|
||||
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
|
||||
{
|
||||
int nbytes;
|
||||
|
||||
@@ -157,12 +155,12 @@ int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct C
|
||||
/* check csw status */
|
||||
if (csw->dSignature != MSC_CSW_Signature) {
|
||||
USB_LOG_ERR("csw signature error\r\n");
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (csw->bStatus != 0) {
|
||||
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
__err_exit:
|
||||
return nbytes < 0 ? (int)nbytes : 0;
|
||||
@@ -236,6 +234,132 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
|
||||
}
|
||||
|
||||
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
|
||||
memcpy(g_msc_buf, message, 31);
|
||||
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
|
||||
}
|
||||
|
||||
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
struct usbh_msc_modeswitch_config *config;
|
||||
|
||||
struct usbh_msc *msc_class = usbh_msc_class_alloc();
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc msc_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
msc_class->hport = hport;
|
||||
msc_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(msc_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(msc_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_msc_modeswitch_config) {
|
||||
uint8_t num = 0;
|
||||
while (1) {
|
||||
config = &g_msc_modeswitch_config[num];
|
||||
if (config && config->name) {
|
||||
if ((hport->device_desc.idVendor == config->vid) &&
|
||||
(hport->device_desc.idProduct == config->pid)) {
|
||||
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
|
||||
usbh_msc_modeswitch(msc_class, config->message_content);
|
||||
return 0;
|
||||
}
|
||||
num++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_msc_run(msc_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
|
||||
|
||||
if (msc_class) {
|
||||
if (msc_class->bulkin) {
|
||||
usbh_kill_urb(&msc_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (msc_class->bulkout) {
|
||||
usbh_kill_urb(&msc_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_msc_stop(msc_class);
|
||||
}
|
||||
|
||||
usbh_msc_class_free(msc_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
@@ -284,130 +408,6 @@ void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
|
||||
memcpy(g_msc_buf, message, 31);
|
||||
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
|
||||
}
|
||||
|
||||
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
struct usbh_msc_modeswitch_config *config;
|
||||
|
||||
struct usbh_msc *msc_class = usbh_msc_class_alloc();
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc msc_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msc_class->hport = hport;
|
||||
msc_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&msc_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_msc_modeswitch_config) {
|
||||
uint8_t num = 0;
|
||||
while (1) {
|
||||
config = &g_msc_modeswitch_config[num];
|
||||
if (config) {
|
||||
if ((hport->device_desc.idVendor == config->vid) &&
|
||||
(hport->device_desc.idProduct == config->pid)) {
|
||||
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
|
||||
usbh_msc_modeswitch(msc_class, config->message_content);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_msc_run(msc_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
|
||||
|
||||
if (msc_class) {
|
||||
if (msc_class->bulkin) {
|
||||
usbh_pipe_free(msc_class->bulkin);
|
||||
}
|
||||
|
||||
if (msc_class->bulkout) {
|
||||
usbh_pipe_free(msc_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_msc_stop(msc_class);
|
||||
}
|
||||
|
||||
usbh_msc_class_free(msc_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
|
||||
struct usbh_msc {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
|
||||
uint8_t intf; /* Data interface number */
|
||||
uint8_t sdchar;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
|
||||
uint16_t blocksize; /* Block size of USB mass storage device */
|
||||
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
|
||||
uint16_t blocksize; /* Block size of USB mass storage device */
|
||||
};
|
||||
|
||||
struct usbh_msc_modeswitch_config {
|
||||
|
||||
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MTP_H
|
||||
#define USB_MTP_H
|
||||
|
||||
#define USB_MTP_CLASS 0x06
|
||||
|
||||
#define USB_MTP_SUB_CLASS 0x01U
|
||||
#define USB_MTP_PROTOCOL 0x01U
|
||||
|
||||
/* MTP class requests */
|
||||
#define MTP_REQUEST_CANCEL 0x64U
|
||||
#define MTP_REQUEST_GET_EXT_EVENT_DATA 0x65U
|
||||
#define MTP_REQUEST_RESET 0x66U
|
||||
#define MTP_REQUEST_GET_DEVICE_STATUS 0x67U
|
||||
|
||||
/* Container Types */
|
||||
#define MTP_CONTAINER_TYPE_UNDEFINED 0U
|
||||
#define MTP_CONTAINER_TYPE_COMMAND 1U
|
||||
#define MTP_CONTAINER_TYPE_DATA 2U
|
||||
#define MTP_CONTAINER_TYPE_RESPONSE 3U
|
||||
#define MTP_CONTAINER_TYPE_EVENT 4U
|
||||
|
||||
/*
|
||||
* MTP Class specification Revision 1.1
|
||||
* Appendix D. Operations
|
||||
*/
|
||||
|
||||
/* Operations code */
|
||||
#define MTP_OP_GET_DEVICE_INFO 0x1001U
|
||||
#define MTP_OP_OPEN_SESSION 0x1002U
|
||||
#define MTP_OP_CLOSE_SESSION 0x1003U
|
||||
#define MTP_OP_GET_STORAGE_IDS 0x1004U
|
||||
#define MTP_OP_GET_STORAGE_INFO 0x1005U
|
||||
#define MTP_OP_GET_NUM_OBJECTS 0x1006U
|
||||
#define MTP_OP_GET_OBJECT_HANDLES 0x1007U
|
||||
#define MTP_OP_GET_OBJECT_INFO 0x1008U
|
||||
#define MTP_OP_GET_OBJECT 0x1009U
|
||||
#define MTP_OP_GET_THUMB 0x100AU
|
||||
#define MTP_OP_DELETE_OBJECT 0x100BU
|
||||
#define MTP_OP_SEND_OBJECT_INFO 0x100CU
|
||||
#define MTP_OP_SEND_OBJECT 0x100DU
|
||||
#define MTP_OP_FORMAT_STORE 0x100FU
|
||||
#define MTP_OP_RESET_DEVICE 0x1010U
|
||||
#define MTP_OP_GET_DEVICE_PROP_DESC 0x1014U
|
||||
#define MTP_OP_GET_DEVICE_PROP_VALUE 0x1015U
|
||||
#define MTP_OP_SET_DEVICE_PROP_VALUE 0x1016U
|
||||
#define MTP_OP_RESET_DEVICE_PROP_VALUE 0x1017U
|
||||
#define MTP_OP_TERMINATE_OPEN_CAPTURE 0x1018U
|
||||
#define MTP_OP_MOVE_OBJECT 0x1019U
|
||||
#define MTP_OP_COPY_OBJECT 0x101AU
|
||||
#define MTP_OP_GET_PARTIAL_OBJECT 0x101BU
|
||||
#define MTP_OP_INITIATE_OPEN_CAPTURE 0x101CU
|
||||
#define MTP_OP_GET_OBJECT_PROPS_SUPPORTED 0x9801U
|
||||
#define MTP_OP_GET_OBJECT_PROP_DESC 0x9802U
|
||||
#define MTP_OP_GET_OBJECT_PROP_VALUE 0x9803U
|
||||
#define MTP_OP_SET_OBJECT_PROP_VALUE 0x9804U
|
||||
#define MTP_OP_GET_OBJECT_PROPLIST 0x9805U
|
||||
#define MTP_OP_GET_OBJECT_PROP_REFERENCES 0x9810U
|
||||
#define MTP_OP_GETSERVICEIDS 0x9301U
|
||||
#define MTP_OP_GETSERVICEINFO 0x9302U
|
||||
#define MTP_OP_GETSERVICECAPABILITIES 0x9303U
|
||||
#define MTP_OP_GETSERVICEPROPDESC 0x9304U
|
||||
|
||||
/* MTP response code */
|
||||
#define MTP_RESPONSE_OK 0x2001U
|
||||
#define MTP_RESPONSE_GENERAL_ERROR 0x2002U
|
||||
#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006U
|
||||
#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007U
|
||||
#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008U
|
||||
#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009U
|
||||
#define MTP_RESPONSE_DEVICEPROP_NOT_SUPPORTED 0x200AU
|
||||
#define MTP_RESPONSE_STORE_FULL 0x200CU
|
||||
#define MTP_RESPONSE_ACCESS_DENIED 0x200FU
|
||||
#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013U
|
||||
#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_NOT_SUPPORTED 0x2014U
|
||||
#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015U
|
||||
#define MTP_RESPONSE_DEVICE_BUSY 0x2019U
|
||||
#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201AU
|
||||
#define MTP_RESPONSE_INVALID_PARAMETER 0x201DU
|
||||
#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201EU
|
||||
#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201FU
|
||||
#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801U
|
||||
#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807U
|
||||
#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80AU
|
||||
|
||||
/* MTP Object format codes */
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED 0x3000U
|
||||
#define MTP_OBJ_FORMAT_ASSOCIATION 0x3001U
|
||||
#define MTP_OBJ_FORMAT_SCRIPT 0x3002U
|
||||
#define MTP_OBJ_FORMAT_EXECUTABLE 0x3003U
|
||||
#define MTP_OBJ_FORMAT_TEXT 0x3004U
|
||||
#define MTP_OBJ_FORMAT_HTML 0x3005U
|
||||
#define MTP_OBJ_FORMAT_DPOF 0x3006U
|
||||
#define MTP_OBJ_FORMAT_AIFF 0x3007U
|
||||
#define MTP_OBJ_FORMAT_WAV 0x3008U
|
||||
#define MTP_OBJ_FORMAT_MP3 0x3009U
|
||||
#define MTP_OBJ_FORMAT_AVI 0x300AU
|
||||
#define MTP_OBJ_FORMAT_MPEG 0x300BU
|
||||
#define MTP_OBJ_FORMAT_ASF 0x300CU
|
||||
#define MTP_OBJ_FORMAT_DEFINED 0x3800U
|
||||
#define MTP_OBJ_FORMAT_EXIF_JPEG 0x3801U
|
||||
#define MTP_OBJ_FORMAT_TIFF_EP 0x3802U
|
||||
#define MTP_OBJ_FORMAT_FLASHPIX 0x3803U
|
||||
#define MTP_OBJ_FORMAT_BMP 0x3804U
|
||||
#define MTP_OBJ_FORMAT_CIFF 0x3805U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED0 0x3806U
|
||||
#define MTP_OBJ_FORMAT_GIF 0x3807U
|
||||
#define MTP_OBJ_FORMAT_JFIF 0x3808U
|
||||
#define MTP_OBJ_FORMAT_CD 0x3809U
|
||||
#define MTP_OBJ_FORMAT_PICT 0x380AU
|
||||
#define MTP_OBJ_FORMAT_PNG 0x380BU
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED1 0x380CU
|
||||
#define MTP_OBJ_FORMAT_TIFF 0x380DU
|
||||
#define MTP_OBJ_FORMAT_TIFF_IT 0x380EU
|
||||
#define MTP_OBJ_FORMAT_JP2 0x380FU
|
||||
#define MTP_OBJ_FORMAT_JPX 0x3810U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_FIRMWARE 0xB802U
|
||||
#define MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_AUDIO 0xB900U
|
||||
#define MTP_OBJ_FORMAT_WMA 0xB901U
|
||||
#define MTP_OBJ_FORMAT_OGG 0xB902U
|
||||
#define MTP_OBJ_FORMAT_AAC 0xB903U
|
||||
#define MTP_OBJ_FORMAT_AUDIBLE 0xB904U
|
||||
#define MTP_OBJ_FORMAT_FLAC 0xB906U
|
||||
#define MTP_OBJ_FORMAT_UNDEFINED_VIDEO 0xB980U
|
||||
#define MTP_OBJ_FORMAT_WMV 0xB981U
|
||||
#define MTP_OBJ_FORMAT_MP4_CONTAINER 0xB982U
|
||||
#define MTP_OBJ_FORMAT_MP2 0xB983U
|
||||
#define MTP_OBJ_FORMAT_3GP_CONTAINER 0xB984U
|
||||
|
||||
/* MTP event codes*/
|
||||
#define MTP_EVENT_UNDEFINED 0x4000U
|
||||
#define MTP_EVENT_CANCELTRANSACTION 0x4001U
|
||||
#define MTP_EVENT_OBJECTADDED 0x4002U
|
||||
#define MTP_EVENT_OBJECTREMOVED 0x4003U
|
||||
#define MTP_EVENT_STOREADDED 0x4004U
|
||||
#define MTP_EVENT_STOREREMOVED 0x4005U
|
||||
#define MTP_EVENT_DEVICEPROPCHANGED 0x4006U
|
||||
#define MTP_EVENT_OBJECTINFOCHANGED 0x4007U
|
||||
#define MTP_EVENT_DEVICEINFOCHANGED 0x4008U
|
||||
#define MTP_EVENT_REQUESTOBJECTTRANSFER 0x4009U
|
||||
#define MTP_EVENT_STOREFULL 0x400AU
|
||||
#define MTP_EVENT_DEVICERESET 0x400BU
|
||||
#define MTP_EVENT_STORAGEINFOCHANGED 0x400CU
|
||||
#define MTP_EVENT_CAPTURECOMPLETE 0x400DU
|
||||
#define MTP_EVENT_UNREPORTEDSTATUS 0x400EU
|
||||
#define MTP_EVENT_OBJECTPROPCHANGED 0xC801U
|
||||
#define MTP_EVENT_OBJECTPROPDESCCHANGED 0xC802U
|
||||
#define MTP_EVENT_OBJECTREFERENCESCHANGED 0xC803U
|
||||
|
||||
/* MTP device properties code*/
|
||||
#define MTP_DEV_PROP_UNDEFINED 0x5000U
|
||||
#define MTP_DEV_PROP_BATTERY_LEVEL 0x5001U
|
||||
#define MTP_DEV_PROP_FUNCTIONAL_MODE 0x5002U
|
||||
#define MTP_DEV_PROP_IMAGE_SIZE 0x5003U
|
||||
#define MTP_DEV_PROP_COMPRESSION_SETTING 0x5004U
|
||||
#define MTP_DEV_PROP_WHITE_BALANCE 0x5005U
|
||||
#define MTP_DEV_PROP_RGB_GAIN 0x5006U
|
||||
#define MTP_DEV_PROP_F_NUMBER 0x5007U
|
||||
#define MTP_DEV_PROP_FOCAL_LENGTH 0x5008U
|
||||
#define MTP_DEV_PROP_FOCUS_DISTANCE 0x5009U
|
||||
#define MTP_DEV_PROP_FOCUS_MODE 0x500AU
|
||||
#define MTP_DEV_PROP_EXPOSURE_METERING_MODE 0x500BU
|
||||
#define MTP_DEV_PROP_FLASH_MODE 0x500CU
|
||||
#define MTP_DEV_PROP_EXPOSURE_TIME 0x500DU
|
||||
#define MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE 0x500EU
|
||||
#define MTP_DEV_PROP_EXPOSURE_INDEX 0x500FU
|
||||
#define MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION 0x5010U
|
||||
#define MTP_DEV_PROP_DATETIME 0x5011U
|
||||
#define MTP_DEV_PROP_CAPTURE_DELAY 0x5012U
|
||||
#define MTP_DEV_PROP_STILL_CAPTURE_MODE 0x5013U
|
||||
#define MTP_DEV_PROP_CONTRAST 0x5014U
|
||||
#define MTP_DEV_PROP_SHARPNESS 0x5015U
|
||||
#define MTP_DEV_PROP_DIGITAL_ZOOM 0x5016U
|
||||
#define MTP_DEV_PROP_EFFECT_MODE 0x5017U
|
||||
#define MTP_DEV_PROP_BURST_NUMBER 0x5018U
|
||||
#define MTP_DEV_PROP_BURST_INTERVAL 0x5019U
|
||||
#define MTP_DEV_PROP_TIMELAPSE_NUMBER 0x501AU
|
||||
#define MTP_DEV_PROP_TIMELAPSE_INTERVAL 0x501BU
|
||||
#define MTP_DEV_PROP_FOCUS_METERING_MODE 0x501CU
|
||||
#define MTP_DEV_PROP_UPLOAD_URL 0x501DU
|
||||
#define MTP_DEV_PROP_ARTIST 0x501EU
|
||||
#define MTP_DEV_PROP_COPYRIGHT_INFO 0x501FU
|
||||
#define MTP_DEV_PROP_SYNCHRONIZATION_PARTNER 0xD401U
|
||||
#define MTP_DEV_PROP_DEVICE_FRIENDLY_NAME 0xD402U
|
||||
#define MTP_DEV_PROP_VOLUME 0xD403U
|
||||
#define MTP_DEV_PROP_SUPPORTEDFORMATSORDERED 0xD404U
|
||||
#define MTP_DEV_PROP_DEVICEICON 0xD405U
|
||||
#define MTP_DEV_PROP_PLAYBACK_RATE 0xD410U
|
||||
#define MTP_DEV_PROP_PLAYBACK_OBJECT 0xD411U
|
||||
#define MTP_DEV_PROP_PLAYBACK_CONTAINER 0xD412U
|
||||
#define MTP_DEV_PROP_SESSION_INITIATOR_VERSION_INFO 0xD406U
|
||||
#define MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE 0xD407U
|
||||
|
||||
/*
|
||||
* MTP Class specification Revision 1.1
|
||||
* Appendix B. Object Properties
|
||||
*/
|
||||
|
||||
/* MTP OBJECT PROPERTIES supported*/
|
||||
#define MTP_OB_PROP_STORAGE_ID 0xDC01U
|
||||
#define MTP_OB_PROP_OBJECT_FORMAT 0xDC02U
|
||||
#define MTP_OB_PROP_PROTECTION_STATUS 0xDC03U
|
||||
#define MTP_OB_PROP_OBJECT_SIZE 0xDC04U
|
||||
#define MTP_OB_PROP_ASSOC_TYPE 0xDC05U
|
||||
#define MTP_OB_PROP_ASSOC_DESC 0xDC06U
|
||||
#define MTP_OB_PROP_OBJ_FILE_NAME 0xDC07U
|
||||
#define MTP_OB_PROP_DATE_CREATED 0xDC08U
|
||||
#define MTP_OB_PROP_DATE_MODIFIED 0xDC09U
|
||||
#define MTP_OB_PROP_KEYWORDS 0xDC0AU
|
||||
#define MTP_OB_PROP_PARENT_OBJECT 0xDC0BU
|
||||
#define MTP_OB_PROP_ALLOWED_FOLD_CONTENTS 0xDC0CU
|
||||
#define MTP_OB_PROP_HIDDEN 0xDC0DU
|
||||
#define MTP_OB_PROP_SYSTEM_OBJECT 0xDC0EU
|
||||
#define MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN 0xDC41U
|
||||
#define MTP_OB_PROP_SYNCID 0xDC42U
|
||||
#define MTP_OB_PROP_PROPERTY_BAG 0xDC43U
|
||||
#define MTP_OB_PROP_NAME 0xDC44U
|
||||
#define MTP_OB_PROP_CREATED_BY 0xDC45U
|
||||
#define MTP_OB_PROP_ARTIST 0xDC46U
|
||||
#define MTP_OB_PROP_DATE_AUTHORED 0xDC47U
|
||||
#define MTP_OB_PROP_DESCRIPTION 0xDC48U
|
||||
#define MTP_OB_PROP_URL_REFERENCE 0xDC49U
|
||||
#define MTP_OB_PROP_LANGUAGELOCALE 0xDC4AU
|
||||
#define MTP_OB_PROP_COPYRIGHT_INFORMATION 0xDC4BU
|
||||
#define MTP_OB_PROP_SOURCE 0xDC4CU
|
||||
#define MTP_OB_PROP_ORIGIN_LOCATION 0xDC4DU
|
||||
#define MTP_OB_PROP_DATE_ADDED 0xDC4EU
|
||||
#define MTP_OB_PROP_NON_CONSUMABLE 0xDC4FU
|
||||
#define MTP_OB_PROP_CORRUPTUNPLAYABLE 0xDC50U
|
||||
#define MTP_OB_PROP_PRODUCERSERIALNUMBER 0xDC51U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_SIZE 0xDC82U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DURATION 0xDC85U
|
||||
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DATA 0xDC86U
|
||||
#define MTP_OB_PROP_WIDTH 0xDC87U
|
||||
#define MTP_OB_PROP_HEIGHT 0xDC88U
|
||||
#define MTP_OB_PROP_DURATION 0xDC89U
|
||||
#define MTP_OB_PROP_RATING 0xDC8AU
|
||||
#define MTP_OB_PROP_TRACK 0xDC8BU
|
||||
#define MTP_OB_PROP_GENRE 0xDC8CU
|
||||
#define MTP_OB_PROP_CREDITS 0xDC8DU
|
||||
#define MTP_OB_PROP_LYRICS 0xDC8EU
|
||||
#define MTP_OB_PROP_SUBSCRIPTION_CONTENT_ID 0xDC8FU
|
||||
#define MTP_OB_PROP_PRODUCED_BY 0xDC90U
|
||||
#define MTP_OB_PROP_USE_COUNT 0xDC91U
|
||||
#define MTP_OB_PROP_SKIP_COUNT 0xDC92U
|
||||
#define MTP_OB_PROP_LAST_ACCESSED 0xDC93U
|
||||
#define MTP_OB_PROP_PARENTAL_RATING 0xDC94U
|
||||
#define MTP_OB_PROP_META_GENRE 0xDC95U
|
||||
#define MTP_OB_PROP_COMPOSER 0xDC96U
|
||||
#define MTP_OB_PROP_EFFECTIVE_RATING 0xDC97U
|
||||
#define MTP_OB_PROP_SUBTITLE 0xDC98U
|
||||
#define MTP_OB_PROP_ORIGINAL_RELEASE_DATE 0xDC99U
|
||||
#define MTP_OB_PROP_ALBUM_NAME 0xDC9AU
|
||||
#define MTP_OB_PROP_ALBUM_ARTIST 0xDC9BU
|
||||
#define MTP_OB_PROP_MOOD 0xDC9CU
|
||||
#define MTP_OB_PROP_DRM_STATUS 0xDC9DU
|
||||
#define MTP_OB_PROP_SUB_DESCRIPTION 0xDC9EU
|
||||
#define MTP_OB_PROP_IS_CROPPED 0xDCD1U
|
||||
#define MTP_OB_PROP_IS_COLOUR_CORRECTED 0xDCD2U
|
||||
#define MTP_OB_PROP_IMAGE_BIT_DEPTH 0xDCD3U
|
||||
#define MTP_OB_PROP_FNUMBER 0xDCD4U
|
||||
#define MTP_OB_PROP_EXPOSURE_TIME 0xDCD5U
|
||||
#define MTP_OB_PROP_EXPOSURE_INDEX 0xDCD6U
|
||||
#define MTP_OB_PROP_TOTAL_BITRATE 0xDE91U
|
||||
#define MTP_OB_PROP_BITRATE_TYPE 0xDE92U
|
||||
#define MTP_OB_PROP_SAMPLE_RATE 0xDE93U
|
||||
#define MTP_OB_PROP_NUMBER_OF_CHANNELS 0xDE94U
|
||||
#define MTP_OB_PROP_AUDIO_BITDEPTH 0xDE95U
|
||||
#define MTP_OB_PROP_SCAN_TYPE 0xDE97U
|
||||
#define MTP_OB_PROP_AUDIO_WAVE_CODEC 0xDE99U
|
||||
#define MTP_OB_PROP_AUDIO_BITRATE 0xDE9AU
|
||||
#define MTP_OB_PROP_VIDEO_FOURCC_CODEC 0xDE9BU
|
||||
#define MTP_OB_PROP_VIDEO_BITRATE 0xDE9CU
|
||||
#define MTP_OB_PROP_FRAMES_PER_THOUSAND_SECONDS 0xDE9DU
|
||||
#define MTP_OB_PROP_KEYFRAME_DISTANCE 0xDE9EU
|
||||
#define MTP_OB_PROP_BUFFER_SIZE 0xDE9FU
|
||||
#define MTP_OB_PROP_ENCODING_QUALITY 0xDEA0U
|
||||
#define MTP_OB_PROP_ENCODING_PROFILE 0xDEA1U
|
||||
#define MTP_OB_PROP_DISPLAY_NAME 0xDCE0U
|
||||
#define MTP_OB_PROP_BODY_TEXT 0xDCE1U
|
||||
#define MTP_OB_PROP_SUBJECT 0xDCE2U
|
||||
#define MTP_OB_PROP_PRIORITY 0xDCE3U
|
||||
#define MTP_OB_PROP_GIVEN_NAME 0xDD00U
|
||||
#define MTP_OB_PROP_MIDDLE_NAMES 0xDD01U
|
||||
#define MTP_OB_PROP_FAMILY_NAME 0xDD02U
|
||||
#define MTP_OB_PROP_PREFIX 0xDD03U
|
||||
#define MTP_OB_PROP_SUFFIX 0xDD04U
|
||||
#define MTP_OB_PROP_PHONETIC_GIVEN_NAME 0xDD05U
|
||||
#define MTP_OB_PROP_PHONETIC_FAMILY_NAME 0xDD06U
|
||||
#define MTP_OB_PROP_EMAIL_PRIMARY 0xDD07U
|
||||
#define MTP_OB_PROP_EMAIL_PERSONAL_1 0xDD08U
|
||||
#define MTP_OB_PROP_EMAIL_PERSONAL_2 0xDD09U
|
||||
#define MTP_OB_PROP_EMAIL_BUSINESS_1 0xDD0AU
|
||||
#define MTP_OB_PROP_EMAIL_BUSINESS_2 0xDD0BU
|
||||
#define MTP_OB_PROP_EMAIL_OTHERS 0xDD0CU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PRIMARY 0xDD0DU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL 0xDD0EU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL_2 0xDD0FU
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS 0xDD10U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS_2 0xDD11U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE 0xDD12U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE_2 0xDD13U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_PRIMARY 0xDD14U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_PERSONAL 0xDD15U
|
||||
#define MTP_OB_PROP_FAX_NUMBER_BUSINESS 0xDD16U
|
||||
#define MTP_OB_PROP_PAGER_NUMBER 0xDD17U
|
||||
#define MTP_OB_PROP_PHONE_NUMBER_OTHERS 0xDD18U
|
||||
#define MTP_OB_PROP_PRIMARY_WEB_ADDRESS 0xDD19U
|
||||
#define MTP_OB_PROP_PERSONAL_WEB_ADDRESS 0xDD1AU
|
||||
#define MTP_OB_PROP_BUSINESS_WEB_ADDRESS 0xDD1BU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS 0xDD1CU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_2 0xDD1DU
|
||||
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_3 0xDD1EU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1FU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2AU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2BU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2CU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_FULL 0xDD2DU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2EU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2FU
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_CITY 0xDD30U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_REGION 0xDD31U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32U
|
||||
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33U
|
||||
#define MTP_OB_PROP_ORGANIZATION_NAME 0xDD34U
|
||||
#define MTP_OB_PROP_PHONETIC_ORGANIZATION_NAME 0xDD35U
|
||||
#define MTP_OB_PROP_ROLE 0xDD36U
|
||||
#define MTP_OB_PROP_BIRTHDATE 0xDD37U
|
||||
#define MTP_OB_PROP_MESSAGE_TO 0xDD40U
|
||||
#define MTP_OB_PROP_MESSAGE_CC 0xDD41U
|
||||
#define MTP_OB_PROP_MESSAGE_BCC 0xDD42U
|
||||
#define MTP_OB_PROP_MESSAGE_READ 0xDD43U
|
||||
#define MTP_OB_PROP_MESSAGE_RECEIVED_TIME 0xDD44U
|
||||
#define MTP_OB_PROP_MESSAGE_SENDER 0xDD45U
|
||||
#define MTP_OB_PROP_ACT_BEGIN_TIME 0xDD50U
|
||||
#define MTP_OB_PROP_ACT_END_TIME 0xDD51U
|
||||
#define MTP_OB_PROP_ACT_LOCATION 0xDD52U
|
||||
#define MTP_OB_PROP_ACT_REQUIRED_ATTENDEES 0xDD54U
|
||||
#define MTP_OB_PROP_ACT_OPTIONAL_ATTENDEES 0xDD55U
|
||||
#define MTP_OB_PROP_ACT_RESOURCES 0xDD56U
|
||||
#define MTP_OB_PROP_ACT_ACCEPTED 0xDD57U
|
||||
#define MTP_OB_PROP_OWNER 0xDD5DU
|
||||
#define MTP_OB_PROP_EDITOR 0xDD5EU
|
||||
#define MTP_OB_PROP_WEBMASTER 0xDD5FU
|
||||
#define MTP_OB_PROP_URL_SOURCE 0xDD60U
|
||||
#define MTP_OB_PROP_URL_DESTINATION 0xDD61U
|
||||
#define MTP_OB_PROP_TIME_BOOKMARK 0xDD62U
|
||||
#define MTP_OB_PROP_OBJECT_BOOKMARK 0xDD63U
|
||||
#define MTP_OB_PROP_BYTE_BOOKMARK 0xDD64U
|
||||
#define MTP_OB_PROP_LAST_BUILD_DATE 0xDD70U
|
||||
#define MTP_OB_PROP_TIME_TO_LIVE 0xDD71U
|
||||
#define MTP_OB_PROP_MEDIA_GUID 0xDD72U
|
||||
|
||||
/* MTP storage type */
|
||||
#define MTP_STORAGE_UNDEFINED 0U
|
||||
#define MTP_STORAGE_FIXED_ROM 0x0001U
|
||||
#define MTP_STORAGE_REMOVABLE_ROM 0x0002U
|
||||
#define MTP_STORAGE_FIXED_RAM 0x0003U
|
||||
#define MTP_STORAGE_REMOVABLE_RAM 0x0004U
|
||||
|
||||
/* MTP file system type */
|
||||
#define MTP_FILESYSTEM_UNDEFINED 0U
|
||||
#define MTP_FILESYSTEM_GENERIC_FLAT 0x0001U
|
||||
#define MTP_FILESYSTEM_GENERIC_HIERARCH 0x0002U
|
||||
#define MTP_FILESYSTEM_DCF 0x0003U
|
||||
|
||||
/* MTP access capability */
|
||||
#define MTP_ACCESS_CAP_RW 0U /* read write */
|
||||
#define MTP_ACCESS_CAP_RO_WITHOUT_DEL 0x0001U
|
||||
#define MTP_ACCESS_CAP_RO_WITH_DEL 0x0002U
|
||||
|
||||
/* MTP standard data types supported */
|
||||
#define MTP_DATATYPE_INT8 0x0001U
|
||||
#define MTP_DATATYPE_UINT8 0x0002U
|
||||
#define MTP_DATATYPE_INT16 0x0003U
|
||||
#define MTP_DATATYPE_UINT16 0x0004U
|
||||
#define MTP_DATATYPE_INT32 0x0005U
|
||||
#define MTP_DATATYPE_UINT32 0x0006U
|
||||
#define MTP_DATATYPE_INT64 0x0007U
|
||||
#define MTP_DATATYPE_UINT64 0x0008U
|
||||
#define MTP_DATATYPE_UINT128 0x000AU
|
||||
#define MTP_DATATYPE_STR 0xFFFFU
|
||||
|
||||
/* MTP reading only or reading/writing */
|
||||
#define MTP_PROP_GET 0x00U
|
||||
#define MTP_PROP_GET_SET 0x01U
|
||||
|
||||
#define MTP_SESSION_CLOSED 0x00
|
||||
#define MTP_SESSION_OPENED 0x01
|
||||
|
||||
struct mtp_container_command {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
uint32_t param4;
|
||||
uint32_t param5;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_container_data {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
uint8_t data[512];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_container_response {
|
||||
uint32_t conlen;
|
||||
uint16_t contype;
|
||||
uint16_t code;
|
||||
uint32_t trans_id;
|
||||
} __PACKED;
|
||||
|
||||
/*Length of template descriptor: 23 bytes*/
|
||||
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
|
||||
|
||||
// clang-format off
|
||||
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x03, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
|
||||
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
|
||||
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x1c, 0x00, /* wMaxPacketSize */ \
|
||||
0x06 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_MTP_H */
|
||||
@@ -1,566 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_mtp.h"
|
||||
#include "usbd_mtp_config.h"
|
||||
|
||||
/* MTP Stage */
|
||||
enum Stage {
|
||||
MTP_READ_COMMAND = 0,
|
||||
MTP_DATA_OUT = 1,
|
||||
MTP_DATA_IN = 2,
|
||||
MTP_SEND_RESPONSE = 3,
|
||||
MTP_WAIT_RESPONSE = 4,
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct usbd_mtp_priv {
|
||||
USB_MEM_ALIGNX struct mtp_container_command con_command;
|
||||
USB_MEM_ALIGNX struct mtp_container_data con_data;
|
||||
USB_MEM_ALIGNX struct mtp_container_response con_response;
|
||||
enum Stage stage;
|
||||
uint8_t session_state;
|
||||
uint32_t response_code;
|
||||
} g_usbd_mtp;
|
||||
|
||||
/* Max USB packet size */
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define MTP_BULK_EP_MPS 64
|
||||
#else
|
||||
#define MTP_BULK_EP_MPS 512
|
||||
#endif
|
||||
|
||||
#define MTP_OUT_EP_IDX 0
|
||||
#define MTP_IN_EP_IDX 1
|
||||
#define MTP_INT_EP_IDX 2
|
||||
|
||||
/* Describe EndPoints configuration */
|
||||
static struct usbd_endpoint mtp_ep_data[3];
|
||||
|
||||
static int mtp_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("MTP Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case MTP_REQUEST_CANCEL:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_GET_EXT_EVENT_DATA:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_RESET:
|
||||
|
||||
break;
|
||||
case MTP_REQUEST_GET_DEVICE_STATUS:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled MTP Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbd_mtp_send_response(uint32_t code)
|
||||
{
|
||||
USB_LOG_DBG("Send response\r\n");
|
||||
|
||||
g_usbd_mtp.stage = MTP_WAIT_RESPONSE;
|
||||
|
||||
g_usbd_mtp.con_response.conlen = 12;
|
||||
g_usbd_mtp.con_response.contype = MTP_CONTAINER_TYPE_RESPONSE;
|
||||
g_usbd_mtp.con_response.code = code;
|
||||
g_usbd_mtp.con_response.trans_id = g_usbd_mtp.con_command.trans_id;
|
||||
|
||||
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_response, 12);
|
||||
}
|
||||
|
||||
static void usbd_mtp_send_info(uint8_t *data, uint32_t len)
|
||||
{
|
||||
USB_LOG_DBG("Send info\r\n");
|
||||
|
||||
g_usbd_mtp.stage = MTP_SEND_RESPONSE;
|
||||
|
||||
g_usbd_mtp.con_data.conlen = 12 + len;
|
||||
g_usbd_mtp.con_data.contype = MTP_CONTAINER_TYPE_DATA;
|
||||
g_usbd_mtp.con_data.code = MTP_RESPONSE_OK;
|
||||
g_usbd_mtp.con_data.trans_id = g_usbd_mtp.con_command.trans_id;
|
||||
|
||||
memcpy(g_usbd_mtp.con_data.data, data, len);
|
||||
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_data, 12 + len);
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_device_info(void)
|
||||
{
|
||||
struct mtp_device_info device_info;
|
||||
uint16_t i;
|
||||
|
||||
device_info.StandardVersion = 100;
|
||||
device_info.VendorExtensionID = 0x06;
|
||||
device_info.VendorExtensionVersion = 100;
|
||||
device_info.VendorExtensionDesc_len = (uint8_t)CONFIG_MTP_VEND_EXT_DESC_LEN;
|
||||
|
||||
for (i = 0; i < CONFIG_MTP_VEND_EXT_DESC_LEN; i++) {
|
||||
device_info.VendorExtensionDesc[i] = VendExtDesc[i];
|
||||
}
|
||||
|
||||
/* device supports one mode , standard mode */
|
||||
device_info.FunctionalMode = 0x0000;
|
||||
|
||||
/* All supported operation */
|
||||
device_info.OperationsSupported_len = CONFIG_MTP_SUPP_OP_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OP_LEN; i++) {
|
||||
device_info.OperationsSupported[i] = SuppOP[i];
|
||||
}
|
||||
|
||||
/* event that are currently generated by the device*/
|
||||
device_info.EventsSupported_len = CONFIG_MTP_SUPP_EVENTS_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_EVENTS_LEN; i++) {
|
||||
device_info.EventsSupported[i] = SuppEvents[i];
|
||||
}
|
||||
|
||||
device_info.DevicePropertiesSupported_len = CONFIG_MTP_SUPP_DEVICE_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_DEVICE_PROP_LEN; i++) {
|
||||
device_info.DevicePropertiesSupported[i] = DevicePropSupp[i];
|
||||
}
|
||||
|
||||
device_info.CaptureFormats_len = CONFIG_MTP_SUPP_CAPT_FORMAT_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_CAPT_FORMAT_LEN; i++) {
|
||||
device_info.CaptureFormats[i] = SuppCaptFormat[i];
|
||||
}
|
||||
|
||||
device_info.ImageFormats_len = CONFIG_MTP_SUPP_IMG_FORMAT_LEN; /* number of image formats that are supported by the device*/
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_IMG_FORMAT_LEN; i++) {
|
||||
device_info.ImageFormats[i] = SuppImgFormat[i];
|
||||
}
|
||||
|
||||
device_info.Manufacturer_len = (uint8_t)CONFIG_MTP_MANUF_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_MANUF_LEN; i++) {
|
||||
device_info.Manufacturer[i] = Manuf[i];
|
||||
}
|
||||
|
||||
device_info.Model_len = (uint8_t)CONFIG_MTP_MODEL_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_MODEL_LEN; i++) {
|
||||
device_info.Model[i] = Model[i];
|
||||
}
|
||||
|
||||
device_info.DeviceVersion_len = (uint8_t)CONFIG_MTP_DEVICE_VERSION_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_DEVICE_VERSION_LEN; i++) {
|
||||
device_info.DeviceVersion[i] = DeviceVers[i];
|
||||
}
|
||||
|
||||
device_info.SerialNumber_len = (uint8_t)CONFIG_MTP_SERIAL_NBR_LEN;
|
||||
for (i = 0U; i < CONFIG_MTP_SERIAL_NBR_LEN; i++) {
|
||||
device_info.SerialNumber[i] = SerialNbr[i];
|
||||
}
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&device_info, sizeof(struct mtp_device_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_open_session(void)
|
||||
{
|
||||
usbd_mtp_send_response(MTP_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_storage_ids(void)
|
||||
{
|
||||
struct mtp_storage_id storage_id;
|
||||
|
||||
storage_id.StorageIDS_len = CONFIG_MTP_STORAGE_ID_LEN;
|
||||
storage_id.StorageIDS[0] = MTP_STORAGE_ID;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&storage_id, sizeof(struct mtp_storage_id));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_storage_info(void)
|
||||
{
|
||||
struct mtp_storage_info storage_info;
|
||||
|
||||
storage_info.StorageType = MTP_STORAGE_REMOVABLE_RAM;
|
||||
storage_info.FilesystemType = MTP_FILESYSTEM_GENERIC_FLAT;
|
||||
storage_info.AccessCapability = MTP_ACCESS_CAP_RW;
|
||||
storage_info.MaxCapability = 0x0080DFA81A000000; // todo
|
||||
storage_info.FreeSpaceInBytes = 0x00007EEB0D000000; // todo
|
||||
storage_info.FreeSpaceInObjects = 0xFFFFFFFFU; /* not used */
|
||||
storage_info.StorageDescription = 0U;
|
||||
storage_info.VolumeLabel = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&storage_info, sizeof(struct mtp_storage_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_handles(void)
|
||||
{
|
||||
struct mtp_object_handle object_handle;
|
||||
|
||||
// todo
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&object_handle, sizeof(struct mtp_object_handle));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_info(void)
|
||||
{
|
||||
struct mtp_object_info object_info;
|
||||
|
||||
object_info.Storage_id = MTP_STORAGE_ID;
|
||||
object_info.ObjectFormat = 0; // todo
|
||||
object_info.ObjectCompressedSize = 0; //todo
|
||||
object_info.ProtectionStatus = 0U;
|
||||
object_info.ThumbFormat = MTP_OBJ_FORMAT_UNDEFINED;
|
||||
object_info.ThumbCompressedSize = 0U;
|
||||
object_info.ThumbPixWidth = 0U; /* not supported or not an image */
|
||||
object_info.ThumbPixHeight = 0U;
|
||||
object_info.ImagePixWidth = 0U;
|
||||
object_info.ImagePixHeight = 0U;
|
||||
object_info.ImageBitDepth = 0U;
|
||||
object_info.ParentObject = 0; // todo
|
||||
object_info.AssociationType = 0U;
|
||||
object_info.AssociationDesc = 0U;
|
||||
object_info.SequenceNumber = 0U;
|
||||
|
||||
/* we have to get this value before object_info.Filename */
|
||||
object_info.Filename_len = sizeof(DefaultFileName);
|
||||
memcpy(object_info.Filename, DefaultFileName, (uint32_t)object_info.Filename_len + 1U);
|
||||
|
||||
object_info.CaptureDate = 0U;
|
||||
object_info.ModificationDate = 0U;
|
||||
object_info.Keywords = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&object_info, sizeof(struct mtp_object_info));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_prop_desc(void)
|
||||
{
|
||||
struct mtp_object_prop_desc object_prop_desc;
|
||||
|
||||
uint16_t undef_format = MTP_OBJ_FORMAT_UNDEFINED;
|
||||
uint32_t storageid = MTP_STORAGE_ID;
|
||||
|
||||
switch (g_usbd_mtp.con_command.param1) /* switch obj prop code */
|
||||
{
|
||||
case MTP_OB_PROP_OBJECT_FORMAT:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = (uint8_t *)&undef_format;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_STORAGE_ID:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT32;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = (uint8_t *)&storageid;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJ_FILE_NAME:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PARENT_OBJECT:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_SIZE:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT64;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_NAME:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = NULL;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT128;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PROTECTION_STATUS:
|
||||
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
|
||||
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
|
||||
object_prop_desc.GetSet = MTP_PROP_GET_SET;
|
||||
object_prop_desc.DefValue = 0U;
|
||||
object_prop_desc.GroupCode = 0U;
|
||||
object_prop_desc.FormFlag = 0U;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// todo
|
||||
usbd_mtp_send_info((uint8_t *)&object_prop_desc, sizeof(struct mtp_object_prop_desc));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_props_supported(void)
|
||||
{
|
||||
struct mtp_object_props_support object_props_support;
|
||||
uint32_t i;
|
||||
|
||||
object_props_support.ObjectPropCode_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
|
||||
object_props_support.ObjectPropCode[i] = ObjectPropCode[i];
|
||||
}
|
||||
usbd_mtp_send_info((uint8_t *)&object_props_support, sizeof(struct mtp_object_props_support));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_object_prop_list(void)
|
||||
{
|
||||
struct mtp_object_prop_list object_prop_list;
|
||||
|
||||
uint16_t filename[255];
|
||||
uint32_t storageid = MTP_STORAGE_ID;
|
||||
uint32_t default_val = 0U;
|
||||
uint32_t i;
|
||||
uint16_t format;
|
||||
uint64_t objsize;
|
||||
uint32_t parent_proval;
|
||||
|
||||
object_prop_list.Properties_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
|
||||
|
||||
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
|
||||
object_prop_list.Properties[i].ObjectHandle = g_usbd_mtp.con_command.param1;
|
||||
|
||||
switch (ObjectPropCode[i]) {
|
||||
case MTP_OB_PROP_STORAGE_ID:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_STORAGE_ID;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&storageid;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_FORMAT:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_FORMAT;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&format;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJ_FILE_NAME:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJ_FILE_NAME;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
|
||||
object_prop_list.Properties[i].propval = NULL;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PARENT_OBJECT:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PARENT_OBJECT;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&parent_proval;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_OBJECT_SIZE:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_SIZE;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT64;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&objsize;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_NAME:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_NAME;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
|
||||
object_prop_list.Properties[i].propval = NULL;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT128;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&g_usbd_mtp.con_command.param1;
|
||||
break;
|
||||
|
||||
case MTP_OB_PROP_PROTECTION_STATUS:
|
||||
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PROTECTION_STATUS;
|
||||
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
|
||||
object_prop_list.Properties[i].propval = (uint8_t *)&default_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// todo
|
||||
usbd_mtp_send_info((uint8_t *)&object_prop_list, sizeof(struct mtp_object_prop_list));
|
||||
}
|
||||
|
||||
static void usbd_mtp_get_device_prop_desc(void)
|
||||
{
|
||||
struct mtp_device_prop_desc device_prop_desc;
|
||||
uint32_t i;
|
||||
|
||||
device_prop_desc.DevicePropertyCode = MTP_DEV_PROP_DEVICE_FRIENDLY_NAME;
|
||||
device_prop_desc.DataType = MTP_DATATYPE_STR;
|
||||
device_prop_desc.GetSet = MTP_PROP_GET_SET;
|
||||
device_prop_desc.DefaultValue_len = CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN;
|
||||
|
||||
for (i = 0U; i < (sizeof(DevicePropDefVal) / 2U); i++) {
|
||||
device_prop_desc.DefaultValue[i] = DevicePropDefVal[i];
|
||||
}
|
||||
|
||||
device_prop_desc.CurrentValue_len = CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN;
|
||||
|
||||
for (i = 0U; i < (sizeof(DevicePropCurDefVal) / 2U); i++) {
|
||||
device_prop_desc.CurrentValue[i] = DevicePropCurDefVal[i];
|
||||
}
|
||||
|
||||
device_prop_desc.FormFlag = 0U;
|
||||
|
||||
usbd_mtp_send_info((uint8_t *)&device_prop_desc, sizeof(struct mtp_device_prop_desc));
|
||||
}
|
||||
|
||||
static int usbd_mtp_decode_command(struct mtp_container_command *command)
|
||||
{
|
||||
printf("code:%04x\r\n", command->code);
|
||||
switch (command->code) {
|
||||
case MTP_OP_GET_DEVICE_INFO:
|
||||
usbd_mtp_get_device_info();
|
||||
break;
|
||||
case MTP_OP_OPEN_SESSION:
|
||||
usbd_mtp_open_session();
|
||||
break;
|
||||
case MTP_OP_CLOSE_SESSION:
|
||||
break;
|
||||
case MTP_OP_GET_STORAGE_IDS:
|
||||
usbd_mtp_get_storage_ids();
|
||||
break;
|
||||
case MTP_OP_GET_STORAGE_INFO:
|
||||
usbd_mtp_get_storage_info();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_HANDLES:
|
||||
usbd_mtp_get_object_handles();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_INFO:
|
||||
usbd_mtp_get_object_info();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_REFERENCES:
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROPS_SUPPORTED:
|
||||
usbd_mtp_get_object_props_supported();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_DESC:
|
||||
usbd_mtp_get_object_prop_desc();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROPLIST:
|
||||
usbd_mtp_get_object_prop_list();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT_PROP_VALUE:
|
||||
break;
|
||||
case MTP_OP_GET_DEVICE_PROP_DESC:
|
||||
usbd_mtp_get_device_prop_desc();
|
||||
break;
|
||||
case MTP_OP_GET_OBJECT:
|
||||
break;
|
||||
case MTP_OP_SEND_OBJECT_INFO:
|
||||
break;
|
||||
case MTP_OP_SEND_OBJECT:
|
||||
break;
|
||||
case MTP_OP_DELETE_OBJECT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbd_mtp_bulk_out(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
switch (g_usbd_mtp.stage) {
|
||||
case MTP_READ_COMMAND:
|
||||
usbd_mtp_decode_command(&g_usbd_mtp.con_command);
|
||||
break;
|
||||
case MTP_DATA_OUT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbd_mtp_bulk_in(uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
printf("send:%d\r\n", nbytes);
|
||||
switch (g_usbd_mtp.stage) {
|
||||
case MTP_DATA_IN:
|
||||
break;
|
||||
case MTP_SEND_RESPONSE:
|
||||
usbd_mtp_send_response(MTP_RESPONSE_OK);
|
||||
break;
|
||||
case MTP_WAIT_RESPONSE:
|
||||
USB_LOG_DBG("Start reading command\r\n");
|
||||
g_usbd_mtp.stage = MTP_READ_COMMAND;
|
||||
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mtp_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
USB_LOG_DBG("Start reading command\r\n");
|
||||
g_usbd_mtp.stage = MTP_READ_COMMAND;
|
||||
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep)
|
||||
{
|
||||
intf->class_interface_handler = mtp_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = mtp_notify_handler;
|
||||
|
||||
mtp_ep_data[MTP_OUT_EP_IDX].ep_addr = out_ep;
|
||||
mtp_ep_data[MTP_OUT_EP_IDX].ep_cb = usbd_mtp_bulk_out;
|
||||
mtp_ep_data[MTP_IN_EP_IDX].ep_addr = in_ep;
|
||||
mtp_ep_data[MTP_IN_EP_IDX].ep_cb = usbd_mtp_bulk_in;
|
||||
mtp_ep_data[MTP_INT_EP_IDX].ep_addr = int_ep;
|
||||
mtp_ep_data[MTP_INT_EP_IDX].ep_cb = NULL;
|
||||
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_IN_EP_IDX]);
|
||||
usbd_add_endpoint(&mtp_ep_data[MTP_INT_EP_IDX]);
|
||||
|
||||
return intf;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_MTP_H
|
||||
#define USBD_MTP_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_MTP_H */
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MTP_CONFIG_H
|
||||
#define USB_MTP_CONFIG_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
static const uint16_t VendExtDesc[] = { 'm', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '.', 'c', 'o', 'm', ':', ' ', '1', '.', '0', ';', ' ', 0 }; /* last 2 bytes must be 0*/
|
||||
|
||||
static const uint16_t SuppOP[] = { MTP_OP_GET_DEVICE_INFO, MTP_OP_OPEN_SESSION, MTP_OP_CLOSE_SESSION,
|
||||
MTP_OP_GET_STORAGE_IDS, MTP_OP_GET_STORAGE_INFO, MTP_OP_GET_NUM_OBJECTS,
|
||||
MTP_OP_GET_OBJECT_HANDLES, MTP_OP_GET_OBJECT_INFO, MTP_OP_GET_OBJECT,
|
||||
MTP_OP_DELETE_OBJECT, MTP_OP_SEND_OBJECT_INFO, MTP_OP_SEND_OBJECT,
|
||||
MTP_OP_GET_DEVICE_PROP_DESC, MTP_OP_GET_DEVICE_PROP_VALUE,
|
||||
MTP_OP_SET_OBJECT_PROP_VALUE, MTP_OP_GET_OBJECT_PROP_VALUE,
|
||||
MTP_OP_GET_OBJECT_PROPS_SUPPORTED, MTP_OP_GET_OBJECT_PROPLIST,
|
||||
MTP_OP_GET_OBJECT_PROP_DESC, MTP_OP_GET_OBJECT_PROP_REFERENCES };
|
||||
|
||||
static const uint16_t SuppEvents[] = { MTP_EVENT_OBJECTADDED };
|
||||
|
||||
static const uint16_t DevicePropSupp[] = { MTP_DEV_PROP_DEVICE_FRIENDLY_NAME, MTP_DEV_PROP_BATTERY_LEVEL };
|
||||
|
||||
static const uint16_t SuppCaptFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_ASSOCIATION, MTP_OBJ_FORMAT_TEXT };
|
||||
|
||||
static const uint16_t SuppImgFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_TEXT, MTP_OBJ_FORMAT_ASSOCIATION,
|
||||
MTP_OBJ_FORMAT_EXECUTABLE, MTP_OBJ_FORMAT_WAV, MTP_OBJ_FORMAT_MP3,
|
||||
MTP_OBJ_FORMAT_EXIF_JPEG, MTP_OBJ_FORMAT_MPEG, MTP_OBJ_FORMAT_MP4_CONTAINER,
|
||||
MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT, MTP_OBJ_FORMAT_PNG, MTP_OBJ_FORMAT_WMA,
|
||||
MTP_OBJ_FORMAT_WMV };
|
||||
|
||||
static const uint16_t Manuf[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t Model[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t DeviceVers[] = { 'V', '1', '.', '0', '0', 0 }; /* last 2 bytes must be 0*/
|
||||
/*SerialNbr shall be 32 character hexadecimal string for legacy compatibility reasons */
|
||||
static const uint16_t SerialNbr[] = { '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0', '0',
|
||||
'1', '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0',
|
||||
'0', '1', '0', '0', 0 }; /* last 2 bytes must be 0*/
|
||||
|
||||
static const uint16_t DefaultFileName[] = { 'N', 'e', 'w', ' ', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
|
||||
|
||||
static const uint16_t DevicePropDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
|
||||
static const uint16_t DevicePropCurDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 };
|
||||
|
||||
/* required for all object format : storageID, objectFormat, ObjectCompressedSize,
|
||||
persistent unique object identifier, name*/
|
||||
static const uint16_t ObjectPropCode[] = { MTP_OB_PROP_STORAGE_ID, MTP_OB_PROP_OBJECT_FORMAT, MTP_OB_PROP_OBJECT_SIZE,
|
||||
MTP_OB_PROP_OBJ_FILE_NAME, MTP_OB_PROP_PARENT_OBJECT, MTP_OB_PROP_NAME,
|
||||
MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN, MTP_OB_PROP_PROTECTION_STATUS };
|
||||
|
||||
#define MTP_STORAGE_ID 0x00010001U /* SD card is inserted*/
|
||||
|
||||
#define CONFIG_MTP_VEND_EXT_DESC_LEN (sizeof(VendExtDesc) / 2U)
|
||||
#define CONFIG_MTP_SUPP_OP_LEN (sizeof(SuppOP) / 2U)
|
||||
#define CONFIG_MTP_SUPP_EVENTS_LEN (sizeof(SuppEvents) / 2U)
|
||||
#define CONFIG_MTP_SUPP_DEVICE_PROP_LEN (sizeof(DevicePropSupp) / 2U)
|
||||
#define CONFIG_MTP_SUPP_CAPT_FORMAT_LEN (sizeof(SuppCaptFormat) / 2U)
|
||||
#define CONFIG_MTP_SUPP_IMG_FORMAT_LEN (sizeof(SuppImgFormat) / 2U)
|
||||
#define CONFIG_MTP_MANUF_LEN (sizeof(Manuf) / 2U)
|
||||
#define CONFIG_MTP_MODEL_LEN (sizeof(Model) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_VERSION_LEN (sizeof(DeviceVers) / 2U)
|
||||
#define CONFIG_MTP_SERIAL_NBR_LEN (sizeof(SerialNbr) / 2U)
|
||||
#define CONFIG_MTP_SUPP_OBJ_PROP_LEN (sizeof(ObjectPropCode) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN (sizeof(DevicePropDefVal) / 2U)
|
||||
#define CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN (sizeof(DevicePropCurDefVal) / 2U)
|
||||
#define CONFIG_MTP_STORAGE_ID_LEN 1
|
||||
#define CONFIG_MTP_OBJECT_HANDLE_LEN 100
|
||||
|
||||
struct mtp_device_info {
|
||||
uint16_t StandardVersion;
|
||||
uint32_t VendorExtensionID;
|
||||
uint16_t VendorExtensionVersion;
|
||||
uint8_t VendorExtensionDesc_len;
|
||||
uint16_t VendorExtensionDesc[CONFIG_MTP_VEND_EXT_DESC_LEN];
|
||||
uint16_t FunctionalMode;
|
||||
uint32_t OperationsSupported_len;
|
||||
uint16_t OperationsSupported[CONFIG_MTP_SUPP_OP_LEN];
|
||||
uint32_t EventsSupported_len;
|
||||
uint16_t EventsSupported[CONFIG_MTP_SUPP_EVENTS_LEN];
|
||||
uint32_t DevicePropertiesSupported_len;
|
||||
uint16_t DevicePropertiesSupported[CONFIG_MTP_SUPP_DEVICE_PROP_LEN];
|
||||
uint32_t CaptureFormats_len;
|
||||
uint16_t CaptureFormats[CONFIG_MTP_SUPP_CAPT_FORMAT_LEN];
|
||||
uint32_t ImageFormats_len;
|
||||
uint16_t ImageFormats[CONFIG_MTP_SUPP_IMG_FORMAT_LEN];
|
||||
uint8_t Manufacturer_len;
|
||||
uint16_t Manufacturer[CONFIG_MTP_MANUF_LEN];
|
||||
uint8_t Model_len;
|
||||
uint16_t Model[CONFIG_MTP_MODEL_LEN];
|
||||
uint8_t DeviceVersion_len;
|
||||
uint16_t DeviceVersion[CONFIG_MTP_DEVICE_VERSION_LEN];
|
||||
uint8_t SerialNumber_len;
|
||||
uint16_t SerialNumber[CONFIG_MTP_SERIAL_NBR_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_props_support {
|
||||
uint32_t ObjectPropCode_len;
|
||||
uint16_t ObjectPropCode[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_device_prop_desc {
|
||||
uint16_t DevicePropertyCode;
|
||||
uint16_t DataType;
|
||||
uint8_t GetSet;
|
||||
uint8_t DefaultValue_len;
|
||||
uint16_t DefaultValue[CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN];
|
||||
uint8_t CurrentValue_len;
|
||||
uint16_t CurrentValue[CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN];
|
||||
uint8_t FormFlag;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_storage_id {
|
||||
uint32_t StorageIDS_len;
|
||||
uint32_t StorageIDS[CONFIG_MTP_STORAGE_ID_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_storage_info {
|
||||
uint16_t StorageType;
|
||||
uint16_t FilesystemType;
|
||||
uint16_t AccessCapability;
|
||||
uint64_t MaxCapability;
|
||||
uint64_t FreeSpaceInBytes;
|
||||
uint32_t FreeSpaceInObjects;
|
||||
uint8_t StorageDescription;
|
||||
uint8_t VolumeLabel;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_handle {
|
||||
uint32_t ObjectHandle_len;
|
||||
uint32_t ObjectHandle[CONFIG_MTP_OBJECT_HANDLE_LEN];
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_info {
|
||||
uint32_t Storage_id;
|
||||
uint16_t ObjectFormat;
|
||||
uint16_t ProtectionStatus;
|
||||
uint32_t ObjectCompressedSize;
|
||||
uint16_t ThumbFormat;
|
||||
uint32_t ThumbCompressedSize;
|
||||
uint32_t ThumbPixWidth;
|
||||
uint32_t ThumbPixHeight;
|
||||
uint32_t ImagePixWidth;
|
||||
uint32_t ImagePixHeight;
|
||||
uint32_t ImageBitDepth;
|
||||
uint32_t ParentObject;
|
||||
uint16_t AssociationType;
|
||||
uint32_t AssociationDesc;
|
||||
uint32_t SequenceNumber;
|
||||
uint8_t Filename_len;
|
||||
uint16_t Filename[255];
|
||||
uint32_t CaptureDate;
|
||||
uint32_t ModificationDate;
|
||||
uint8_t Keywords;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_desc {
|
||||
uint16_t ObjectPropertyCode;
|
||||
uint16_t DataType;
|
||||
uint8_t GetSet;
|
||||
uint8_t *DefValue;
|
||||
uint32_t GroupCode;
|
||||
uint8_t FormFlag;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_element {
|
||||
uint32_t ObjectHandle;
|
||||
uint16_t PropertyCode;
|
||||
uint16_t Datatype;
|
||||
uint8_t *propval;
|
||||
} __PACKED;
|
||||
|
||||
struct mtp_object_prop_list {
|
||||
uint32_t Properties_len;
|
||||
struct mtp_object_prop_element Properties[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
|
||||
} __PACKED;
|
||||
|
||||
#endif /* USB_MTP_CONFIG_H */
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_mtp.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/mtp"
|
||||
|
||||
static int usbh_mtp_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_mtp *mtp_class = usb_malloc(sizeof(struct usbh_mtp));
|
||||
if (mtp_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc mtp_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mtp_class, 0, sizeof(struct usbh_mtp));
|
||||
mtp_class->hport = hport;
|
||||
mtp_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = mtp_class;
|
||||
|
||||
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&mtp_class->intin, hport, ep_desc);
|
||||
#endif
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&mtp_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&mtp_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register MTP Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_mtp_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_mtp *mtp_class = (struct usbh_mtp *)hport->config.intf[intf].priv;
|
||||
|
||||
if (mtp_class) {
|
||||
if (mtp_class->bulkin) {
|
||||
usbh_pipe_free(mtp_class->bulkin);
|
||||
}
|
||||
|
||||
if (mtp_class->bulkout) {
|
||||
usbh_pipe_free(mtp_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister MTP Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
|
||||
memset(mtp_class, 0, sizeof(struct usbh_mtp));
|
||||
usb_free(mtp_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver mtp_class_driver = {
|
||||
.driver_name = "mtp",
|
||||
.connect = usbh_mtp_connect,
|
||||
.disconnect = usbh_mtp_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info mtp_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_MTP_CLASS,
|
||||
.subclass = USB_MTP_SUB_CLASS,
|
||||
.protocol = USB_MTP_PROTOCOL,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &mtp_class_driver
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_MTP_H
|
||||
#define USBH_MTP_H
|
||||
|
||||
#include "usb_mtp.h"
|
||||
|
||||
struct usbh_mtp {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_MTP_H */
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_PRINTER_H
|
||||
#define USB_PRINTER_H
|
||||
|
||||
#define PRINTER_SUBCLASS 0x01U
|
||||
|
||||
#define PRINTER_REQUEST_GET_DEVICE_ID 0x00U
|
||||
#define PRINTER_REQUEST_GET_PORT_SATTUS 0x01U
|
||||
#define PRINTER_REQUEST_SOFT_RESET 0x02U
|
||||
|
||||
#define PRINTER_STATUS_NO_ERROR 0x00U
|
||||
#define PRINTER_STATUS_SELECTED 0x08U
|
||||
#define PRINTER_STATUS_PAPER_EMPTY 0x10U
|
||||
|
||||
#endif /* USB_PRINTER_H */
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_printer.h"
|
||||
|
||||
struct usbd_printer_priv {
|
||||
const uint8_t *device_id;
|
||||
uint8_t device_id_len;
|
||||
uint8_t port_status;
|
||||
} g_usbd_printer;
|
||||
|
||||
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USB_LOG_DBG("Printer Class request: "
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case PRINTER_REQUEST_GET_DEVICE_ID:
|
||||
memcpy(*data, g_usbd_printer.device_id, g_usbd_printer.device_id_len);
|
||||
*len = g_usbd_printer.device_id_len;
|
||||
break;
|
||||
case PRINTER_REQUEST_GET_PORT_SATTUS:
|
||||
|
||||
break;
|
||||
case PRINTER_REQUEST_SOFT_RESET:
|
||||
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled Printer Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void printer_notify_handler(uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len)
|
||||
{
|
||||
intf->class_interface_handler = printer_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = printer_notify_handler;
|
||||
|
||||
g_usbd_printer.device_id = device_id;
|
||||
g_usbd_printer.device_id_len = device_id_len;
|
||||
return intf;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_PRINTER_H
|
||||
#define USBD_PRINTER_H
|
||||
|
||||
#include "usb_printer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init printer interface driver */
|
||||
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_PRINTER_H */
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_printer.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/printer"
|
||||
|
||||
static struct usbh_printer g_printer_class[CONFIG_USBHOST_MAX_PRINTER_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_printer *usbh_printer_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_PRINTER_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_printer_class[devno], 0, sizeof(struct usbh_printer));
|
||||
g_printer_class[devno].minor = devno;
|
||||
return &g_printer_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_printer_class_free(struct usbh_printer *printer_class)
|
||||
{
|
||||
int devno = printer_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||
}
|
||||
|
||||
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_GET_DEVICE_ID;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 256;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||
}
|
||||
|
||||
static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_GET_PORT_SATTUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||
}
|
||||
|
||||
static int usbh_printer_soft_reset(struct usbh_printer *printer_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = &printer_class->hport->setup;
|
||||
int ret;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = PRINTER_REQUEST_SOFT_RESET;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = printer_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(printer_class->hport->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_printer *printer_class = usbh_printer_class_alloc();
|
||||
if (printer_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc printer_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
printer_class->hport = hport;
|
||||
printer_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = printer_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&printer_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&printer_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
// uint8_t *device_id = usb_iomalloc(256);
|
||||
// ret = usbh_printer_get_device_id(printer_class, device_id);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_printer *printer_class = (struct usbh_printer *)hport->config.intf[intf].priv;
|
||||
|
||||
if (printer_class) {
|
||||
if (printer_class->bulkin) {
|
||||
usbh_pipe_free(printer_class->bulkin);
|
||||
}
|
||||
|
||||
if (printer_class->bulkout) {
|
||||
usbh_pipe_free(printer_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
|
||||
usbh_printer_class_free(printer_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver printer_class_driver = {
|
||||
.driver_name = "printer",
|
||||
.connect = usbh_printer_connect,
|
||||
.disconnect = usbh_printer_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info printer_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_PRINTER,
|
||||
.subclass = PRINTER_SUBCLASS,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &printer_class_driver
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_PRINTER_H
|
||||
#define USBH_PRINTER_H
|
||||
|
||||
#include "usb_printer.h"
|
||||
|
||||
struct usbh_printer {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* BULK IN endpoint */
|
||||
usbh_pipe_t bulkout; /* BULK OUT endpoint */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_PRINTER_H */
|
||||
@@ -28,12 +28,12 @@ static void xxx_notify_handler(uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf)
|
||||
{
|
||||
intf->class_interface_handler = xxx_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = xxx_notify_handler;
|
||||
|
||||
usbd_class_add_interface(devclass, intf);
|
||||
return intf;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||
struct usbd_interface *usbd_xxx_init_intf(struct usbd_interface *intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/xxx"
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CUSTOM_CLASS 1
|
||||
static struct usbh_xxx g_xxx_class[CONFIG_USBHOST_MAX_CUSTOM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
@@ -33,14 +34,13 @@ static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
|
||||
|
||||
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
|
||||
if (xxx_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -54,12 +54,12 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;
|
||||
|
||||
if (xxx_class) {
|
||||
if (xxx_class->bulkin) {
|
||||
usbh_pipe_free(xxx_class->bulkin);
|
||||
if (xxx_class->xxxin) {
|
||||
usbh_kill_urb(&xxx_class->xxxin_urb);
|
||||
}
|
||||
|
||||
if (xxx_class->bulkout) {
|
||||
usbh_pipe_free(xxx_class->bulkout);
|
||||
if (xxx_class->xxxout) {
|
||||
usbh_kill_urb(&xxx_class->xxxout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
|
||||
@@ -5,11 +5,16 @@
|
||||
|
||||
struct usbh_xxx {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *xxxin;
|
||||
struct usb_endpoint_descriptor *xxxout;
|
||||
struct usbh_urb xxxin_urb;
|
||||
struct usbh_urb xxxout_urb;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* bulk OUT endpoint */
|
||||
};
|
||||
|
||||
void usbh_xxx_run(struct usbh_xxx *xxx_class);
|
||||
void usbh_xxx_stop(struct usbh_xxx *xxx_class);
|
||||
|
||||
#endif
|
||||
125
class/vendor/air72x/usbh_air724.c
vendored
125
class/vendor/air72x/usbh_air724.c
vendored
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/air724"
|
||||
|
||||
struct usbh_cdc_custom_air724 {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
};
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_air724_buf[32];
|
||||
|
||||
static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_custom_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int usbh_air724_bulk_in_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &cdc_custom_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
|
||||
/* interface 3 is AT command */
|
||||
if (intf != 3) {
|
||||
USB_LOG_WRN("ignore intf:%d\r\n", intf);
|
||||
return 0;
|
||||
}
|
||||
struct usbh_cdc_custom_air724 *cdc_custom_class = usb_malloc(sizeof(struct usbh_cdc_custom_air724));
|
||||
if (cdc_custom_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc cdc_custom_class\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(cdc_custom_class, 0, sizeof(struct usbh_cdc_custom_air724));
|
||||
cdc_custom_class->hport = hport;
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
hport->config.intf[intf].priv = cdc_custom_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&cdc_custom_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&cdc_custom_class->bulkout, hport, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
const uint8_t AT[4] = { 0x41, 0x54, 0x0d, 0x0a };
|
||||
|
||||
memcpy(g_air724_buf, AT, 4);
|
||||
ret = usbh_air724_bulk_out_transfer(cdc_custom_class, g_air724_buf, 4, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", ret);
|
||||
}
|
||||
ret = usbh_air724_bulk_in_transfer(cdc_custom_class, g_air724_buf, 10, 3000);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||
for (size_t i = 0; i < ret; i++) {
|
||||
USB_LOG_RAW("0x%02x ", g_air724_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_air724_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_custom_class_driver = {
|
||||
.driver_name = "cdc_acm",
|
||||
.connect = usbh_air724_connect,
|
||||
.disconnect = usbh_air724_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = 0xff,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x1782,
|
||||
.pid = 0x4e00,
|
||||
.class_driver = &cdc_custom_class_driver
|
||||
};
|
||||
596
class/vendor/asix/asix.h
vendored
596
class/vendor/asix/asix.h
vendored
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Change Logs
|
||||
* Date Author Notes
|
||||
* 2022-04-17 aozima the first version for CherryUSB.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USBNET_ASIX_H
|
||||
#define __LINUX_USBNET_ASIX_H
|
||||
|
||||
// #define __BIG_ENDIAN_BITFIELD
|
||||
#define __LITTLE_ENDIAN_BITFIELD
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
||||
#define KERNEL_VERSION(...) (0)
|
||||
#define LINUX_VERSION_CODE (1)
|
||||
|
||||
/*
|
||||
* Turn on this flag if the implementation of your USB host controller
|
||||
* cannot handle non-double word aligned buffer.
|
||||
* When turn on this flag, driver will fixup egress packet aligned on double
|
||||
* word boundary before deliver to USB host controller. And will Disable the
|
||||
* function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
|
||||
* double word alignment for ingress packets.
|
||||
*/
|
||||
#define AX_FORCE_BUFF_ALIGN 0
|
||||
|
||||
//#define RX_SKB_COPY
|
||||
|
||||
#define AX_MONITOR_MODE 0x01
|
||||
#define AX_MONITOR_LINK 0x02
|
||||
#define AX_MONITOR_MAGIC 0x04
|
||||
#define AX_MONITOR_HSFS 0x10
|
||||
|
||||
/* AX88172 Medium Status Register values */
|
||||
#define AX_MEDIUM_FULL_DUPLEX 0x02
|
||||
#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
|
||||
#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
|
||||
#define AX_MCAST_FILTER_SIZE 8
|
||||
#define AX_MAX_MCAST 64
|
||||
|
||||
#define AX_EEPROM_LEN 0x40
|
||||
|
||||
#define AX_SWRESET_CLEAR 0x00
|
||||
#define AX_SWRESET_RR 0x01
|
||||
#define AX_SWRESET_RT 0x02
|
||||
#define AX_SWRESET_PRTE 0x04
|
||||
#define AX_SWRESET_PRL 0x08
|
||||
#define AX_SWRESET_BZ 0x10
|
||||
#define AX_SWRESET_IPRL 0x20
|
||||
#define AX_SWRESET_IPPD 0x40
|
||||
#define AX_SWRESET_IPOSC 0x0080
|
||||
#define AX_SWRESET_IPPSL_0 0x0100
|
||||
#define AX_SWRESET_IPPSL_1 0x0200
|
||||
#define AX_SWRESET_IPCOPS 0x0400
|
||||
#define AX_SWRESET_IPCOPSC 0x0800
|
||||
#define AX_SWRESET_AUTODETACH 0x1000
|
||||
#define AX_SWRESET_WOLLP 0x8000
|
||||
|
||||
#define AX88772_IPG0_DEFAULT 0x15
|
||||
#define AX88772_IPG1_DEFAULT 0x0c
|
||||
#define AX88772_IPG2_DEFAULT 0x0E
|
||||
|
||||
#define AX88772A_IPG0_DEFAULT 0x15
|
||||
#define AX88772A_IPG1_DEFAULT 0x16
|
||||
#define AX88772A_IPG2_DEFAULT 0x1A
|
||||
|
||||
#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
|
||||
#define AX88772_MEDIUM_RESERVED 0x0004
|
||||
#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
|
||||
#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
|
||||
#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
|
||||
#define AX88772_MEDIUM_RX_ENABLE 0x0100
|
||||
#define AX88772_MEDIUM_100MB 0x0200
|
||||
#define AX88772_MEDIUM_DEFAULT \
|
||||
(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
|
||||
AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
|
||||
AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
|
||||
|
||||
#define AX_CMD_SET_SW_MII 0x06
|
||||
#define AX_CMD_READ_MII_REG 0x07
|
||||
#define AX_CMD_WRITE_MII_REG 0x08
|
||||
#define AX_CMD_READ_STATMNGSTS_REG 0x09
|
||||
#define AX_HOST_EN 0x01
|
||||
|
||||
#define AX_CMD_SET_HW_MII 0x0a
|
||||
#define AX_CMD_READ_EEPROM 0x0b
|
||||
#define AX_CMD_WRITE_EEPROM 0x0c
|
||||
#define AX_CMD_WRITE_EEPROM_EN 0x0d
|
||||
#define AX_CMD_WRITE_EEPROM_DIS 0x0e
|
||||
#define AX_CMD_WRITE_RX_CTL 0x10
|
||||
#define AX_CMD_READ_IPG012 0x11
|
||||
#define AX_CMD_WRITE_IPG0 0x12
|
||||
#define AX_CMD_WRITE_IPG1 0x13
|
||||
#define AX_CMD_WRITE_IPG2 0x14
|
||||
#define AX_CMD_WRITE_MULTI_FILTER 0x16
|
||||
#define AX_CMD_READ_NODE_ID 0x17
|
||||
#define AX_CMD_READ_PHY_ID 0x19
|
||||
#define AX_CMD_READ_MEDIUM_MODE 0x1a
|
||||
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
|
||||
#define AX_CMD_READ_MONITOR_MODE 0x1c
|
||||
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
|
||||
#define AX_CMD_WRITE_GPIOS 0x1f
|
||||
#define AX_CMD_SW_RESET 0x20
|
||||
#define AX_CMD_SW_PHY_STATUS 0x21
|
||||
#define AX_CMD_SW_PHY_SELECT 0x22
|
||||
#define AX_PHYSEL_PSEL (1 << 0)
|
||||
#define AX_PHYSEL_ASEL (1 << 1)
|
||||
#define AX_PHYSEL_SSMII (0 << 2)
|
||||
#define AX_PHYSEL_SSRMII (1 << 2)
|
||||
#define AX_PHYSEL_SSRRMII (3 << 2)
|
||||
#define AX_PHYSEL_SSEN (1 << 4)
|
||||
#define AX88772_CMD_READ_NODE_ID 0x13
|
||||
#define AX88772_CMD_WRITE_NODE_ID 0x14
|
||||
#define AX_CMD_READ_WKFARY 0x23
|
||||
#define AX_CMD_WRITE_WKFARY 0x24
|
||||
#define AX_CMD_READ_RXCOE_CTL 0x2b
|
||||
#define AX_CMD_WRITE_RXCOE_CTL 0x2c
|
||||
#define AX_CMD_READ_TXCOE_CTL 0x2d
|
||||
#define AX_CMD_WRITE_TXCOE_CTL 0x2e
|
||||
|
||||
#define REG_LENGTH 2
|
||||
#define PHY_ID_MASK 0x1f
|
||||
|
||||
#define AX_RXCOE_IPCE 0x0001
|
||||
#define AX_RXCOE_IPVE 0x0002
|
||||
#define AX_RXCOE_V6VE 0x0004
|
||||
#define AX_RXCOE_TCPE 0x0008
|
||||
#define AX_RXCOE_UDPE 0x0010
|
||||
#define AX_RXCOE_ICMP 0x0020
|
||||
#define AX_RXCOE_IGMP 0x0040
|
||||
#define AX_RXCOE_ICV6 0x0080
|
||||
#define AX_RXCOE_TCPV6 0x0100
|
||||
#define AX_RXCOE_UDPV6 0x0200
|
||||
#define AX_RXCOE_ICMV6 0x0400
|
||||
#define AX_RXCOE_IGMV6 0x0800
|
||||
#define AX_RXCOE_ICV6V6 0x1000
|
||||
#define AX_RXCOE_FOPC 0x8000
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||
AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
|
||||
AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
|
||||
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
|
||||
#else
|
||||
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||
AX_RXCOE_TCPE | AX_RXCOE_UDPE)
|
||||
#endif
|
||||
|
||||
#define AX_RXCOE_64TE 0x0100
|
||||
#define AX_RXCOE_PPPOE 0x0200
|
||||
#define AX_RXCOE_RPCE 0x8000
|
||||
|
||||
#define AX_TXCOE_IP 0x0001
|
||||
#define AX_TXCOE_TCP 0x0002
|
||||
#define AX_TXCOE_UDP 0x0004
|
||||
#define AX_TXCOE_ICMP 0x0008
|
||||
#define AX_TXCOE_IGMP 0x0010
|
||||
#define AX_TXCOE_ICV6 0x0020
|
||||
|
||||
#define AX_TXCOE_TCPV6 0x0100
|
||||
#define AX_TXCOE_UDPV6 0x0200
|
||||
#define AX_TXCOE_ICMV6 0x0400
|
||||
#define AX_TXCOE_IGMV6 0x0800
|
||||
#define AX_TXCOE_ICV6V6 0x1000
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
|
||||
AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
|
||||
#else
|
||||
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
|
||||
#endif
|
||||
|
||||
#define AX_TXCOE_64TE 0x0001
|
||||
#define AX_TXCOE_PPPE 0x0002
|
||||
|
||||
#define AX88772B_MAX_BULKIN_2K 0
|
||||
#define AX88772B_MAX_BULKIN_4K 1
|
||||
#define AX88772B_MAX_BULKIN_6K 2
|
||||
#define AX88772B_MAX_BULKIN_8K 3
|
||||
#define AX88772B_MAX_BULKIN_16K 4
|
||||
#define AX88772B_MAX_BULKIN_20K 5
|
||||
#define AX88772B_MAX_BULKIN_24K 6
|
||||
#define AX88772B_MAX_BULKIN_32K 7
|
||||
struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
|
||||
/* 2k */
|
||||
{2048, 0x8000, 0x8001},
|
||||
/* 4k */
|
||||
{4096, 0x8100, 0x8147},
|
||||
/* 6k */
|
||||
{6144, 0x8200, 0x81EB},
|
||||
/* 8k */
|
||||
{8192, 0x8300, 0x83D7},
|
||||
/* 16 */
|
||||
{16384, 0x8400, 0x851E},
|
||||
/* 20k */
|
||||
{20480, 0x8500, 0x8666},
|
||||
/* 24k */
|
||||
{24576, 0x8600, 0x87AE},
|
||||
/* 32k */
|
||||
{32768, 0x8700, 0x8A3D},
|
||||
};
|
||||
|
||||
|
||||
#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
|
||||
#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
|
||||
#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
|
||||
#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
|
||||
|
||||
#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
|
||||
#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
|
||||
#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
|
||||
#define AX_RX_CTL_AM 0x0010
|
||||
#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
|
||||
#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
|
||||
#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
|
||||
#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
|
||||
#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
|
||||
|
||||
#define AX_MONITOR_MODE 0x01
|
||||
#define AX_MONITOR_LINK 0x02
|
||||
#define AX_MONITOR_MAGIC 0x04
|
||||
#define AX_MONITOR_HSFS 0x10
|
||||
|
||||
#define AX_MCAST_FILTER_SIZE 8
|
||||
#define AX_MAX_MCAST 64
|
||||
#define AX_INTERRUPT_BUFSIZE 8
|
||||
|
||||
#define AX_EEPROM_LEN 0x40
|
||||
#define AX_EEPROM_MAGIC 0xdeadbeef
|
||||
#define EEPROMMASK 0x7f
|
||||
|
||||
/* GPIO REGISTER */
|
||||
#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
|
||||
#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
|
||||
#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
|
||||
#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
|
||||
#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
|
||||
#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
|
||||
#define AXGPIOS_RSE 0X80 /* 1 << 7 */
|
||||
|
||||
/* TX-header format */
|
||||
#define AX_TX_HDR_CPHI 0x4000
|
||||
#define AX_TX_HDR_DICF 0x8000
|
||||
|
||||
/* GMII register definitions */
|
||||
#define GMII_PHY_CONTROL 0x00 /* control reg */
|
||||
#define GMII_PHY_STATUS 0x01 /* status reg */
|
||||
#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
|
||||
#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
|
||||
#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
|
||||
#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
|
||||
#define GMII_PHY_ANER 0x06 /* AN expansion reg */
|
||||
#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
|
||||
#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
|
||||
|
||||
/* Bit definitions: GMII Control */
|
||||
#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
|
||||
#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
|
||||
#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
|
||||
#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
|
||||
#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
|
||||
#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
|
||||
#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
|
||||
#define GMII_CONTROL_POWER_DOWN 0x0800
|
||||
#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
|
||||
#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
|
||||
#define GMII_CONTROL_FULL_DUPLEX 0x0100
|
||||
|
||||
/* Bit definitions: GMII Status */
|
||||
#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
|
||||
#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
|
||||
#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
|
||||
#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
|
||||
#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
|
||||
#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
|
||||
#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
|
||||
#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
|
||||
#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
|
||||
#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
|
||||
#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
|
||||
|
||||
/* Bit definitions: Auto-Negotiation Advertisement */
|
||||
#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||
#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
|
||||
#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
|
||||
#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||
#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||
#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||
#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
|
||||
#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
|
||||
|
||||
/* Bit definitions: Auto-Negotiation Link Partner Ability */
|
||||
#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
|
||||
#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||
#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||
#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||
#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
|
||||
#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
|
||||
#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||
#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
|
||||
#define GMII_SELECTOR_8023 0x0001;
|
||||
|
||||
/* Bit definitions: 1000BaseT AUX Control */
|
||||
#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
|
||||
#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
|
||||
#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
|
||||
|
||||
/* Bit definitions: 1000BaseT AUX Status */
|
||||
#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
|
||||
#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
|
||||
|
||||
/* Cicada MII Registers */
|
||||
#define GMII_AUX_CTRL_STATUS 0x1C
|
||||
#define GMII_AUX_ANEG_CPLT 0x8000
|
||||
#define GMII_AUX_FDX 0x0020
|
||||
#define GMII_AUX_SPEED_1000 0x0010
|
||||
#define GMII_AUX_SPEED_100 0x0008
|
||||
|
||||
#ifndef ADVERTISE_PAUSE_CAP
|
||||
#define ADVERTISE_PAUSE_CAP 0x0400
|
||||
#endif
|
||||
|
||||
#ifndef MII_STAT1000
|
||||
#define MII_STAT1000 0x000A
|
||||
#endif
|
||||
|
||||
#ifndef LPA_1000FULL
|
||||
#define LPA_1000FULL 0x0800
|
||||
#endif
|
||||
|
||||
/* medium mode register */
|
||||
#define MEDIUM_GIGA_MODE 0x0001
|
||||
#define MEDIUM_FULL_DUPLEX_MODE 0x0002
|
||||
#define MEDIUM_TX_ABORT_MODE 0x0004
|
||||
#define MEDIUM_ENABLE_125MHZ 0x0008
|
||||
#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
|
||||
#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
|
||||
#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
|
||||
#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
|
||||
#define MEDIUM_ENABLE_RECEIVE 0x0100
|
||||
#define MEDIUM_MII_100M_MODE 0x0200
|
||||
#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
|
||||
#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
|
||||
#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
|
||||
|
||||
/* PHY mode */
|
||||
#define PHY_MODE_MARVELL 0
|
||||
#define PHY_MODE_CICADA_FAMILY 1
|
||||
#define PHY_MODE_CICADA_V1 1
|
||||
#define PHY_MODE_AGERE_FAMILY 2
|
||||
#define PHY_MODE_AGERE_V0 2
|
||||
#define PHY_MODE_CICADA_V2 5
|
||||
#define PHY_MODE_AGERE_V0_GMII 6
|
||||
#define PHY_MODE_CICADA_V2_ASIX 9
|
||||
#define PHY_MODE_VSC8601 10
|
||||
#define PHY_MODE_RTL8211CL 12
|
||||
#define PHY_MODE_RTL8211BN 13
|
||||
#define PHY_MODE_RTL8251CL 14
|
||||
#define PHY_MODE_ATTANSIC_V0 0x40
|
||||
#define PHY_MODE_ATTANSIC_FAMILY 0x40
|
||||
#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
|
||||
|
||||
/* */
|
||||
#define LED_MODE_MARVELL 0
|
||||
#define LED_MODE_CAMEO 1
|
||||
|
||||
#define MARVELL_LED_CTRL 0x18
|
||||
#define MARVELL_MANUAL_LED 0x19
|
||||
|
||||
#define PHY_IDENTIFIER 0x0002
|
||||
#define PHY_AGERE_IDENTIFIER 0x0282
|
||||
#define PHY_CICADA_IDENTIFIER 0x000f
|
||||
#define PHY_MARVELL_IDENTIFIER 0x0141
|
||||
|
||||
#define PHY_MARVELL_STATUS 0x001b
|
||||
#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
|
||||
|
||||
#define PHY_MARVELL_CTRL 0x0014
|
||||
#define MARVELL_CTRL_RXDELAY 0x0080
|
||||
#define MARVELL_CTRL_TXDELAY 0x0002
|
||||
|
||||
#define PHY_CICADA_EXTPAGE 0x001f
|
||||
#define CICADA_EXTPAGE_EN 0x0001
|
||||
#define CICADA_EXTPAGE_DIS 0x0000
|
||||
|
||||
/* External ethernet phy */
|
||||
#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
|
||||
#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
|
||||
|
||||
#define EXTPHY_BROADCOM_OUI 0x2B8094
|
||||
#define EXTPHY_BCM89811_MODEL 0x02
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
|
||||
{0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
|
||||
{0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
|
||||
{0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
|
||||
{0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
|
||||
{0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
|
||||
{0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
|
||||
{0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
|
||||
{0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||
{0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
|
||||
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
|
||||
{0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||
{0x0000, 0x001f},
|
||||
};
|
||||
|
||||
struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
|
||||
{0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
|
||||
{0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
|
||||
{0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
|
||||
{0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
|
||||
{0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
|
||||
{0x0002, 0x0012},
|
||||
};
|
||||
|
||||
struct ax88178_data {
|
||||
u16 EepromData;
|
||||
u16 MediaLink;
|
||||
int UseGpio0;
|
||||
int UseRgmii;
|
||||
u8 PhyMode;
|
||||
u8 LedMode;
|
||||
u8 BuffaloOld;
|
||||
};
|
||||
|
||||
enum watchdog_state {
|
||||
AX_NOP = 0,
|
||||
CHK_LINK, /* Routine A */
|
||||
CHK_CABLE_EXIST, /* Called by A */
|
||||
CHK_CABLE_EXIST_AGAIN, /* Routine B */
|
||||
PHY_POWER_UP, /* Called by B */
|
||||
PHY_POWER_UP_BH,
|
||||
PHY_POWER_DOWN,
|
||||
CHK_CABLE_STATUS, /* Routine C */
|
||||
WAIT_AUTONEG_COMPLETE,
|
||||
AX_SET_RX_CFG,
|
||||
AX_CHK_AUTODETACH,
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct ax88772b_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long time_to_chk;
|
||||
u16 psc;
|
||||
u8 pw_enabled;
|
||||
u8 Event;
|
||||
u8 checksum;
|
||||
u8 PhySelect:1;
|
||||
u8 OperationMode:1;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
|
||||
u32 ext_phy_oui;
|
||||
u8 ext_phy_model;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* define for MAC or PHY mode */
|
||||
#define OPERATION_MAC_MODE 0
|
||||
#define OPERATION_PHY_MODE 1
|
||||
|
||||
#if 0
|
||||
struct ax88772a_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long autoneg_start;
|
||||
#define AX88772B_WATCHDOG (6 * HZ)
|
||||
u8 Event;
|
||||
u8 TickToExpire;
|
||||
u8 DlyIndex;
|
||||
u8 DlySel;
|
||||
u16 EepromData;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
};
|
||||
|
||||
struct ax88772_data {
|
||||
struct usbnet *dev;
|
||||
struct workqueue_struct *ax_work;
|
||||
struct work_struct check_link;
|
||||
unsigned long autoneg_start;
|
||||
u8 Event;
|
||||
u8 TickToExpire;
|
||||
u16 presvd_phy_advertise;
|
||||
u16 presvd_phy_bmcr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define AX_RX_CHECKSUM 1
|
||||
#define AX_TX_CHECKSUM 2
|
||||
|
||||
#if 0
|
||||
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
|
||||
struct ax8817x_data {
|
||||
u8 multi_filter[AX_MCAST_FILTER_SIZE];
|
||||
int (*resume) (struct usb_interface *intf);
|
||||
int (*suspend) (struct usb_interface *intf,
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
|
||||
pm_message_t message);
|
||||
#else
|
||||
u32 message);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ax88172_int_data {
|
||||
u16 res1;
|
||||
#define AX_INT_PPLS_LINK (1 << 0)
|
||||
#define AX_INT_SPLS_LINK (1 << 1)
|
||||
#define AX_INT_CABOFF_UNPLUG (1 << 7)
|
||||
u8 link;
|
||||
u16 res2;
|
||||
u8 status;
|
||||
u16 res3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define AX_RXHDR_L4_ERR (1 << 8)
|
||||
#define AX_RXHDR_L3_ERR (1 << 9)
|
||||
|
||||
#define AX_RXHDR_L4_TYPE_UDP 1
|
||||
#define AX_RXHDR_L4_TYPE_ICMP 2
|
||||
#define AX_RXHDR_L4_TYPE_IGMP 3
|
||||
#define AX_RXHDR_L4_TYPE_TCP 4
|
||||
#define AX_RXHDR_L4_TYPE_TCMPV6 5
|
||||
#define AX_RXHDR_L4_TYPE_MASK 7
|
||||
|
||||
#define AX_RXHDR_L3_TYPE_IP 1
|
||||
#define AX_RXHDR_L3_TYPE_IPV6 2
|
||||
|
||||
struct ax88772b_rx_header {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
u16 len:11,
|
||||
res1:1,
|
||||
crc:1,
|
||||
mii:1,
|
||||
runt:1,
|
||||
mc_bc:1;
|
||||
|
||||
u16 len_bar:11,
|
||||
res2:5;
|
||||
|
||||
u8 vlan_ind:3,
|
||||
vlan_tag_striped:1,
|
||||
pri:3,
|
||||
res3:1;
|
||||
|
||||
u8 l4_csum_err:1,
|
||||
l3_csum_err:1,
|
||||
l4_type:3,
|
||||
l3_type:2,
|
||||
ce:1;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
u16 mc_bc:1,
|
||||
runt:1,
|
||||
mii:1,
|
||||
crc:1,
|
||||
res1:1,
|
||||
len:11;
|
||||
|
||||
u16 res2:5,
|
||||
len_bar:11;
|
||||
|
||||
u8 res3:1,
|
||||
pri:3,
|
||||
vlan_tag_striped:1,
|
||||
vlan_ind:3;
|
||||
|
||||
u8 ce:1,
|
||||
l3_type:2,
|
||||
l4_type:3,
|
||||
l3_csum_err:1,
|
||||
l4_csum_err:1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#endif /* __LINUX_USBNET_ASIX_H */
|
||||
|
||||
1208
class/vendor/asix/axusbnet.c
vendored
1208
class/vendor/asix/axusbnet.c
vendored
File diff suppressed because it is too large
Load Diff
30
class/vendor/asix/axusbnet.h
vendored
30
class/vendor/asix/axusbnet.h
vendored
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, aozima
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
* Change Logs
|
||||
* Date Author Notes
|
||||
* 2022-04-17 aozima the first version for CherryUSB.
|
||||
*/
|
||||
|
||||
#ifndef __USB_CLASHH_AXUSBNET_H__
|
||||
#define __USB_CLASHH_AXUSBNET_H__
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "asix.h"
|
||||
|
||||
struct usbh_axusbnet {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
|
||||
usbh_pipe_t int_notify; /* Notify endpoint */
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
uint32_t bulkin_buf[2048/sizeof(uint32_t)];
|
||||
};
|
||||
|
||||
#endif /* __USB_CLASHH_AXUSBNET_H__ */
|
||||
1763
class/vendor/cp201x/usbh_cp210x.c
vendored
1763
class/vendor/cp201x/usbh_cp210x.c
vendored
File diff suppressed because it is too large
Load Diff
99
class/vendor/cp201x/usbh_cp210x.h
vendored
99
class/vendor/cp201x/usbh_cp210x.h
vendored
@@ -1,99 +0,0 @@
|
||||
|
||||
#ifndef USBH_CP210X_H
|
||||
#define USBH_CP210X_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "usbh_core.h"
|
||||
|
||||
typedef int32_t speed_t;
|
||||
typedef int32_t tcflag_t;
|
||||
|
||||
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
|
||||
|
||||
struct usb_serial_port{
|
||||
uint8_t partnum;
|
||||
uint8_t ctrlpipe_rx;
|
||||
uint8_t ctrlpipe_tx;
|
||||
int32_t max_speed;
|
||||
speed_t use_actual_rate;
|
||||
uint8_t bInterfaceNumber;
|
||||
int has_swapped_line_ctl;
|
||||
};
|
||||
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
|
||||
#define NCCS 19
|
||||
struct termios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has identical termios and termios2 */
|
||||
|
||||
struct termios2 {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
/* Alpha has matching termios and ktermios */
|
||||
|
||||
struct ktermios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
cc_t c_line; /* line discipline (== c_cc[19]) */
|
||||
speed_t c_ispeed; /* input speed */
|
||||
speed_t c_ospeed; /* output speed */
|
||||
};
|
||||
|
||||
|
||||
struct tty_struct{
|
||||
struct usb_serial_port driver_data;
|
||||
struct termios termios;
|
||||
};
|
||||
|
||||
int cp210x_attach(struct usb_serial_port *port);
|
||||
int cp210x_port_probe(struct usb_serial_port *port);
|
||||
void cp210x_break_ctl(struct tty_struct *tty, int break_state);
|
||||
int cp210x_open(struct tty_struct *tty);
|
||||
int cp210x_tiocmget(struct tty_struct *tty);
|
||||
void cp210x_set_termios(struct tty_struct *tty);
|
||||
void cp210x_change_speed(struct tty_struct *tty);
|
||||
void cp210x_dtr_rts(struct usb_serial_port *port, int on);
|
||||
|
||||
struct usbh_cp210x
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t intf;
|
||||
usbh_pipe_t bulkin;
|
||||
usbh_pipe_t bulkout;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb bulkout_urb;
|
||||
|
||||
struct tty_struct drv_data;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
/* weak defined function */
|
||||
void drv_usbh_cp210x_run(struct usbh_cp210x *p_device);
|
||||
void drv_usbh_cp210x_stop(struct usbh_cp210x *p_device);
|
||||
|
||||
#endif
|
||||
@@ -67,7 +67,7 @@ int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf
|
||||
|
||||
retry = 0;
|
||||
while (1) {
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, g_video_buf);
|
||||
if (ret > 0) {
|
||||
break;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf
|
||||
|
||||
memcpy(g_video_buf, buf, len);
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, g_video_buf);
|
||||
usb_osal_msleep(50);
|
||||
return ret;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
uint8_t step;
|
||||
|
||||
if (video_class->is_opened) {
|
||||
return -EMFILE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
|
||||
@@ -161,11 +161,11 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
return -ENODEV;
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
if (altsetting > (video_class->num_of_intf_altsettings - 1)) {
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
/* Open video step:
|
||||
@@ -233,7 +233,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
@@ -243,10 +243,10 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
video_class->isoin_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&video_class->isoin, video_class->hport, ep_desc);
|
||||
USBH_EP_INIT(video_class->isoin, ep_desc);
|
||||
} else {
|
||||
video_class->isoout_mps = mps * (mult + 1);
|
||||
usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc);
|
||||
USBH_EP_INIT(video_class->isoout, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
|
||||
@@ -269,12 +269,10 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
video_class->is_opened = false;
|
||||
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
video_class->isoin = NULL;
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
video_class->isoout = NULL;
|
||||
}
|
||||
|
||||
@@ -284,7 +282,7 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -350,7 +348,7 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_video *video_class = usbh_video_class_alloc();
|
||||
if (video_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc video_class\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
video_class->hport = hport;
|
||||
@@ -455,11 +453,9 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (video_class) {
|
||||
if (video_class->isoin) {
|
||||
usbh_pipe_free(video_class->isoin);
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
usbh_pipe_free(video_class->isoout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
|
||||
@@ -32,12 +32,12 @@ struct usbh_videostreaming {
|
||||
|
||||
struct usbh_video {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* interface number */
|
||||
uint8_t data_intf; /* interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t isoin; /* ISO IN endpoint */
|
||||
usbh_pipe_t isoout; /* ISO OUT endpoint */
|
||||
struct video_probe_and_commit_controls probe;
|
||||
struct video_probe_and_commit_controls commit;
|
||||
uint16_t isoin_mps;
|
||||
|
||||
@@ -45,8 +45,8 @@ struct usbd_rndis_priv {
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
|
||||
@@ -512,7 +512,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
}
|
||||
|
||||
if (g_rndis_tx_data_length > 0) {
|
||||
return -EBUSY;
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
|
||||
|
||||
@@ -11,8 +11,33 @@
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
|
||||
|
||||
/* eth rx size must be a multiple of 512 or 64 */
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE];
|
||||
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16];
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
// int ret;
|
||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
||||
|
||||
// usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
// ret = usbh_submit_urb(urb);
|
||||
// if (ret == 0) {
|
||||
// ret = urb->actual_length;
|
||||
// }
|
||||
// return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
@@ -35,13 +60,13 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_initialize_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -51,7 +76,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
@@ -83,13 +108,13 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = query_len + sizeof(rndis_query_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_query_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -99,7 +124,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
@@ -135,13 +160,13 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = info_len + sizeof(rndis_set_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_set_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -151,7 +176,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
@@ -160,32 +185,22 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
uint8_t data[32];
|
||||
uint32_t data_len;
|
||||
|
||||
usbh_bulk_urb_fill(urb, rndis_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill(urb, rndis_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
rndis_class->link_status = true;
|
||||
} else {
|
||||
rndis_class->link_status = false;
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
@@ -207,13 +222,13 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_keepalive_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_keepalive_cmplt_t *)g_rndis_buf;
|
||||
|
||||
@@ -223,7 +238,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
@@ -254,17 +269,16 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
hport->config.intf[intf].priv = rndis_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
#ifdef CONFIG_USBHOST_RNDIS_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&rndis_class->intin, hport, ep_desc);
|
||||
#endif
|
||||
// ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
// USBH_EP_INIT(rndis_class->intin, ep_desc);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&rndis_class->bulkin, hport, ep_desc);
|
||||
USBH_EP_INIT(rndis_class->bulkin, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&rndis_class->bulkout, hport, ep_desc);
|
||||
USBH_EP_INIT(rndis_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +374,14 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
|
||||
|
||||
USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
rndis_class->mac[0],
|
||||
rndis_class->mac[1],
|
||||
rndis_class->mac[2],
|
||||
rndis_class->mac[3],
|
||||
rndis_class->mac[4],
|
||||
rndis_class->mac[5]);
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
@@ -378,13 +400,17 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (rndis_class) {
|
||||
if (rndis_class->bulkin) {
|
||||
usbh_pipe_free(rndis_class->bulkin);
|
||||
usbh_kill_urb(&rndis_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (rndis_class->bulkout) {
|
||||
usbh_pipe_free(rndis_class->bulkout);
|
||||
usbh_kill_urb(&rndis_class->bulkout_urb);
|
||||
}
|
||||
|
||||
// if (rndis_class->intin) {
|
||||
// usbh_kill_urb(&rndis_class->intin_urb);
|
||||
// }
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_stop(rndis_class);
|
||||
@@ -396,6 +422,131 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_rndis_rx_thread(void *argument)
|
||||
{
|
||||
uint32_t g_rndis_rx_length;
|
||||
uint32_t pmg_offset;
|
||||
uint32_t payload_offset;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p, *q;
|
||||
rndis_data_packet_t *pmsg;
|
||||
rndis_data_packet_t temp;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
|
||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
g_rndis_class.link_status = false;
|
||||
if (usbh_find_class_instance("/dev/rndis") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_rndis_class.link_status == false) {
|
||||
ret = usbh_rndis_get_connect_status(&g_rndis_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
g_rndis_rx_length = 0;
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_rndis_rx_length = g_rndis_class.bulkin_urb.actual_length;
|
||||
pmg_offset = 0;
|
||||
while (g_rndis_rx_length > 0) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
|
||||
|
||||
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
|
||||
|
||||
/* Not word-aligned case */
|
||||
if (pmg_offset & 0x3) {
|
||||
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
|
||||
pmsg = &temp;
|
||||
}
|
||||
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
payload_offset = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset);
|
||||
memcpy(q->payload, src, q->len);
|
||||
payload_offset += q->len;
|
||||
}
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
pmg_offset += pmsg->MessageLength;
|
||||
g_rndis_rx_length -= pmsg->MessageLength;
|
||||
} else {
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
|
||||
}
|
||||
} else {
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("Error rndis packet message\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete rndis rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (g_rndis_class.link_status == false) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = p->tot_len;
|
||||
|
||||
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
|
||||
if (!(hdr->MessageLength % g_rndis_class.bulkout->wMaxPacketSize)) {
|
||||
hdr->MessageLength += 1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength);
|
||||
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,36 +8,45 @@
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
struct usbh_rndis {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Notify endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
|
||||
uint32_t request_id;
|
||||
|
||||
uint32_t link_speed;
|
||||
bool link_status;
|
||||
uint8_t mac[6];
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class);
|
||||
|
||||
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
void usbh_rndis_rx_thread(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,18 +12,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB Endpoint Configuration.
|
||||
*
|
||||
* Structure containing the USB endpoint configuration.
|
||||
*/
|
||||
struct usbd_endpoint_cfg {
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_mult; /* Endpoint additional transcations in micro frame */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief init device controller registers.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
@@ -61,7 +49,7 @@ uint8_t usbd_get_port_speed(const uint8_t port);
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep);
|
||||
|
||||
/**
|
||||
* @brief Disable the selected endpoint
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_GET_ENDPOINT_TYPE(x) ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT)
|
||||
|
||||
#define USB_ENDPOINT_SYNC_SHIFT 2
|
||||
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
@@ -245,6 +246,8 @@
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_GET_MAXPACKETSIZE(x) ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT)
|
||||
#define USB_GET_MULT(x) ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
|
||||
/* bDevCapabilityType in Device Capability Descriptor */
|
||||
#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
|
||||
|
||||
@@ -1,320 +1,24 @@
|
||||
/*
|
||||
* Apache NuttX
|
||||
* Copyright 2020 The Apache Software Foundation
|
||||
* Copyright (c) 2023, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __INCLUDE_ERRNO_H
|
||||
#define __INCLUDE_ERRNO_H
|
||||
#ifndef USB_ERRNO_H
|
||||
#define USB_ERRNO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
#define USB_ERR_NOMEM 1
|
||||
#define USB_ERR_INVAL 2
|
||||
#define USB_ERR_NODEV 3
|
||||
#define USB_ERR_NOTCONN 4
|
||||
#define USB_ERR_NOTSUPP 5
|
||||
#define USB_ERR_BUSY 6
|
||||
#define USB_ERR_RANGE 7
|
||||
#define USB_ERR_STALL 8
|
||||
#define USB_ERR_BABBLE 9
|
||||
#define USB_ERR_NAK 10
|
||||
#define USB_ERR_DT 11
|
||||
#define USB_ERR_IO 12
|
||||
#define USB_ERR_SHUTDOWN 13
|
||||
#define USB_ERR_TIMEOUT 14
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Convenience/compatibility definition. If the errno is accessed from the
|
||||
* internal OS code, then the OS code should use the set_errno() and
|
||||
* get_errno(). Currently, those are just placeholders but would be needed
|
||||
* in the KERNEL mode build in order to instantiate the process address
|
||||
* environment as necessary to access the TLS-based errno variable.
|
||||
*/
|
||||
|
||||
/* Definitions of error numbers and the string that would be
|
||||
* returned by strerror().
|
||||
*/
|
||||
#ifndef CONFIG_USB_ERROR_USE_SYSTEM
|
||||
|
||||
#define EPERM 1
|
||||
#define EPERM_STR "Operation not permitted"
|
||||
#define ENOENT 2
|
||||
#define ENOENT_STR "No such file or directory"
|
||||
#define ESRCH 3
|
||||
#define ESRCH_STR "No such process"
|
||||
#define EINTR 4
|
||||
#define EINTR_STR "Interrupted system call"
|
||||
#define EIO 5
|
||||
#define EIO_STR "I/O error"
|
||||
#define ENXIO 6
|
||||
#define ENXIO_STR "No such device or address"
|
||||
#define E2BIG 7
|
||||
#define E2BIG_STR "Arg list too long"
|
||||
#define ENOEXEC 8
|
||||
#define ENOEXEC_STR "Exec format error"
|
||||
#define EBADF 9
|
||||
#define EBADF_STR "Bad file number"
|
||||
#define ECHILD 10
|
||||
#define ECHILD_STR "No child processes"
|
||||
#define EAGAIN 11
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
#define EAGAIN_STR "Try again"
|
||||
#define ENOMEM 12
|
||||
#define ENOMEM_STR "Out of memory"
|
||||
#define EACCES 13
|
||||
#define EACCES_STR "Permission denied"
|
||||
#define EFAULT 14 /* Linux errno extension */
|
||||
#define EFAULT_STR "Bad address"
|
||||
#define ENOTBLK 15
|
||||
#define ENOTBLK_STR "Block device required"
|
||||
#define EBUSY 16
|
||||
#define EBUSY_STR "Device or resource busy"
|
||||
#define EEXIST 17
|
||||
#define EEXIST_STR "File exists"
|
||||
#define EXDEV 18
|
||||
#define EXDEV_STR "Cross-device link"
|
||||
#define ENODEV 19
|
||||
#define ENODEV_STR "No such device"
|
||||
#define ENOTDIR 20
|
||||
#define ENOTDIR_STR "Not a directory"
|
||||
#define EISDIR 21
|
||||
#define EISDIR_STR "Is a directory"
|
||||
#define EINVAL 22
|
||||
#define EINVAL_STR "Invalid argument"
|
||||
#define ENFILE 23
|
||||
#define ENFILE_STR "File table overflow"
|
||||
#define EMFILE 24
|
||||
#define EMFILE_STR "Too many open files"
|
||||
#define ENOTTY 25
|
||||
#define ENOTTY_STR "Not a typewriter"
|
||||
#define ETXTBSY 26
|
||||
#define ETXTBSY_STR "Text file busy"
|
||||
#define EFBIG 27
|
||||
#define EFBIG_STR "File too large"
|
||||
#define ENOSPC 28
|
||||
#define ENOSPC_STR "No space left on device"
|
||||
#define ESPIPE 29
|
||||
#define ESPIPE_STR "Illegal seek"
|
||||
#define EROFS 30
|
||||
#define EROFS_STR "Read-only file system"
|
||||
#define EMLINK 31
|
||||
#define EMLINK_STR "Too many links"
|
||||
#define EPIPE 32
|
||||
#define EPIPE_STR "Broken pipe"
|
||||
#define EDOM 33
|
||||
#define EDOM_STR "Math argument out of domain of func"
|
||||
#define ERANGE 34
|
||||
#define ERANGE_STR "Math result not representable"
|
||||
#define ENOMSG 35
|
||||
#define ENOMSG_STR "No message of desired type"
|
||||
#define EIDRM 36
|
||||
#define EIDRM_STR "Identifier removed"
|
||||
#define ECHRNG 37 /* Linux errno extension */
|
||||
#define ECHRNG_STR "Channel number out of range"
|
||||
#define EL2NSYNC 38 /* Linux errno extension */
|
||||
#define EL2NSYNC_STR "Level 2 not synchronized"
|
||||
#define EL3HLT 39 /* Linux errno extension */
|
||||
#define EL3HLT_STR "Level 3 halted"
|
||||
#define EL3RST 40 /* Linux errno extension */
|
||||
#define EL3RST_STR "Level 3 reset"
|
||||
#define ELNRNG 41 /* Linux errno extension */
|
||||
#define ELNRNG_STR "Link number out of range"
|
||||
#define EUNATCH 42 /* Linux errno extension */
|
||||
#define EUNATCH_STR "Protocol driver not attached"
|
||||
#define ENOCSI 43 /* Linux errno extension */
|
||||
#define ENOCSI_STR "No CSI structure available"
|
||||
#define EL2HLT 44 /* Linux errno extension */
|
||||
#define EL2HLT_STR "Level 2 halted"
|
||||
#define EDEADLK 45
|
||||
#define EDEADLK_STR "Resource deadlock would occur"
|
||||
#define ENOLCK 46
|
||||
#define ENOLCK_STR "No record locks available"
|
||||
|
||||
#define EBADE 50 /* Linux errno extension */
|
||||
#define EBADE_STR "Invalid exchange"
|
||||
#define EBADR 51 /* Linux errno extension */
|
||||
#define EBADR_STR "Invalid request descriptor"
|
||||
#define EXFULL 52 /* Linux errno extension */
|
||||
#define EXFULL_STR "Exchange full"
|
||||
#define ENOANO 53 /* Linux errno extension */
|
||||
#define ENOANO_STR "No anode"
|
||||
#define EBADRQC 54 /* Linux errno extension */
|
||||
#define EBADRQC_STR "Invalid request code"
|
||||
#define EBADSLT 55 /* Linux errno extension */
|
||||
#define EBADSLT_STR "Invalid slot"
|
||||
#define EDEADLOCK 56 /* Linux errno extension */
|
||||
#define EDEADLOCK_STR "File locking deadlock error"
|
||||
#define EBFONT 57 /* Linux errno extension */
|
||||
#define EBFONT_STR "Bad font file format"
|
||||
|
||||
#define ENOSTR 60
|
||||
#define ENOSTR_STR "Device not a stream"
|
||||
#define ENODATA 61
|
||||
#define ENODATA_STR "No data available"
|
||||
#define ETIME 62
|
||||
#define ETIME_STR "Timer expired"
|
||||
#define ENOSR 63
|
||||
#define ENOSR_STR "Out of streams resources"
|
||||
#define ENONET 64 /* Linux errno extension */
|
||||
#define ENONET_STR "Machine is not on the network"
|
||||
#define ENOPKG 65 /* Linux errno extension */
|
||||
#define ENOPKG_STR "Package not installed"
|
||||
#define EREMOTE 66 /* Linux errno extension */
|
||||
#define EREMOTE_STR "Object is remote"
|
||||
#define ENOLINK 67
|
||||
#define ENOLINK_STR "Link has been severed"
|
||||
#define EADV 68 /* Linux errno extension */
|
||||
#define EADV_STR "Advertise error"
|
||||
#define ESRMNT 69 /* Linux errno extension */
|
||||
#define ESRMNT_STR "Srmount error"
|
||||
#define ECOMM 70 /* Linux errno extension */
|
||||
#define ECOMM_STR "Communication error on send"
|
||||
#define EPROTO 71
|
||||
#define EPROTO_STR "Protocol error"
|
||||
|
||||
#define EMULTIHOP 74
|
||||
#define EMULTIHOP_STR "Multihop attempted"
|
||||
#define ELBIN 75 /* Linux errno extension */
|
||||
#define ELBIN_STR "Inode is remote"
|
||||
#define EDOTDOT 76 /* Linux errno extension */
|
||||
#define EDOTDOT_STR "RFS specific error"
|
||||
#define EBADMSG 77
|
||||
#define EBADMSG_STR "Not a data message"
|
||||
|
||||
#define EFTYPE 79
|
||||
#define EFTYPE_STR "Inappropriate file type or format"
|
||||
#define ENOTUNIQ 80 /* Linux errno extension */
|
||||
#define ENOTUNIQ_STR "Name not unique on network"
|
||||
#define EBADFD 81 /* Linux errno extension */
|
||||
#define EBADFD_STR "File descriptor in bad state"
|
||||
#define EREMCHG 82 /* Linux errno extension */
|
||||
#define EREMCHG_STR "Remote address changed"
|
||||
#define ELIBACC 83 /* Linux errno extension */
|
||||
#define ELIBACC_STR "Can not access a needed shared library"
|
||||
#define ELIBBAD 84 /* Linux errno extension */
|
||||
#define ELIBBAD_STR "Accessing a corrupted shared library"
|
||||
#define ELIBSCN 85 /* Linux errno extension */
|
||||
#define ELIBSCN_STR ".lib section in a.out corrupted"
|
||||
#define ELIBMAX 86 /* Linux errno extension */
|
||||
#define ELIBMAX_STR "Attempting to link in too many shared libraries"
|
||||
#define ELIBEXEC 87 /* Linux errno extension */
|
||||
#define ELIBEXEC_STR "Cannot exec a shared library directly"
|
||||
#define ENOSYS 88
|
||||
#define ENOSYS_STR "Function not implemented"
|
||||
#define ENMFILE 89 /* Cygwin */
|
||||
#define ENMFILE_STR "No more files"
|
||||
#define ENOTEMPTY 90
|
||||
#define ENOTEMPTY_STR "Directory not empty"
|
||||
#define ENAMETOOLONG 91
|
||||
#define ENAMETOOLONG_STR "File name too long"
|
||||
#define ELOOP 92
|
||||
#define ELOOP_STR "Too many symbolic links encountered"
|
||||
|
||||
#define EOPNOTSUPP 95
|
||||
#define EOPNOTSUPP_STR "Operation not supported on transport endpoint"
|
||||
#define EPFNOSUPPORT 96
|
||||
#define EPFNOSUPPORT_STR "Protocol family not supported"
|
||||
|
||||
#define ECONNRESET 104
|
||||
#define ECONNRESET_STR "Connection reset by peer"
|
||||
#define ENOBUFS 105
|
||||
#define ENOBUFS_STR "No buffer space available"
|
||||
#define EAFNOSUPPORT 106
|
||||
#define EAFNOSUPPORT_STR "Address family not supported by protocol"
|
||||
#define EPROTOTYPE 107
|
||||
#define EPROTOTYPE_STR "Protocol wrong type for socket"
|
||||
#define ENOTSOCK 108
|
||||
#define ENOTSOCK_STR "Socket operation on non-socket"
|
||||
#define ENOPROTOOPT 109
|
||||
#define ENOPROTOOPT_STR "Protocol not available"
|
||||
#define ESHUTDOWN 110 /* Linux errno extension */
|
||||
#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown"
|
||||
#define ECONNREFUSED 111
|
||||
#define ECONNREFUSED_STR "Connection refused"
|
||||
#define EADDRINUSE 112
|
||||
#define EADDRINUSE_STR "Address already in use"
|
||||
#define ECONNABORTED 113
|
||||
#define ECONNABORTED_STR "Software caused connection abort"
|
||||
#define ENETUNREACH 114
|
||||
#define ENETUNREACH_STR "Network is unreachable"
|
||||
#define ENETDOWN 115
|
||||
#define ENETDOWN_STR "Network is down"
|
||||
#define ETIMEDOUT 116
|
||||
#define ETIMEDOUT_STR "Connection timed out"
|
||||
#define EHOSTDOWN 117
|
||||
#define EHOSTDOWN_STR "Host is down"
|
||||
#define EHOSTUNREACH 118
|
||||
#define EHOSTUNREACH_STR "No route to host"
|
||||
#define EINPROGRESS 119
|
||||
#define EINPROGRESS_STR "Operation now in progress"
|
||||
#define EALREADY 120
|
||||
#define EALREADY_STR "Socket already connected"
|
||||
#define EDESTADDRREQ 121
|
||||
#define EDESTADDRREQ_STR "Destination address required"
|
||||
#define EMSGSIZE 122
|
||||
#define EMSGSIZE_STR "Message too long"
|
||||
#define EPROTONOSUPPORT 123
|
||||
#define EPROTONOSUPPORT_STR "Protocol not supported"
|
||||
#define ESOCKTNOSUPPORT 124 /* Linux errno extension */
|
||||
#define ESOCKTNOSUPPORT_STR "Socket type not supported"
|
||||
#define EADDRNOTAVAIL 125
|
||||
#define EADDRNOTAVAIL_STR "Cannot assign requested address"
|
||||
#define ENETRESET 126
|
||||
#define ENETRESET_STR "Network dropped connection because of reset"
|
||||
#define EISCONN 127
|
||||
#define EISCONN_STR "Transport endpoint is already connected"
|
||||
#define ENOTCONN 128
|
||||
#define ENOTCONN_STR "Transport endpoint is not connected"
|
||||
#define ETOOMANYREFS 129
|
||||
#define ETOOMANYREFS_STR "Too many references: cannot splice"
|
||||
#define EPROCLIM 130
|
||||
#define EPROCLIM_STR "Limit would be exceeded by attempted fork"
|
||||
#define EUSERS 131
|
||||
#define EUSERS_STR "Too many users"
|
||||
#define EDQUOT 132
|
||||
#define EDQUOT_STR "Quota exceeded"
|
||||
#define ESTALE 133
|
||||
#define ESTALE_STR "Stale NFS file handle"
|
||||
#define ENOTSUP 134
|
||||
#define ENOTSUP_STR "Not supported"
|
||||
#define ENOMEDIUM 135 /* Linux errno extension */
|
||||
#define ENOMEDIUM_STR "No medium found"
|
||||
#define ENOSHARE 136 /* Cygwin */
|
||||
#define ENOSHARE_STR "No such host or network path"
|
||||
#define ECASECLASH 137 /* Cygwin */
|
||||
#define ECASECLASH_STR "Filename exists with different case"
|
||||
#define EILSEQ 138
|
||||
#define EILSEQ_STR "Illegal byte sequence"
|
||||
#define EOVERFLOW 139
|
||||
#define EOVERFLOW_STR "Value too large for defined data type"
|
||||
#define ECANCELED 140
|
||||
#define ECANCELED_STR "Operation cancelled"
|
||||
#define ENOTRECOVERABLE 141
|
||||
#define ENOTRECOVERABLE_STR "State not recoverable"
|
||||
#define EOWNERDEAD 142
|
||||
#define EOWNERDEAD_STR "Previous owner died"
|
||||
#define ESTRPIPE 143 /* Linux errno extension */
|
||||
#define ESTRPIPE_STR "Streams pipe error"
|
||||
|
||||
#define __ELASTERROR 2000 /* Users can add values starting here */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the thread specific errno. */
|
||||
|
||||
int *__errno(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_ERRNO_H */
|
||||
#endif /* USB_ERRNO_H */
|
||||
|
||||
@@ -13,21 +13,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
|
||||
typedef void *usbh_pipe_t;
|
||||
|
||||
/**
|
||||
* @brief USB Endpoint Configuration.
|
||||
*
|
||||
* Structure containing the USB endpoint configuration.
|
||||
*/
|
||||
struct usbh_endpoint_cfg {
|
||||
struct usbh_hubport *hport;
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_interval; /* Endpoint interval */
|
||||
uint8_t mult; /* Endpoint additional transcation */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief USB Iso Configuration.
|
||||
@@ -47,7 +32,10 @@ struct usbh_iso_frame_packet {
|
||||
* Structure containing the USB Urb configuration.
|
||||
*/
|
||||
struct usbh_urb {
|
||||
usbh_pipe_t pipe;
|
||||
void *hcpriv;
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
uint8_t data_toggle;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
@@ -73,6 +61,13 @@ struct usbh_urb {
|
||||
*/
|
||||
int usb_hc_init(void);
|
||||
|
||||
/**
|
||||
* @brief usb host controller hardware deinit.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_hc_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Get frame number.
|
||||
*
|
||||
@@ -88,34 +83,6 @@ uint16_t usbh_get_frame_number(void);
|
||||
*/
|
||||
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief reconfig endpoint pipe.
|
||||
*
|
||||
* @param pipe A memory allocated for pipe.
|
||||
* @param dev_addr device address.
|
||||
* @param ep_mps endpoint max packet size.
|
||||
* @param mult endpoint additional transcation
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
/**
|
||||
* @brief Allocate pipe for endpoint
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to save the allocated pipe.
|
||||
* @param ep_cfg Describes the endpoint info to be allocated.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
|
||||
|
||||
/**
|
||||
* @brief Free a pipe in which saves endpoint info.
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_free(usbh_pipe_t pipe);
|
||||
|
||||
/**
|
||||
* @brief Submit a usb transfer request to an endpoint.
|
||||
*
|
||||
@@ -130,7 +97,7 @@ int usbh_submit_urb(struct usbh_urb *urb);
|
||||
/**
|
||||
* @brief Cancel a transfer request.
|
||||
*
|
||||
* This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
|
||||
* This function will call When calls usbh_submit_urb and return -USB_ERR_TIMEOUT or -USB_ERR_SHUTDOWN.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MEM_H
|
||||
#define USB_MEM_H
|
||||
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
#if (CONFIG_USB_ALIGN_SIZE > 4)
|
||||
static inline void *usb_iomalloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
void *align_ptr;
|
||||
int uintptr_size;
|
||||
size_t align_size;
|
||||
uint32_t align = CONFIG_USB_ALIGN_SIZE;
|
||||
|
||||
/* sizeof pointer */
|
||||
uintptr_size = sizeof(void *);
|
||||
uintptr_size -= 1;
|
||||
|
||||
/* align the alignment size to uintptr size byte */
|
||||
align = ((align + uintptr_size) & ~uintptr_size);
|
||||
|
||||
/* get total aligned size */
|
||||
align_size = ((size + uintptr_size) & ~uintptr_size) + align;
|
||||
/* allocate memory block from heap */
|
||||
ptr = usb_malloc(align_size);
|
||||
if (ptr != NULL) {
|
||||
/* the allocated memory block is aligned */
|
||||
if (((unsigned long)ptr & (align - 1)) == 0) {
|
||||
align_ptr = (void *)((unsigned long)ptr + align);
|
||||
} else {
|
||||
align_ptr = (void *)(((unsigned long)ptr + (align - 1)) & ~(align - 1));
|
||||
}
|
||||
|
||||
/* set the pointer before alignment pointer to the real pointer */
|
||||
*((unsigned long *)((unsigned long)align_ptr - sizeof(void *))) = (unsigned long)ptr;
|
||||
|
||||
ptr = align_ptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void usb_iofree(void *ptr)
|
||||
{
|
||||
void *real_ptr;
|
||||
|
||||
real_ptr = (void *)*(unsigned long *)((unsigned long)ptr - sizeof(void *));
|
||||
usb_free(real_ptr);
|
||||
}
|
||||
#else
|
||||
#define usb_iomalloc(size) usb_malloc(size)
|
||||
#define usb_iofree(ptr) usb_free(ptr)
|
||||
#endif
|
||||
|
||||
#endif /* USB_MEM_H */
|
||||
@@ -27,6 +27,7 @@ usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem);
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem);
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem);
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void);
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
|
||||
@@ -34,6 +35,7 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq);
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
||||
|
||||
@@ -203,4 +203,6 @@
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
#endif /* USB_UTIL_H */
|
||||
|
||||
262
core/usbd_core.c
262
core/usbd_core.c
@@ -45,10 +45,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
|
||||
const struct usb_descriptor *descriptors;
|
||||
#else
|
||||
const uint8_t *descriptors;
|
||||
#endif
|
||||
struct usb_msosv1_descriptor *msosv1_desc;
|
||||
struct usb_msosv2_descriptor *msosv2_desc;
|
||||
struct usb_bos_descriptor *bos_desc;
|
||||
#endif
|
||||
/* Buffer used for storing standard, class and vendor request data */
|
||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||
|
||||
@@ -89,22 +89,18 @@ static bool is_device_configured(void)
|
||||
* This function sets endpoint configuration according to one specified in USB
|
||||
* endpoint descriptor and then enables it for data transfers.
|
||||
*
|
||||
* @param [in] ep_desc Endpoint descriptor byte array
|
||||
* @param [in] ep Endpoint descriptor byte array
|
||||
*
|
||||
* @return true if successfully configured and enabled
|
||||
*/
|
||||
static bool usbd_set_endpoint(const struct usb_endpoint_descriptor *ep_desc)
|
||||
static bool usbd_set_endpoint(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
struct usbd_endpoint_cfg ep_cfg;
|
||||
|
||||
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
|
||||
ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||
|
||||
USB_LOG_INFO("Open ep:0x%02x type:%u mps:%u\r\n",
|
||||
ep_cfg.ep_addr, ep_cfg.ep_type, ep_cfg.ep_mps);
|
||||
ep->bEndpointAddress,
|
||||
USB_GET_ENDPOINT_TYPE(ep->bmAttributes),
|
||||
USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
||||
|
||||
return usbd_ep_open(&ep_cfg) == 0 ? true : false;
|
||||
return usbd_ep_open(ep) == 0 ? true : false;
|
||||
}
|
||||
/**
|
||||
* @brief Disable endpoint for transferring data
|
||||
@@ -112,22 +108,17 @@ static bool usbd_set_endpoint(const struct usb_endpoint_descriptor *ep_desc)
|
||||
* This function cancels transfers that are associated with endpoint and
|
||||
* disabled endpoint itself.
|
||||
*
|
||||
* @param [in] ep_desc Endpoint descriptor byte array
|
||||
* @param [in] ep Endpoint descriptor byte array
|
||||
*
|
||||
* @return true if successfully deconfigured and disabled
|
||||
*/
|
||||
static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep_desc)
|
||||
static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
struct usbd_endpoint_cfg ep_cfg;
|
||||
|
||||
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
|
||||
ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||
|
||||
USB_LOG_INFO("Close ep:0x%02x type:%u\r\n",
|
||||
ep_cfg.ep_addr, ep_cfg.ep_type);
|
||||
ep->bEndpointAddress,
|
||||
USB_GET_ENDPOINT_TYPE(ep->bmAttributes));
|
||||
|
||||
return usbd_ep_close(ep_cfg.ep_addr) == 0 ? true : false;
|
||||
return usbd_ep_close(ep->bEndpointAddress) == 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,99 +139,76 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
uint8_t type = 0U;
|
||||
uint8_t index = 0U;
|
||||
bool found = true;
|
||||
uint8_t str_len = 0;
|
||||
uint32_t desc_len = 0;
|
||||
const uint8_t *desc = NULL;
|
||||
|
||||
type = HI_BYTE(type_index);
|
||||
index = LO_BYTE(type_index);
|
||||
|
||||
switch (type) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_descriptor[0];
|
||||
desc = g_usbd_core.descriptors->device_descriptor_callback(g_usbd_core.speed);
|
||||
if (desc == NULL) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
desc_len = desc[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
g_usbd_core.speed = usbd_get_port_speed(0);
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->hs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (g_usbd_core.descriptors->fs_config_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_config_descriptor[CONF_DESC_wTotalLength + 1] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
desc = g_usbd_core.descriptors->config_descriptor_callback(g_usbd_core.speed);
|
||||
if (desc == NULL) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
if (index == USB_STRING_LANGID_INDEX) {
|
||||
(*data)[0] = 0x04;
|
||||
(*data)[1] = 0x03;
|
||||
(*data)[2] = 0x09;
|
||||
(*data)[3] = 0x04;
|
||||
*len = 4;
|
||||
} else if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
if (g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n");
|
||||
*data = g_usbd_core.descriptors->msosv1_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->msosv1_descriptor->string_len;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (g_usbd_core.descriptors->string_descriptor[index - 1]) {
|
||||
str_len = strlen((const char *)g_usbd_core.descriptors->string_descriptor[index - 1]);
|
||||
if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
|
||||
|
||||
(*data)[0] = str_len * 2 + 2;
|
||||
(*data)[1] = 0x03;
|
||||
for (uint16_t i = 0; i < str_len; i++) {
|
||||
(*data)[i * 2 + 2] = g_usbd_core.descriptors->string_descriptor[index - 1][i];
|
||||
(*data)[i * 2 + 3] = 0;
|
||||
}
|
||||
|
||||
*len = str_len * 2 + 2;
|
||||
} else {
|
||||
if (!g_usbd_core.descriptors->msosv1_descriptor) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
desc = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->string;
|
||||
desc_len = g_usbd_core.descriptors->msosv1_descriptor->string[0];
|
||||
} else {
|
||||
desc = g_usbd_core.descriptors->string_descriptor_callback(g_usbd_core.speed, index);
|
||||
if (desc == NULL) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
desc_len = desc[0];
|
||||
}
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
if (g_usbd_core.descriptors->device_quality_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->device_quality_descriptor;
|
||||
*len = g_usbd_core.descriptors->device_quality_descriptor[0];
|
||||
} else {
|
||||
desc = g_usbd_core.descriptors->device_quality_descriptor_callback(g_usbd_core.speed);
|
||||
if (desc == NULL) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
desc_len = desc[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
if (g_usbd_core.descriptors->fs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->fs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
} else {
|
||||
if (g_usbd_core.descriptors->hs_other_speed_descriptor) {
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->hs_other_speed_descriptor;
|
||||
*len = (g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] |
|
||||
(g_usbd_core.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8));
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
desc = g_usbd_core.descriptors->other_speed_descriptor_callback(g_usbd_core.speed);
|
||||
if (desc == NULL) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE:
|
||||
USB_LOG_INFO("read BOS descriptor string\r\n");
|
||||
|
||||
if (!g_usbd_core.descriptors->bos_descriptor) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
desc = (uint8_t *)g_usbd_core.descriptors->bos_descriptor->string;
|
||||
desc_len = g_usbd_core.descriptors->bos_descriptor->string_len;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -251,6 +219,10 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l
|
||||
if (found == false) {
|
||||
/* nothing found */
|
||||
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
|
||||
} else {
|
||||
// *data = desc;
|
||||
memcpy(*data, desc, desc_len);
|
||||
*len = desc_len;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -359,13 +331,12 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
uint8_t cur_alt_setting = 0xFF;
|
||||
uint8_t cur_config = 0xFF;
|
||||
bool found = false;
|
||||
uint8_t *p;
|
||||
const uint8_t *p;
|
||||
uint32_t desc_len = 0;
|
||||
uint32_t current_desc_len = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
p = g_usbd_core.descriptors->config_descriptor_callback(g_usbd_core.speed);
|
||||
#else
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
@@ -378,6 +349,10 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
|
||||
if (cur_config == config_index) {
|
||||
found = true;
|
||||
|
||||
current_desc_len = 0;
|
||||
desc_len = (p[CONF_DESC_wTotalLength]) |
|
||||
(p[CONF_DESC_wTotalLength + 1] << 8);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -403,6 +378,10 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
|
||||
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
current_desc_len += p[DESC_bLength];
|
||||
if (current_desc_len >= desc_len && desc_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
@@ -423,13 +402,12 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
uint8_t cur_alt_setting = 0xFF;
|
||||
uint8_t cur_iface = 0xFF;
|
||||
bool ret = false;
|
||||
uint8_t *p;
|
||||
const uint8_t *p;
|
||||
uint32_t desc_len = 0;
|
||||
uint32_t current_desc_len = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (g_usbd_core.speed == USB_SPEED_HIGH) {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->hs_config_descriptor;
|
||||
} else {
|
||||
p = (uint8_t *)g_usbd_core.descriptors->fs_config_descriptor;
|
||||
}
|
||||
p = g_usbd_core.descriptors->config_descriptor_callback(g_usbd_core.speed);
|
||||
#else
|
||||
p = (uint8_t *)g_usbd_core.descriptors;
|
||||
#endif
|
||||
@@ -437,6 +415,13 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
|
||||
while (p[DESC_bLength] != 0U) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
current_desc_len = 0;
|
||||
desc_len = (p[CONF_DESC_wTotalLength]) |
|
||||
(p[CONF_DESC_wTotalLength + 1] << 8);
|
||||
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
/* remember current alternate setting */
|
||||
cur_alt_setting = p[INTF_DESC_bAlternateSetting];
|
||||
@@ -470,6 +455,10 @@ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
|
||||
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
current_desc_len += p[DESC_bLength];
|
||||
if (current_desc_len >= desc_len && desc_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
usbd_class_event_notify_handler(USBD_EVENT_SET_INTERFACE, (void *)if_desc);
|
||||
@@ -782,22 +771,24 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
switch (setup->wIndex) {
|
||||
case 0x04:
|
||||
USB_LOG_INFO("get Compat ID\r\n");
|
||||
desclen = g_usbd_core.msosv1_desc->compat_id[0] +
|
||||
(g_usbd_core.msosv1_desc->compat_id[1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->compat_id[3] << 24);
|
||||
desclen = g_usbd_core.descriptors->msosv1_descriptor->compat_id[0] +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->compat_id[1] << 8) +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->compat_id[2] << 16) +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->compat_id[3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->compat_id;
|
||||
//*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->compat_id;
|
||||
memcpy(*data, g_usbd_core.descriptors->msosv1_descriptor->compat_id, desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
case 0x05:
|
||||
USB_LOG_INFO("get Compat id properties\r\n");
|
||||
desclen = g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.msosv1_desc->comp_id_property[setup->wValue][3] << 24);
|
||||
desclen = g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue][0] +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue][1] << 8) +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue][2] << 16) +
|
||||
(g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue][3] << 24);
|
||||
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
|
||||
//*data = (uint8_t *)g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
|
||||
memcpy(*data, g_usbd_core.descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
@@ -810,7 +801,10 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->msosv2_descriptor->compat_id;
|
||||
|
||||
desclen = g_usbd_core.descriptors->msosv2_descriptor->compat_id_len;
|
||||
//*data = (uint8_t *)g_usbd_core.descriptors->msosv2_descriptor->compat_id;
|
||||
memcpy(*data, g_usbd_core.descriptors->msosv2_descriptor->compat_id, desclen);
|
||||
*len = g_usbd_core.descriptors->msosv2_descriptor->compat_id_len;
|
||||
return 0;
|
||||
default:
|
||||
@@ -823,8 +817,11 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
USB_LOG_INFO("GET Webusb url Descriptor\r\n");
|
||||
*data = (uint8_t *)g_usbd_core.descriptors->webusb_url_descriptor->string;
|
||||
*len = g_usbd_core.descriptors->webusb_url_descriptor->string_len;
|
||||
|
||||
desclen = g_usbd_core.descriptors->webusb_url_descriptor->string_len;
|
||||
//*data = (uint8_t *)g_usbd_core.descriptors->webusb_url_descriptor->string;
|
||||
memcpy(*data, g_usbd_core.descriptors->webusb_url_descriptor->string, desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
@@ -901,22 +898,14 @@ static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t *
|
||||
{
|
||||
switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
|
||||
case USB_REQUEST_STANDARD:
|
||||
if (usbd_standard_request_handler(setup, data, len) < 0) {
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
if (g_usbd_core.speed == USB_SPEED_FULL) {
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef CONFIG_USB_HS
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
//g_usbd_core.speed = USB_SPEED_FULL; /* next time will support getting device speed */
|
||||
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600) && (g_usbd_core.speed <= USB_SPEED_FULL)) {
|
||||
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (usbd_standard_request_handler(setup, data, len) < 0) {
|
||||
USB_LOG_ERR("standard request error\r\n");
|
||||
usbd_print_setup(setup);
|
||||
return false;
|
||||
@@ -990,15 +979,18 @@ void usbd_event_reset_handler(void)
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
g_usbd_core.test_mode = false;
|
||||
#endif
|
||||
struct usbd_endpoint_cfg ep0_cfg;
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
|
||||
ep0_cfg.ep_mps = USB_CTRL_EP_MPS;
|
||||
ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep0_cfg.ep_addr = USB_CONTROL_IN_EP0;
|
||||
usbd_ep_open(&ep0_cfg);
|
||||
ep0.bLength = 7;
|
||||
ep0.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
|
||||
ep0.wMaxPacketSize = USB_CTRL_EP_MPS;
|
||||
ep0.bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep0.bEndpointAddress = USB_CONTROL_IN_EP0;
|
||||
ep0.bInterval = 0;
|
||||
usbd_ep_open(&ep0);
|
||||
|
||||
ep0_cfg.ep_addr = USB_CONTROL_OUT_EP0;
|
||||
usbd_ep_open(&ep0_cfg);
|
||||
ep0.bEndpointAddress = USB_CONTROL_OUT_EP0;
|
||||
usbd_ep_open(&ep0);
|
||||
|
||||
usbd_class_event_notify_handler(USBD_EVENT_RESET, NULL);
|
||||
usbd_event_handler(USBD_EVENT_RESET);
|
||||
@@ -1141,7 +1133,7 @@ void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
void usbd_desc_register(struct usb_descriptor *desc)
|
||||
void usbd_desc_register(const struct usb_descriptor *desc)
|
||||
{
|
||||
memset(&g_usbd_core, 0, sizeof(struct usbd_core_priv));
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ extern "C" {
|
||||
#include "usb_errno.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_list.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_dc.h"
|
||||
|
||||
@@ -62,21 +61,19 @@ struct usbd_interface {
|
||||
};
|
||||
|
||||
struct usb_descriptor {
|
||||
const uint8_t *device_descriptor;
|
||||
const uint8_t *fs_config_descriptor;
|
||||
const uint8_t *hs_config_descriptor;
|
||||
const uint8_t *device_quality_descriptor;
|
||||
const uint8_t *fs_other_speed_descriptor;
|
||||
const uint8_t *hs_other_speed_descriptor;
|
||||
const char **string_descriptor;
|
||||
struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
|
||||
struct usb_bos_descriptor *bos_descriptor;
|
||||
const uint8_t *(*device_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*config_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*device_quality_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*other_speed_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
||||
const struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
const struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
const struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
|
||||
const struct usb_bos_descriptor *bos_descriptor;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
void usbd_desc_register(struct usb_descriptor *desc);
|
||||
void usbd_desc_register(const struct usb_descriptor *desc);
|
||||
#else
|
||||
void usbd_desc_register(const uint8_t *desc);
|
||||
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
|
||||
|
||||
199
core/usbh_core.c
199
core/usbh_core.c
@@ -4,7 +4,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
struct usbh_class_info *usbh_class_info_table_begin = NULL;
|
||||
struct usbh_class_info *usbh_class_info_table_end = NULL;
|
||||
@@ -59,12 +58,12 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
|
||||
}
|
||||
|
||||
if (startaddr == devaddr) {
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
|
||||
static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
|
||||
{
|
||||
int index;
|
||||
int bitno;
|
||||
@@ -127,10 +126,10 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device
|
||||
{
|
||||
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
|
||||
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else {
|
||||
if (length <= 8) {
|
||||
return 0;
|
||||
@@ -183,10 +182,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
|
||||
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
|
||||
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
|
||||
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
} else {
|
||||
if (length <= USB_SIZEOF_CONFIG_DESC) {
|
||||
return 0;
|
||||
@@ -228,15 +227,15 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
cur_ep = 0;
|
||||
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
|
||||
USB_LOG_ERR("Interface num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
|
||||
USB_LOG_ERR("Interface altsetting num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
|
||||
USB_LOG_ERR("Endpoint num overflow\r\n");
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
#if 0
|
||||
USB_LOG_DBG("Interface Descriptor:\r\n");
|
||||
@@ -300,25 +299,25 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport)
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
|
||||
USB_LOG_RAW("Interface Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("bAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("bNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("bInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("bInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("bInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("iInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
USB_LOG_RAW("\tInterface Descriptor:\r\n");
|
||||
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
|
||||
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
|
||||
USB_LOG_RAW("Endpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("wMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("bInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,57 +339,18 @@ static int usbh_get_default_mps(int speed)
|
||||
}
|
||||
}
|
||||
|
||||
int usbh_hport_activate_ep0(struct usbh_hubport *hport)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep0_cfg = { 0 };
|
||||
|
||||
ep0_cfg.ep_addr = 0x00;
|
||||
ep0_cfg.ep_interval = 0x00;
|
||||
ep0_cfg.ep_mps = usbh_get_default_mps(hport->speed);
|
||||
ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep0_cfg.hport = hport;
|
||||
|
||||
usbh_pipe_alloc(&hport->ep0, &ep0_cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hport_deactivate_ep0(struct usbh_hubport *hport)
|
||||
int usbh_free_devaddr(struct usbh_hubport *hport)
|
||||
{
|
||||
#ifndef CONFIG_USBHOST_XHCI
|
||||
if (hport->dev_addr > 0) {
|
||||
usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
|
||||
__usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
|
||||
}
|
||||
#endif
|
||||
if (hport->ep0) {
|
||||
usbh_pipe_free(hport->ep0);
|
||||
}
|
||||
|
||||
hport->ep0 = NULL;
|
||||
hport->dev_addr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc)
|
||||
{
|
||||
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||
|
||||
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
|
||||
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||
ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
ep_cfg.ep_interval = ep_desc->bInterval;
|
||||
ep_cfg.mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
ep_cfg.hport = hport;
|
||||
|
||||
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
ep_cfg.ep_addr,
|
||||
ep_desc->bmAttributes,
|
||||
ep_cfg.ep_mps,
|
||||
ep_cfg.ep_interval,
|
||||
ep_cfg.mult);
|
||||
|
||||
return usbh_pipe_alloc(pipe, &ep_cfg);
|
||||
}
|
||||
|
||||
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
|
||||
{
|
||||
struct usb_setup_packet *setup = hport->setup;
|
||||
@@ -408,7 +368,7 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
|
||||
setup->wIndex = 0x0409;
|
||||
setup->wLength = 255;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -432,11 +392,11 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = intf;
|
||||
setup->wIndex = altsetting;
|
||||
setup->wValue = altsetting;
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
return usbh_control_transfer(hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_enumerate(struct usbh_hubport *hport)
|
||||
@@ -444,12 +404,25 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
struct usb_interface_descriptor *intf_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usb_device_descriptor *dev_desc;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
int dev_addr;
|
||||
uint16_t ep_mps;
|
||||
int ret;
|
||||
|
||||
hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1];
|
||||
setup = hport->setup;
|
||||
ep = &hport->ep0;
|
||||
|
||||
/* Config EP0 mps from speed */
|
||||
ep->bEndpointAddress = 0x00;
|
||||
ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
|
||||
ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
|
||||
ep->bInterval = 0;
|
||||
ep->bLength = 7;
|
||||
|
||||
/* Configure EP0 with zero address */
|
||||
hport->dev_addr = 0;
|
||||
|
||||
/* Read the first 8 bytes of the device descriptor */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
@@ -458,7 +431,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 8;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -479,7 +452,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
dev_desc->bDeviceProtocol, ep_mps);
|
||||
|
||||
/* Reconfigure EP0 with the correct maximum packet size */
|
||||
usbh_ep_pipe_reconfigure(hport->ep0, 0, ep_mps, 0);
|
||||
ep->wMaxPacketSize = ep_mps;
|
||||
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
|
||||
@@ -506,7 +479,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -515,12 +488,9 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
/* Wait device set address completely */
|
||||
usb_osal_msleep(2);
|
||||
|
||||
/* Assign the function address to the port */
|
||||
/*Reconfigure EP0 with the correct address */
|
||||
hport->dev_addr = dev_addr;
|
||||
|
||||
/* And reconfigure EP0 with the correct address */
|
||||
usbh_ep_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, 0);
|
||||
|
||||
/* Read the full device descriptor */
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
@@ -528,7 +498,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_DEVICE_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -547,7 +517,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_CONFIG_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -564,7 +534,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = wTotalLength;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -578,7 +548,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces);
|
||||
hport->raw_config_desc = usb_malloc(wTotalLength);
|
||||
if (hport->raw_config_desc == NULL) {
|
||||
ret = -ENOMEM;
|
||||
ret = -USB_ERR_NOMEM;
|
||||
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
||||
goto errout;
|
||||
}
|
||||
@@ -623,7 +593,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(hport->ep0, setup, NULL);
|
||||
ret = usbh_control_transfer(hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
@@ -670,27 +640,6 @@ errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *usbh_find_class_instance(const char *devname)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
usb_slist_t *hub_list;
|
||||
|
||||
usb_slist_for_each(hub_list, &hub_class_head)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
||||
return hport->config.intf[itf].priv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int usbh_initialize(void)
|
||||
{
|
||||
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
|
||||
@@ -717,24 +666,52 @@ int usbh_initialize(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
int usbh_deinitialize(void)
|
||||
{
|
||||
return usbh_hub_deinitialize();
|
||||
}
|
||||
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
int ret;
|
||||
|
||||
urb = usb_malloc(sizeof(struct usbh_urb));
|
||||
urb = &hport->ep0_urb;
|
||||
|
||||
usb_osal_mutex_take(hport->mutex);
|
||||
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
|
||||
|
||||
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
usb_free(urb);
|
||||
|
||||
usb_osal_mutex_give(hport->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *usbh_find_class_instance(const char *devname)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
usb_slist_t *hub_list;
|
||||
|
||||
usb_slist_for_each(hub_list, &hub_class_head)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
|
||||
return hport->config.intf[itf].priv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lsusb(int argc, char **argv)
|
||||
{
|
||||
usb_slist_t *i;
|
||||
|
||||
149
core/usbh_core.h
149
core/usbh_core.h
@@ -16,11 +16,10 @@
|
||||
#include "usb_errno.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_list.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_hc.h"
|
||||
#include "usb_osal.h"
|
||||
#include "usb_hub.h"
|
||||
#include "usbh_hub.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -32,8 +31,8 @@ extern "C" {
|
||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
|
||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
@@ -44,57 +43,16 @@ extern "C" {
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#endif
|
||||
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
#define USBH_EP_INIT(ep, ep_desc) \
|
||||
do { \
|
||||
ep = ep_desc; \
|
||||
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \
|
||||
ep_desc->bEndpointAddress, \
|
||||
USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \
|
||||
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
|
||||
ep_desc->bInterval, \
|
||||
USB_GET_MULT(ep_desc->bmAttributes)); \
|
||||
} while (0)
|
||||
|
||||
struct usbh_class_info {
|
||||
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
|
||||
@@ -140,7 +98,6 @@ struct usbh_hubport {
|
||||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
usbh_pipe_t ep0; /* control ep pipe info */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
@@ -152,7 +109,9 @@ struct usbh_hubport {
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
usb_osal_thread_t thread;
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
struct usbh_urb ep0_urb;
|
||||
usb_osal_mutex_t mutex;
|
||||
};
|
||||
|
||||
struct usbh_hub {
|
||||
@@ -161,25 +120,70 @@ struct usbh_hub {
|
||||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
uint8_t *int_buffer;
|
||||
struct usbh_urb intin_urb;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
struct usb_endpoint_descriptor *intin;
|
||||
struct usbh_urb intin_urb;
|
||||
uint8_t *int_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Activates an endpoint for a USB host pipe on a specific hub port.
|
||||
*
|
||||
* This function is responsible for activating the specified endpoint
|
||||
* described by the given endpoint descriptor on the USB host pipe.
|
||||
* @param pipe Pointer to the USB host pipe structure.
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param ep_desc Pointer to the USB endpoint descriptor.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = &hport->ep0;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_endpoint_descriptor *ep,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = ep;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
struct usb_endpoint_descriptor *ep,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->hport = hport;
|
||||
urb->ep = ep;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Submit an control transfer to an endpoint.
|
||||
@@ -191,7 +195,7 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
|
||||
* @param buffer buffer used for sending the request and for returning any responses.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a USB string descriptor from a specific hub port.
|
||||
@@ -222,6 +226,7 @@ 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_initialize(void);
|
||||
int usbh_deinitialize(void);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
@@ -30,6 +30,133 @@
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
static const uint8_t device_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00)
|
||||
};
|
||||
|
||||
static const uint8_t device_quality_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x02,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const uint8_t string0_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
static const uint8_t string1_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
};
|
||||
|
||||
static const uint8_t string2_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'C', 0x00, /* wcChar10 */
|
||||
'-', 0x00, /* wcChar11 */
|
||||
'M', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
};
|
||||
|
||||
static const uint8_t string3_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
};
|
||||
|
||||
static const uint8_t *string_descriptors[4] = { string0_descriptor, string1_descriptor, string2_descriptor, string3_descriptor };
|
||||
|
||||
static const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return config_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_quality_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *string_descriptor_callback(uint8_t speed, uint8_t index)
|
||||
{
|
||||
if (index > 3) {
|
||||
return NULL;
|
||||
}
|
||||
return string_descriptors[index];
|
||||
}
|
||||
|
||||
const struct usb_descriptor cdc_msc_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback
|
||||
};
|
||||
#else
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_msc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
@@ -109,6 +236,7 @@ static const uint8_t cdc_msc_descriptor[] = {
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||
@@ -184,7 +312,11 @@ struct usbd_interface intf2;
|
||||
|
||||
void cdc_acm_msc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
usbd_desc_register(&cdc_msc_descriptor);
|
||||
#else
|
||||
usbd_desc_register(cdc_msc_descriptor);
|
||||
#endif
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
|
||||
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
|
||||
usbd_add_endpoint(&cdc_out_ep);
|
||||
|
||||
505
demo/usb_host.c
505
demo/usb_host.c
@@ -11,14 +11,18 @@
|
||||
#define TEST_USBH_MSC_FATFS 0
|
||||
#define TEST_USBH_AUDIO 0
|
||||
#define TEST_USBH_VIDEO 0
|
||||
#define TEST_USBH_CDC_ECM 0
|
||||
|
||||
#if __has_include("lwip/pbuf.h")
|
||||
#define TEST_USBH_CDC_ECM 1
|
||||
#define TEST_USBH_RNDIS 1
|
||||
#else
|
||||
#define TEST_USBH_CDC_ECM 0
|
||||
#define TEST_USBH_RNDIS 0
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ACM
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512];
|
||||
|
||||
struct usbh_urb cdc_bulkin_urb;
|
||||
struct usbh_urb cdc_bulkout_urb;
|
||||
|
||||
void usbh_cdc_acm_callback(void *arg, int nbytes)
|
||||
{
|
||||
//struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
|
||||
@@ -36,74 +40,53 @@ static void usbh_cdc_acm_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_cdc_acm *cdc_acm_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
|
||||
if (cdc_acm_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/ttyACM0\r\n");
|
||||
usb_osal_msleep(1000);
|
||||
continue;
|
||||
}
|
||||
memset(cdc_buffer, 0, 512);
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("recv over:%d\r\n", cdc_bulkin_urb.actual_length);
|
||||
for (size_t i = 0; i < cdc_bulkin_urb.actual_length; i++) {
|
||||
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_RAW("\r\n");
|
||||
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||
|
||||
memcpy(cdc_buffer, data1, 8);
|
||||
usbh_bulk_urb_fill(&cdc_bulkout_urb, cdc_acm_class->bulkout, cdc_buffer, 8, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_bulkout_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", cdc_bulkout_urb.actual_length);
|
||||
}
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, usbh_cdc_acm_callback, cdc_acm_class);
|
||||
ret = usbh_submit_urb(&cdc_bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
}
|
||||
|
||||
while (1) {
|
||||
cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
|
||||
if (cdc_acm_class == NULL) {
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(1000);
|
||||
}
|
||||
// clang-format on
|
||||
while ((cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
memset(cdc_buffer, 0, 512);
|
||||
|
||||
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||
|
||||
memcpy(cdc_buffer, data1, 10);
|
||||
usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, cdc_buffer, 10, 3000, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_acm_class->bulkout_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||
goto find_class;
|
||||
} else {
|
||||
USB_LOG_RAW("send over:%d\r\n", cdc_acm_class->bulkout_urb.actual_length);
|
||||
}
|
||||
|
||||
usbh_bulk_urb_fill(&cdc_acm_class->bulkin_urb, cdc_acm_class->hport, cdc_acm_class->bulkin, cdc_buffer, cdc_acm_class->bulkin->wMaxPacketSize, 3000, usbh_cdc_acm_callback, cdc_acm_class);
|
||||
ret = usbh_submit_urb(&cdc_acm_class->bulkin_urb);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||
} else {
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_HID
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_buffer[128];
|
||||
|
||||
struct usbh_urb hid_intin_urb;
|
||||
|
||||
void usbh_hid_callback(void *arg, int nbytes)
|
||||
{
|
||||
//struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
USB_LOG_RAW("0x%02x ", hid_buffer[i]);
|
||||
}
|
||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||
usbh_submit_urb(&hid_intin_urb);
|
||||
usbh_submit_urb(&hid_class->intin_urb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,31 +95,22 @@ static void usbh_hid_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_hid *hid_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
|
||||
if (hid_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/input0\r\n");
|
||||
usb_osal_msleep(1500);
|
||||
continue;
|
||||
}
|
||||
usbh_int_urb_fill(&hid_intin_urb, hid_class->intin, hid_buffer, 8, 0, usbh_hid_callback, hid_class);
|
||||
ret = usbh_submit_urb(&hid_intin_urb);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(1500);
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
|
||||
if (hid_class == NULL) {
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(1500);
|
||||
}
|
||||
// clang-format on
|
||||
while ((hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_buffer, hid_class->intin->wMaxPacketSize, 0, usbh_hid_callback, hid_class);
|
||||
ret = usbh_submit_urb(&hid_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -172,7 +146,7 @@ int usb_msc_fatfs_test()
|
||||
if (res_sd == FR_OK) {
|
||||
res_sd = f_write(&fnew, read_write_buffer, sizeof(read_write_buffer), &fnum);
|
||||
if (res_sd == FR_OK) {
|
||||
USB_LOG_RAW("write success, write len:%d\n", fnum);
|
||||
USB_LOG_RAW("write success, write len:%d\n", fnum);
|
||||
} else {
|
||||
USB_LOG_RAW("write fail\r\n");
|
||||
goto unmount;
|
||||
@@ -188,7 +162,7 @@ int usb_msc_fatfs_test()
|
||||
if (res_sd == FR_OK) {
|
||||
res_sd = f_read(&fnew, read_write_buffer, sizeof(read_write_buffer), &fnum);
|
||||
if (res_sd == FR_OK) {
|
||||
USB_LOG_RAW("read success, read len:%d\n", fnum);
|
||||
USB_LOG_RAW("read success, read len:%d\n", fnum);
|
||||
} else {
|
||||
USB_LOG_RAW("read fail\r\n");
|
||||
goto unmount;
|
||||
@@ -213,45 +187,36 @@ static void usbh_msc_thread(void *argument)
|
||||
int ret;
|
||||
struct usbh_msc *msc_class;
|
||||
|
||||
while (1) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
|
||||
if (msc_class == NULL) {
|
||||
USB_LOG_RAW("do not find /dev/sda\r\n");
|
||||
usb_osal_msleep(2000);
|
||||
continue;
|
||||
}
|
||||
// clang-format on
|
||||
while ((msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda")) == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* get the partition table */
|
||||
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||
usb_osal_msleep(2000);
|
||||
goto find_class;
|
||||
/* get the partition table */
|
||||
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||
goto find_class;
|
||||
}
|
||||
for (uint32_t i = 0; i < 512; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
for (uint32_t i = 0; i < 512; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_MSC_FATFS
|
||||
usb_msc_fatfs_test();
|
||||
usb_msc_fatfs_test();
|
||||
#endif
|
||||
while (1) {
|
||||
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
|
||||
if (msc_class == NULL) {
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(2000);
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -381,19 +346,92 @@ void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostre
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ECM
|
||||
#include "usbh_cdc_ecm.h"
|
||||
|
||||
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#if LWIP_DHCP
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/prot/dhcp.h"
|
||||
#endif
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
|
||||
#ifndef RT_USING_TIMER_SOFT
|
||||
#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <netif/ethernetif.h>
|
||||
#include <netdev.h>
|
||||
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#include "timers.h"
|
||||
|
||||
TimerHandle_t dhcp_handle1;
|
||||
TimerHandle_t dhcp_handle2;
|
||||
|
||||
static void dhcp_timeout(TimerHandle_t xTimer)
|
||||
{
|
||||
struct netif *netif = (struct netif *)pvTimerGetTimerID(xTimer);
|
||||
struct dhcp *dhcp;
|
||||
|
||||
if (netif_is_up(netif)) {
|
||||
dhcp = netif_dhcp_data(netif);
|
||||
|
||||
if (dhcp && (dhcp->state == DHCP_STATE_BOUND)) {
|
||||
USB_LOG_INFO("IPv4 Address : %s\r\n", ipaddr_ntoa(&netif->ip_addr));
|
||||
USB_LOG_INFO("IPv4 Subnet mask : %s\r\n", ipaddr_ntoa(&netif->netmask));
|
||||
USB_LOG_INFO("IPv4 Gateway : %s\r\n\r\n", ipaddr_ntoa(&netif->gw));
|
||||
|
||||
xTimerStop(xTimer, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_CDC_ECM
|
||||
#include "usbh_cdc_ecm.h"
|
||||
|
||||
struct netif g_cdc_ecm_netif;
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
static struct eth_device cdc_ecm_dev;
|
||||
|
||||
static rt_err_t rt_usbh_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)dev->user_data;
|
||||
|
||||
switch (cmd) {
|
||||
case NIOCTL_GADDR:
|
||||
|
||||
/* get mac address */
|
||||
if (args)
|
||||
rt_memcpy(args, cdc_ecm_class->mac, 6);
|
||||
else
|
||||
return -RT_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||
{
|
||||
return usbh_cdc_ecm_linkoutput(NULL, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
static err_t usbh_cdc_ecm_if_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
@@ -410,6 +448,21 @@ static err_t usbh_cdc_ecm_if_init(struct netif *netif)
|
||||
|
||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
struct netdev *netdev;
|
||||
|
||||
memset(&cdc_ecm_dev, 0, sizeof(struct eth_device));
|
||||
|
||||
cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
|
||||
cdc_ecm_dev.eth_rx = NULL;
|
||||
cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
|
||||
cdc_ecm_dev.parent.user_data = cdc_ecm_class;
|
||||
|
||||
eth_device_init(&cdc_ecm_dev, "u0");
|
||||
eth_device_linkchange(&cdc_ecm_dev, RT_TRUE);
|
||||
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, cdc_ecm_dev.netif);
|
||||
#else
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
@@ -424,13 +477,26 @@ void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
dhcp_handle1 = xTimerCreate((const char *)"dhcp1", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||
if (dhcp_handle1 == NULL) {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, netif);
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
xTimerStart(dhcp_handle1, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
eth_device_deinit(&cdc_ecm_dev);
|
||||
#else
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
#if LWIP_DHCP
|
||||
dhcp_stop(netif);
|
||||
@@ -438,11 +504,177 @@ void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
#endif
|
||||
netif_set_down(netif);
|
||||
netif_remove(netif);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_RNDIS
|
||||
#include "usbh_rndis.h"
|
||||
|
||||
struct netif g_rndis_netif;
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
|
||||
static struct eth_device rndis_dev;
|
||||
|
||||
static rt_timer_t keep_timer = RT_NULL;
|
||||
|
||||
static void rndis_dev_keepalive_timeout(void *parameter)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
|
||||
usbh_rndis_keepalive(rndis_class);
|
||||
}
|
||||
|
||||
static void timer_init(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
keep_timer = rt_timer_create("keep",
|
||||
rndis_dev_keepalive_timeout,
|
||||
rndis_class,
|
||||
5000,
|
||||
RT_TIMER_FLAG_PERIODIC |
|
||||
RT_TIMER_FLAG_SOFT_TIMER);
|
||||
|
||||
rt_timer_start(keep_timer);
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
|
||||
|
||||
switch (cmd) {
|
||||
case NIOCTL_GADDR:
|
||||
|
||||
/* get mac address */
|
||||
if (args)
|
||||
rt_memcpy(args, rndis_class->mac, 6);
|
||||
else
|
||||
return -RT_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||
{
|
||||
return usbh_rndis_linkoutput(NULL, p);
|
||||
}
|
||||
|
||||
#else
|
||||
TimerHandle_t timer_handle;
|
||||
|
||||
static void rndis_dev_keepalive_timeout(TimerHandle_t xTimer)
|
||||
{
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)pvTimerGetTimerID(xTimer);
|
||||
usbh_rndis_keepalive(rndis_class);
|
||||
}
|
||||
|
||||
void timer_init(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
timer_handle = xTimerCreate((const char *)NULL, (TickType_t)5000, (UBaseType_t)pdTRUE, (void *const)rndis_class, (TimerCallbackFunction_t)rndis_dev_keepalive_timeout);
|
||||
if (NULL != timer_handle) {
|
||||
xTimerStart(timer_handle, 0);
|
||||
} else {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static err_t usbh_rndis_if_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
netif->state = NULL;
|
||||
netif->name[0] = 'E';
|
||||
netif->name[1] = 'X';
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = usbh_rndis_linkoutput;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
struct netdev *netdev;
|
||||
|
||||
memset(&rndis_dev, 0, sizeof(struct eth_device));
|
||||
|
||||
rndis_dev.parent.control = rt_usbh_rndis_control;
|
||||
rndis_dev.eth_rx = NULL;
|
||||
rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
|
||||
rndis_dev.parent.user_data = rndis_class;
|
||||
|
||||
eth_device_init(&rndis_dev, "u1");
|
||||
eth_device_linkchange(&rndis_dev, RT_TRUE);
|
||||
|
||||
usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, rndis_dev.netif);
|
||||
timer_init(rndis_class);
|
||||
#else
|
||||
struct netif *netif = &g_rndis_netif;
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, rndis_class->mac, 6);
|
||||
|
||||
IP4_ADDR(&rndis_class->ipaddr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&rndis_class->netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&rndis_class->gateway, 0, 0, 0, 0);
|
||||
|
||||
netif = netif_add(netif, &rndis_class->ipaddr, &rndis_class->netmask, &rndis_class->gateway, NULL, usbh_rndis_if_init, tcpip_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
dhcp_handle2 = xTimerCreate((const char *)"dhcp2", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
|
||||
if (dhcp_handle2 == NULL) {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, netif);
|
||||
timer_init(rndis_class);
|
||||
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
xTimerStart(dhcp_handle2, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
eth_device_deinit(&rndis_dev);
|
||||
rt_timer_stop(keep_timer);
|
||||
rt_timer_delete(keep_timer);
|
||||
#else
|
||||
struct netif *netif = &g_rndis_netif;
|
||||
#if LWIP_DHCP
|
||||
dhcp_stop(netif);
|
||||
dhcp_cleanup(netif);
|
||||
#endif
|
||||
netif_set_down(netif);
|
||||
netif_remove(netif);
|
||||
xTimerStop(timer_handle, 0);
|
||||
xTimerDelete(timer_handle, 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
#if TEST_USBH_CDC_ACM
|
||||
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
@@ -451,22 +683,34 @@ void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
#if TEST_USBH_HID
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef __RTTHREAD__
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
#if TEST_USBH_MSC
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbh_audio_run(struct usbh_audio *audio_class)
|
||||
{
|
||||
#if TEST_USBH_AUDIO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_audio", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_audio_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
@@ -475,6 +719,10 @@ void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
|
||||
void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
#if TEST_USBH_VIDEO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_video", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_video_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbh_video_stop(struct usbh_video *video_class)
|
||||
@@ -483,27 +731,12 @@ void usbh_video_stop(struct usbh_video *video_class)
|
||||
|
||||
void usbh_class_test(void)
|
||||
{
|
||||
#if TEST_USBH_CDC_ACM
|
||||
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_HID
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_MSC
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_AUDIO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_audio", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_audio_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_VIDEO
|
||||
#error "if you want to use iso, please contact with me"
|
||||
usb_osal_thread_create("usbh_video", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_video_thread, NULL);
|
||||
#endif
|
||||
#if TEST_USBH_CDC_ECM
|
||||
#ifdef __RTTHREAD__
|
||||
/* do nothing */
|
||||
#else
|
||||
#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS
|
||||
/* Initialize the LwIP stack */
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
usbh_cdc_ecm_lwip_thread_init(&g_cdc_ecm_netif);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -127,12 +127,11 @@ rndis 与 lwip 接口的对接
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
|
||||
|
||||
CONFIG_USBHOST_PSC_PRIO
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
主机插拔线程的优先级,默认是 4,数值越小,优先级越高
|
||||
主机插拔线程的优先级,默认是 0,数值越小,优先级越高
|
||||
|
||||
CONFIG_USBHOST_PSC_STACKSIZE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -76,7 +76,6 @@ hubport 结构体
|
||||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
usbh_pipe_t ep0; /* control ep pipe info */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
@@ -88,7 +87,9 @@ hubport 结构体
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
usb_osal_thread_t thread;
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
struct usbh_urb ep0_urb;
|
||||
usb_osal_mutex_t mutex;
|
||||
};
|
||||
|
||||
hub 结构体
|
||||
@@ -102,12 +103,12 @@ hub 结构体
|
||||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
uint8_t *int_buffer;
|
||||
struct usbh_urb intin_urb;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
struct usb_endpoint_descriptor *intin;
|
||||
struct usbh_urb intin_urb;
|
||||
uint8_t *int_buffer;
|
||||
};
|
||||
|
||||
usbh_initialize
|
||||
@@ -150,7 +151,4 @@ MSC
|
||||
-----------------
|
||||
|
||||
RNDIS
|
||||
-----------------
|
||||
|
||||
PRINTER
|
||||
-----------------
|
||||
@@ -153,46 +153,6 @@ usbh_roothub_control
|
||||
- **buf** 接收缓冲区
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_ep_pipe_reconfigure
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_ep_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
- **pipe** pipe 句柄
|
||||
- **dev_addr** 端点所在设备地址
|
||||
- **ep_mps** 端点最大包长
|
||||
- **mult** 端点一次传输个数
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_pipe_alloc
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_pipe_alloc`` 为端点分配 pipe。 **此函数不对用户开放**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
|
||||
|
||||
- **pipe** pipe 句柄
|
||||
- **ep_cfg** 端点初始化需要的一些信息
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_pipe_free
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
``usbh_pipe_free`` 释放端点的一些属性。 **此函数不对用户开放**。
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int usbh_pipe_free(usbh_pipe_t pipe);
|
||||
|
||||
- **pipe** 端点信息
|
||||
- **return** 返回 0 表示正确,其他表示错误
|
||||
|
||||
usbh_submit_urb
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
@@ -209,22 +169,33 @@ usbh_submit_urb
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct usbh_urb {
|
||||
usbh_pipe_t pipe;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
int transfer_flags;
|
||||
uint32_t actual_length;
|
||||
uint32_t timeout;
|
||||
int errorcode;
|
||||
uint32_t num_of_iso_packets;
|
||||
usbh_complete_callback_t complete;
|
||||
void *arg;
|
||||
struct usbh_iso_frame_packet iso_packet[];
|
||||
};
|
||||
struct usbh_urb {
|
||||
void *hcpriv;
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
uint8_t data_toggle;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
int transfer_flags;
|
||||
uint32_t actual_length;
|
||||
uint32_t timeout;
|
||||
int errorcode;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint32_t start_frame;
|
||||
usbh_complete_callback_t complete;
|
||||
void *arg;
|
||||
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
|
||||
struct usbh_iso_frame_packet *iso_packet;
|
||||
#else
|
||||
struct usbh_iso_frame_packet iso_packet[0];
|
||||
#endif
|
||||
};
|
||||
|
||||
- **pipe** 端点对应的 pipe 句柄
|
||||
- **hcpriv** 主机控制器驱动私有成员
|
||||
- **hport** 当前 urb 使用的 hport
|
||||
- **ep** 当前 urb 使用的 ep
|
||||
- **data_toggle** 当前 data toggle
|
||||
- **setup** setup 请求缓冲区,端点0使用
|
||||
- **transfer_buffer** 传输的数据缓冲区
|
||||
- **transfer_buffer_length** 传输长度
|
||||
@@ -239,30 +210,22 @@ usbh_submit_urb
|
||||
|
||||
`errorcode` 可以返回以下值:
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 30
|
||||
:header-rows: 1
|
||||
.. code-block:: C
|
||||
|
||||
* - ERROR CODE
|
||||
- desc
|
||||
* - ENOMEM
|
||||
- 内存不足
|
||||
* - ENODEV
|
||||
- 设备未连接
|
||||
* - EBUSY
|
||||
- 当前数据发送或者接收还未完成
|
||||
* - ETIMEDOUT
|
||||
- 数据发送或者接收超时
|
||||
* - EPERM
|
||||
- 主机收到 STALL 包或者 BABBLE
|
||||
* - EIO
|
||||
- 数据传输错误
|
||||
* - EAGAIN
|
||||
- 主机一直收到 NAK 包
|
||||
* - EPIPE
|
||||
- 数据溢出
|
||||
* - ESHUTDOWN
|
||||
- 设备断开,传输中止
|
||||
#define USB_ERR_NOMEM 1
|
||||
#define USB_ERR_INVAL 2
|
||||
#define USB_ERR_NODEV 3
|
||||
#define USB_ERR_NOTCONN 4
|
||||
#define USB_ERR_NOTSUPP 5
|
||||
#define USB_ERR_BUSY 6
|
||||
#define USB_ERR_RANGE 7
|
||||
#define USB_ERR_STALL 8
|
||||
#define USB_ERR_BABBLE 9
|
||||
#define USB_ERR_NAK 10
|
||||
#define USB_ERR_DT 11
|
||||
#define USB_ERR_IO 12
|
||||
#define USB_ERR_SHUTDOWN 13
|
||||
#define USB_ERR_TIMEOUT 14
|
||||
|
||||
其中 `iso_packet` 结构体信息如下:
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ project = 'CherryUSB'
|
||||
copyright = '2022, sakumisu'
|
||||
author = 'sakumisu'
|
||||
|
||||
release = '0.10.0'
|
||||
version = '0.10.0'
|
||||
release = '1.0.0'
|
||||
version = '1.0.0'
|
||||
|
||||
# -- General configuration
|
||||
|
||||
|
||||
@@ -48,6 +48,22 @@ FSDEV 仅支持从机。这个 ip 不同厂家基本都是基于标准的 usb
|
||||
- 同上
|
||||
- 1
|
||||
|
||||
fsdev 需要外置 dp 上拉才能使用,有些芯片可能是接上拉电阻,有些芯片可能是设置寄存器,举例如下:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
USB->BCDR |= (uint16_t)USB_BCDR_DPPU;
|
||||
|
||||
如果不存在 BCDR 寄存器,则一般是配置如下,并且该设置需要配置到 `usb_dc_low_level_init` 中或者 `usb_dc_init` 最后都行:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
/* Pull up controller register */
|
||||
#define DP_CTRL ((__IO unsigned*)(0x40001820))
|
||||
|
||||
#define _EnPortPullup() (*DP_CTRL = (*DP_CTRL) | 0x10000000);
|
||||
#define _DisPortPullup() (*DP_CTRL = (*DP_CTRL) & 0xEFFFFFFF);
|
||||
|
||||
MUSB
|
||||
--------------------------
|
||||
|
||||
@@ -153,11 +169,11 @@ MUSB IP 支持主从,并且由 **mentor** 定义了一套标准的寄存器偏
|
||||
DWC2
|
||||
--------------------------
|
||||
|
||||
DWC2 IP 支持主从,并且由 **synopsys** 定义了一套标准的寄存器偏移。大部分厂家都使用标准的寄存器偏移,所以如果是从机仅需要修改 `USBD_IRQHandler` 、 `USB_BASE` 、 `USB_NUM_BIDIR_ENDPOINTS` ,主机仅需要修改 `USBH_IRQHandler` 、 `USB_BASE` 即可。
|
||||
DWC2 IP 支持主从,并且由 **synopsys** 定义了一套标准的寄存器偏移。大部分厂家都使用标准的寄存器偏移(除了 GCCFG(GGPIO)寄存器),所以如果是从机仅需要修改 `USBD_IRQHandler` 、 `USB_BASE` 、 `USB_NUM_BIDIR_ENDPOINTS` ,主机仅需要修改 `USBH_IRQHandler` 、 `USB_BASE` 即可。
|
||||
|
||||
其次还有需要注意 VBUS SENSING 这个项,也会影响 USB 的正常枚举,如何修改参考 `GD32 dwc2驱动的GCCFG_NOVBUSSENS寄存器兼容性和stm32存在区别 <https://github.com/sakumisu/CherryUSB/issues/64>`_。
|
||||
.. note:: GCCFG(GGPIO) 根据不同的厂家设置不同,会影响 usb 枚举,需要根据厂家提供的手册进行配置,并实现 usbd_get_dwc2_gccfg_conf 和 usbh_get_dwc2_gccfg_conf 函数,填充相应需要使能的bit
|
||||
|
||||
.. caution:: 主机 port 仅支持有高速功能的 dwc2 ip, 因为他支持 dma 模式,如果厂家买的 ip 不支持 dma 模式,则无法使用。
|
||||
.. caution:: 主机 port 仅支持有 dma 功能的 dwc2 ip(代码中会判断当前 ip 是否支持), 如果不支持 dma 模式,则无法使用。
|
||||
|
||||
下表为具体芯片从机相关宏的修改值:
|
||||
|
||||
@@ -213,4 +229,4 @@ EHCI 是 intel 制定的标准主机控制器接口,任何厂家都必须实
|
||||
//是否使能 port power bit
|
||||
#define CONFIG_USB_EHCI_PORT_POWER
|
||||
|
||||
同时由于 EHCI 只是主机控制器,一般配合一个 device 控制器+ otg 控制器,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。
|
||||
同时由于 EHCI 只是主机控制器并且只支持高速,一般配合一个 otg 控制器和一个低速全速兼容控制单元,而速度的获取一般是在 otg 寄存器中,所以需要用户实现 `usbh_get_port_speed` 函数。
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
@@ -23,8 +23,8 @@
|
||||
默认提供以下 demo 工程:
|
||||
|
||||
- F103 使用 fsdev ip
|
||||
- F429 主从使用 hs port,并且均用 dma 模式
|
||||
- H7 设备使用 fs port,主机使用 hs port,并且主机带 cache 支持
|
||||
- F429 主从使用 USB_OTG_HS, 引脚 pb14/pb15, 并且都使用 dma 模式
|
||||
- H7 设备使用 USB_OTG_FS, 引脚 pa11/pa12,主机使用 USB_OTG_HS ,引脚 pb14/pb15,并且需要做 nocache 处理
|
||||
|
||||
默认删除 Drivers ,所以需要使用 stm32cubemx 生成一下 Drivers 目录下的文件,demo 底下提供了 **stm32xxx.ioc** 文件,双击打开,点击 **Generate Code** 即可。
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
涵盖 F1/F4/H7,其余芯片基本类似,不再赘述,具体区别有:
|
||||
|
||||
- usb ip 区别:F1使用 fsdev,F4/H7使用 dwc2
|
||||
- dwc2 ip 区别: fs port(引脚是 PA11/PA12) 和 hs port(引脚是 PB14/PB15), 其中 hs port 默认全速,可以接外部PHY 形成高速主机,并且带 dma 功能
|
||||
- F4 与 H7 cache 区别、USB BASE 区别
|
||||
- dwc2 ip 区别: USB_OTG_FS (引脚是 PA11/PA12) 和 USB_OTG_HS (引脚是 PB14/PB15), 其中 USB_OTG_HS 默认全速,可以接外部PHY 形成高速主机,并且带 dma 功能
|
||||
- F4 无cache,H7 有 cache
|
||||
|
||||
如果是 STM32F7/STM32H7 这种带 cache 功能,需要将 usb 使用到的 ram 定位到 no cache ram 区域。举例如下
|
||||
|
||||
@@ -61,11 +61,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. caution :: 如果使用 STM32F7 或者 STM32H7, 请在 CFLAG 中添加 STM32F7 或者 STM32H7 宏定义,否则无法枚举
|
||||
|
||||
.. figure:: img/keil.png
|
||||
|
||||
USB Device 移植要点
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -100,9 +95,15 @@ USB Device 移植要点
|
||||
|
||||
.. figure:: img/stm32_8.png
|
||||
|
||||
- 如果使用 dwc2 ip,编译选项中需要添加 `CONFIG_USB_DWC2_PORT=xxx`,使用 PA11/PA12 则 **xxx=FS_PORT**,使用 PB14/PB15 则 **xxx=HS_PORT**
|
||||
- 如果使用 dwc2 ip,需要增加 **usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
|
||||
|
||||
.. figure:: img/stm32_9.png
|
||||
.. code-block:: C
|
||||
|
||||
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
||||
#define USBD_IRQHandler OTG_HS_IRQHandler // pa11/pa12 引脚使用 OTG_FS_IRQHandler
|
||||
#define USBD_BASE (0x40040000UL) // pa11/pa12 引脚一般使用 50000000UL,STM32F7/H7 使用 0x40080000UL
|
||||
#define CONFIG_USBDEV_EP_NUM 6 // pa11/pa12 引脚使用 4
|
||||
#define CONFIG_USB_DWC2_RAM_SIZE 4096 // pa11/pa12 引脚使用 1280
|
||||
|
||||
- 编译器推荐使用 **AC6**。勾选 **Microlib**,并实现 **printf** ,方便后续查看 log。
|
||||
|
||||
@@ -122,7 +123,7 @@ USB Device 移植要点
|
||||
USB Host 移植要点
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
前面 7 步与 Device 一样。需要注意,host 驱动只支持带 dma 的 hs port (引脚是 PB14/PB15),所以 fs port (引脚是 PA11/PA12)不做支持(没有 dma 你玩什么主机)。
|
||||
前面 6 步与 Device 一样。需要注意,host 驱动只支持带 dma 的 hs port (引脚是 PB14/PB15),所以 fs port (引脚是 PA11/PA12)不做支持(没有 dma 你玩什么主机)。
|
||||
|
||||
- 添加 CherryUSB 必须要的源码( **usbh_core.c** 、 **usbh_hub.c** 、 **usb_hc_dwc2.c** 、以及 **osal** 目录下的适配层文件),以及想要使用的 class 驱动,并且可以将对应的 **usb host.c** 添加方便测试。
|
||||
|
||||
@@ -139,6 +140,17 @@ USB Host 移植要点
|
||||
.. figure:: img/stm32_13.png
|
||||
.. figure:: img/stm32_19.png
|
||||
|
||||
- 复制一份 **cherryusb_config_template.h**,放到 `Core/Inc` 目录下,并命名为 `usb_config.h`
|
||||
|
||||
- 增加 **usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
||||
#define USBH_BASE (0x40040000UL)
|
||||
#define USBH_IRQHandler OTG_HS_IRQHandler
|
||||
#define CONFIG_USBHOST_PIPE_NUM 12
|
||||
|
||||
- 调用 **usbh_initialize** 以及 os 需要的启动线程的函数即可使用
|
||||
|
||||
.. figure:: img/stm32_20.png
|
||||
|
||||
@@ -7,21 +7,25 @@ USB Device 移植要点
|
||||
-----------------------
|
||||
|
||||
- 拷贝 CherryUSB 源码到工程目录下,并按需添加源文件和头文件路径,其中 `usbd_core.c` 和 `usb_dc_xxx.c` 为必须添加项。而 `usb_dc_xxx.c` 是芯片所对应的 USB IP dcd 部分驱动,如果不知道自己芯片属于那个 USB IP,参考 **port** 目录下的不同 USB IP 的 readme。如果使用的 USB IP 没有支持,只能自己实现了
|
||||
- 添加 `USBD_IRQHandler=xxxx` 、 `USB_NUM_BIDIR_ENDPOINTS=x` 以及 `USB_BASE=0xxxxx` 三个 cflag 编译选项,如果没有添加则使用 `usb_dc_xxx.c` 中默认配置
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径。
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径
|
||||
- 在 `usb_config.h` 中添加 `USBD_IRQHandler=xxxx` 、 `CONFIG_USBDEV_EP_NUM=x` 以及 `USBD_BASE=0xxxxx` 三个常规 porting 需要的宏
|
||||
|
||||
.. note:: 上述三个宏仅对 fsdev、musb、dwc2 有效,因为这 3 个是通用 IP
|
||||
|
||||
- 实现 `usb_dc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
|
||||
- 描述符的注册、class的注册、接口的注册、端点中断的注册。不会的参考 demo 下的 template
|
||||
- 调用 `usbd_initialize` 初始化 usb 硬件
|
||||
- 编译使用。各个 class 如何使用,参考 demo 下的 template
|
||||
|
||||
.. note:: device 移植要点其实就三个,实现 `usb_dc_low_level_init` ;改 `USBD_IRQHandler=xxxx` 、`USB_BASE=0xxxxx` 、 `USB_NUM_BIDIR_ENDPOINTS=x`;改 `usb_config.h` 中的内容。其中前面说到的3个宏也可以在 `usb_config.h` 添加
|
||||
|
||||
USB Host 移植要点
|
||||
-----------------------
|
||||
|
||||
- 拷贝 CherryUSB 源码到工程目录下,并按需添加源文件和头文件路径,其中 `usbh_core.c` 、 `usb_hc_xxx.c` 以及 **osal** 目录下源文件(根据不同的 os 选择对应的源文件)为必须添加项。而 `usb_hc_xxx.c` 是芯片所对应的 USB IP dcd 部分驱动,如果不知道自己芯片属于那个 USB IP,参考 **port** 目录下的不同 USB IP 的 readme。如果使用的 USB IP 没有支持,只能自己实现了
|
||||
- 添加 `USBH_IRQHandler=xxxx` 以及 `USB_BASE=0xxxxx` 两个 cflag 编译选项,如果没有添加则使用 `usb_hc_xxx.c` 中默认配置
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径。
|
||||
- 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径
|
||||
- 在 `usb_config.h` 中添加 `USBH_IRQHandler=xxxx` 、 `CONFIG_USBHOST_PIPE_NUM=x` 以及 `USBH_BASE=0xxxxx` 三个常规 porting 需要的宏
|
||||
|
||||
.. note:: 上述三个宏仅对 musb、dwc2 有效,因为这 2 个是通用 IP
|
||||
|
||||
- 实现 `usb_hc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
|
||||
- 调用 `usbh_initialize` 初始化 usb 硬件
|
||||
- 如果使用的是 GCC ,需要在链接脚本(ld)中添加如下代码:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 29 KiB |
@@ -31,7 +31,7 @@
|
||||
|
||||
* 最后退出保存即可。
|
||||
* 退出以后不急着编译,需要在代码中实现 `usb_dc_low_level_init` 函数。
|
||||
* 复制一份 `usb_config.h` 到自己的目录中,并实现以下内容:
|
||||
* 复制一份 `usb_config.h` 到自己的目录中,并实现以下内容, 禁止包含 `"rtthread.h"` :
|
||||
|
||||
.. figure:: img/config_file.png
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* 设置 psc 线程的线程栈以及线程优先级。
|
||||
* 最后退出保存即可。
|
||||
* 退出以后不急着编译,需要在代码中实现 `usb_hc_low_level_init` 函数。
|
||||
* 复制一份 `usb_config.h` 到自己的目录中,并实现以下内容:
|
||||
* 复制一份 `usb_config.h` 到自己的目录中,并实现以下内容, 禁止包含 `"rtthread.h"` :
|
||||
|
||||
.. figure:: img/config_file.png
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ void usb_osal_sem_delete(usb_osal_sem_t sem)
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
{
|
||||
if (timeout == USB_OSAL_WAITING_FOREVER) {
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
} else {
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,12 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
ret = xSemaphoreGive((SemaphoreHandle_t)sem);
|
||||
}
|
||||
|
||||
return (ret == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (ret == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem)
|
||||
{
|
||||
xQueueReset((QueueHandle_t)sem);
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
@@ -71,12 +76,12 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
|
||||
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
@@ -84,6 +89,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
return (usb_osal_mq_t)xQueueCreate(max_msgs, sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq)
|
||||
{
|
||||
vQueueDelete((QueueHandle_t)mq);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
@@ -94,15 +104,15 @@ int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
return (ret == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (ret == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
|
||||
{
|
||||
if (timeout == USB_OSAL_WAITING_FOREVER) {
|
||||
return (xQueueReceive((usb_osal_mq_t)mq, addr, portMAX_DELAY) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xQueueReceive((usb_osal_mq_t)mq, addr, portMAX_DELAY) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
} else {
|
||||
return (xQueueReceive((usb_osal_mq_t)mq, addr, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -ETIMEDOUT;
|
||||
return (xQueueReceive((usb_osal_mq_t)mq, addr, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
165
osal/usb_osal_rtems.c
Normal file
165
osal/usb_osal_rtems.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifdef __rtems__
|
||||
|
||||
#include "usb_osal.h"
|
||||
#include "usb_errno.h"
|
||||
#include <rtems.h>
|
||||
|
||||
#define SYS_USB_MBOX_SIZE (sizeof(void *))
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
|
||||
{
|
||||
rtems_id id = 0;
|
||||
rtems_status_code res;
|
||||
|
||||
res = rtems_task_create(
|
||||
rtems_build_name(name[0], name[1], name[2], name[3]),
|
||||
prio,
|
||||
stack_size,
|
||||
RTEMS_PREEMPT,
|
||||
0,
|
||||
&id);
|
||||
|
||||
if (res != RTEMS_SUCCESSFUL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = rtems_task_start(id, (rtems_task_entry)entry, (rtems_task_argument)args);
|
||||
|
||||
if (res != RTEMS_SUCCESSFUL) {
|
||||
rtems_task_delete(id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (usb_osal_thread_t)id;
|
||||
}
|
||||
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread)
|
||||
{
|
||||
rtems_task_delete(thread);
|
||||
}
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
|
||||
{
|
||||
rtems_id semaphore = 0;
|
||||
rtems_status_code ret = rtems_semaphore_create(
|
||||
rtems_build_name('U', 'S', 'B', 's'),
|
||||
initial_count,
|
||||
RTEMS_COUNTING_SEMAPHORE,
|
||||
0,
|
||||
&semaphore);
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem)
|
||||
{
|
||||
rtems_semaphore_delete(sem);
|
||||
}
|
||||
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
{
|
||||
rtems_status_code status;
|
||||
status = rtems_semaphore_obtain(sem, RTEMS_WAIT, timeout);
|
||||
return status == RTEMS_SUCCESSFUL ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
{
|
||||
rtems_status_code status = rtems_semaphore_release(sem);
|
||||
|
||||
return (status == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
{
|
||||
rtems_id mutex;
|
||||
rtems_status_code ret = rtems_semaphore_create(
|
||||
rtems_build_name('U', 'S', 'B', 'm'),
|
||||
1,
|
||||
RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_LOCAL,
|
||||
0,
|
||||
&mutex);
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
|
||||
{
|
||||
rtems_semaphore_delete(mutex);
|
||||
}
|
||||
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (rtems_semaphore_obtain(mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (rtems_semaphore_release(mutex) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
rtems_status_code ret;
|
||||
rtems_id mailbox = 0;
|
||||
ret = rtems_message_queue_create(
|
||||
rtems_build_name('U', 'S', 'B', 'q'),
|
||||
max_msgs,
|
||||
SYS_USB_MBOX_SIZE,
|
||||
RTEMS_DEFAULT_ATTRIBUTES,
|
||||
&mailbox);
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
rtems_status_code ret;
|
||||
ret = rtems_message_queue_send(mq, &addr, SYS_USB_MBOX_SIZE);
|
||||
return (ret == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
|
||||
{
|
||||
size_t size;
|
||||
rtems_status_code sc;
|
||||
sc = rtems_message_queue_receive(
|
||||
mq,
|
||||
addr,
|
||||
&size,
|
||||
RTEMS_WAIT,
|
||||
timeout);
|
||||
return (sc == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
uint32_t usb_osal_enter_critical_section(void)
|
||||
{
|
||||
rtems_interrupt_level pval;
|
||||
|
||||
#if RTEMS_SMP
|
||||
rtems_recursive_mutex_lock(&sys_arch_lock);
|
||||
#else
|
||||
rtems_interrupt_disable(pval);
|
||||
#endif
|
||||
return pval;
|
||||
}
|
||||
|
||||
void usb_osal_leave_critical_section(size_t flag)
|
||||
{
|
||||
#if RTEMS_SMP
|
||||
rtems_recursive_mutex_unlock(&sys_arch_lock);
|
||||
#else
|
||||
rtems_interrupt_enable(flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usb_osal_msleep(uint32_t delay)
|
||||
{
|
||||
rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(delay));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -46,9 +46,9 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
result = rt_sem_take((rt_sem_t)sem, rt_tick_from_millisecond(timeout));
|
||||
}
|
||||
if (result == -RT_ETIMEOUT) {
|
||||
ret = -ETIMEDOUT;
|
||||
ret = -USB_ERR_TIMEOUT;
|
||||
} else if (result == -RT_ERROR) {
|
||||
ret = -EINVAL;
|
||||
ret = -USB_ERR_INVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
@@ -61,6 +61,11 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
return (int)rt_sem_release((rt_sem_t)sem);
|
||||
}
|
||||
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem)
|
||||
{
|
||||
rt_sem_control((rt_sem_t)sem, RT_IPC_CMD_RESET, (void *)0);
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
{
|
||||
return (usb_osal_mutex_t)rt_mutex_create("usbh_mutex", RT_IPC_FLAG_FIFO);
|
||||
@@ -86,6 +91,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
return (usb_osal_mq_t)rt_mq_create("usbh_mq", sizeof(uintptr_t), max_msgs, RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq)
|
||||
{
|
||||
rt_mq_delete((rt_mq_t)mq);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
return rt_mq_send((rt_mq_t)mq, &addr, sizeof(uintptr_t));
|
||||
@@ -102,9 +112,9 @@ int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
|
||||
result = rt_mq_recv((rt_mq_t)mq, addr, sizeof(uintptr_t), rt_tick_from_millisecond(timeout));
|
||||
}
|
||||
if (result == -RT_ETIMEOUT) {
|
||||
ret = -ETIMEDOUT;
|
||||
ret = -USB_ERR_TIMEOUT;
|
||||
} else if (result == -RT_ERROR) {
|
||||
ret = -EINVAL;
|
||||
ret = -USB_ERR_INVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
{
|
||||
aos_mutex_t mutex = NULL;
|
||||
@@ -84,6 +89,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
return (usb_osal_mq_t)queue;
|
||||
}
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq)
|
||||
{
|
||||
aos_queue_free((aos_queue_t)mq);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
return aos_queue_send((aos_queue_t *)&mq, &addr, sizeof(uintptr_t));
|
||||
|
||||
@@ -147,31 +147,31 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
* @param[in] ep_cfg : Endpoint configuration structure pointer
|
||||
* @retval >=0 success otherwise failure
|
||||
*/
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
/*!< ep id */
|
||||
uint8_t epid = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
if (epid > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
|
||||
/**
|
||||
* If you use ch58x, you can change the EP_NUMS set to 8
|
||||
*/
|
||||
USB_LOG_ERR("Ep addr %d overflow\r\n", ep_cfg->ep_addr);
|
||||
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< ep max packet length */
|
||||
uint8_t mps = ep_cfg->ep_mps;
|
||||
uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
/*!< update ep max packet length */
|
||||
if (USB_EP_DIR_IS_IN(ep_cfg->ep_addr)) {
|
||||
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
|
||||
/*!< in */
|
||||
usb_dc_cfg.ep_in[epid].ep_enable = true;
|
||||
usb_dc_cfg.ep_in[epid].mps = mps;
|
||||
usb_dc_cfg.ep_in[epid].eptype = ep_cfg->ep_type;
|
||||
} else if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
} else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
/*!< out */
|
||||
usb_dc_cfg.ep_out[epid].ep_enable = true;
|
||||
usb_dc_cfg.ep_out[epid].mps = mps;
|
||||
usb_dc_cfg.ep_out[epid].eptype = ep_cfg->ep_type;
|
||||
usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -101,18 +101,18 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_enable = true;
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
} else {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_enable = true;
|
||||
USB_SET_TX_CTRL(ep_idx, USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
}
|
||||
|
||||
@@ -101,24 +101,24 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_enable = true;
|
||||
USBHS_DEVICE->ENDP_CONFIG |= (1 << (ep_idx + 16));
|
||||
USB_SET_RX_CTRL(ep_idx, USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0 | USBHS_EP_R_AUTOTOG);
|
||||
} else {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_enable = true;
|
||||
USBHS_DEVICE->ENDP_CONFIG |= (1 << (ep_idx));
|
||||
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0 | USBHS_EP_T_AUTOTOG);
|
||||
}
|
||||
USB_SET_MAX_LEN(ep_idx, ep_cfg->ep_mps);
|
||||
USB_SET_MAX_LEN(ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
|
||||
## AT32
|
||||
|
||||
- AT32F415xx
|
||||
- AT32F402xx、AT32F405xx、AT32F415xx、AT32F423xx、AT32F425xx、AT32F435xx、AT32F437xx
|
||||
|
||||
## GD32
|
||||
|
||||
|
||||
@@ -51,28 +51,19 @@
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#define FS_PORT 0
|
||||
#define HS_PORT 1
|
||||
|
||||
#ifndef CONFIG_USB_DWC2_PORT
|
||||
#error "please select CONFIG_USB_DWC2_PORT with FS_PORT or HS_PORT"
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_DWC2_PORT == FS_PORT
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler OTG_FS_IRQHandler
|
||||
#error "please define USBD_IRQHandler in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#ifdef STM32H7
|
||||
#define USB_BASE (0x40080000UL)
|
||||
#else
|
||||
#define USB_BASE (0x50000000UL)
|
||||
#endif
|
||||
#ifndef USBD_BASE
|
||||
#error "please define USBD_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#define USB_RAM_SIZE 1280 /* define with minimum value*/
|
||||
#ifndef CONFIG_USB_DWC2_RAM_SIZE
|
||||
#error "please define CONFIG_USB_DWC2_RAM_SIZE in usb_config.h, only support 1280 or 4096"
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_DWC2_RAM_SIZE == 1280
|
||||
/*FIFO sizes in bytes (total available memory for FIFOs is 1.25KB )*/
|
||||
#ifndef CONFIG_USB_DWC2_RX_FIFO_SIZE
|
||||
#define CONFIG_USB_DWC2_RX_FIFO_SIZE (512)
|
||||
@@ -102,29 +93,17 @@
|
||||
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (128)
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 4 /* define with minimum value*/
|
||||
#ifndef CONFIG_USBDEV_EP_NUM
|
||||
#define CONFIG_USBDEV_EP_NUM 4 /* define with minimum value*/
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler OTG_HS_IRQHandler
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x40040000UL)
|
||||
#endif
|
||||
|
||||
#define USB_RAM_SIZE 4096 /* define with minimum value*/
|
||||
#elif CONFIG_USB_DWC2_RAM_SIZE == 4096
|
||||
|
||||
#define CONFIG_USB_DWC2_DMA_ENABLE
|
||||
|
||||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
#if defined(STM32F7) || defined(STM32H7)
|
||||
#warning "if you enable dcache,please add .nocacheble section in your sct or ld or icf"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*FIFO sizes in bytes (total available memory for FIFOs is 4KB )*/
|
||||
#ifndef CONFIG_USB_DWC2_RX_FIFO_SIZE
|
||||
@@ -155,18 +134,20 @@
|
||||
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (256)
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 6 /* define with minimum value*/
|
||||
#ifndef CONFIG_USBDEV_EP_NUM
|
||||
#define CONFIG_USBDEV_EP_NUM 6 /* define with minimum value*/
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "Unsupported CONFIG_USB_DWC2_RAM_SIZE value"
|
||||
#endif
|
||||
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USB_BASE))
|
||||
#define USB_OTG_DEV ((USB_OTG_DeviceTypeDef *)(USB_BASE + USB_OTG_DEVICE_BASE))
|
||||
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_PCGCCTL_BASE)
|
||||
#define USB_OTG_INEP(i) ((USB_OTG_INEndpointTypeDef *)(USB_BASE + USB_OTG_IN_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE)))
|
||||
#define USB_OTG_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)(USB_BASE + USB_OTG_OUT_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE)))
|
||||
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
|
||||
#define USB_OTG_DEV ((USB_OTG_DeviceTypeDef *)(USBD_BASE + USB_OTG_DEVICE_BASE))
|
||||
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USBD_BASE + USB_OTG_PCGCCTL_BASE)
|
||||
#define USB_OTG_INEP(i) ((USB_OTG_INEndpointTypeDef *)(USBD_BASE + USB_OTG_IN_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE)))
|
||||
#define USB_OTG_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)(USBD_BASE + USB_OTG_OUT_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE)))
|
||||
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USBD_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
@@ -183,8 +164,8 @@ struct dwc2_ep_state {
|
||||
/* Driver state */
|
||||
USB_NOCACHE_RAM_SECTION struct dwc2_udc {
|
||||
__attribute__((aligned(32))) struct usb_setup_packet setup;
|
||||
struct dwc2_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct dwc2_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
struct dwc2_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
|
||||
struct dwc2_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
|
||||
} g_dwc2_udc;
|
||||
|
||||
static inline int dwc2_reset(void)
|
||||
@@ -215,8 +196,6 @@ static inline int dwc2_core_init(void)
|
||||
{
|
||||
int ret;
|
||||
#if defined(CONFIG_USB_HS)
|
||||
USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
|
||||
|
||||
/* Init The ULPI Interface */
|
||||
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
|
||||
|
||||
@@ -231,8 +210,6 @@ static inline int dwc2_core_init(void)
|
||||
|
||||
/* Reset after a PHY select */
|
||||
ret = dwc2_reset();
|
||||
/* Activate the USB Transceiver */
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -575,6 +552,7 @@ int usb_dc_init(void)
|
||||
endpoints = ((USB_OTG_GLB->GHWCFG2 & (0x0f << 10)) >> 10) + 1;
|
||||
|
||||
USB_LOG_INFO("========== dwc2 udc params ==========\r\n");
|
||||
USB_LOG_INFO("GCCFG:%08x\r\n", USB_OTG_GLB->GCCFG);
|
||||
USB_LOG_INFO("CID:%08x\r\n", USB_OTG_GLB->CID);
|
||||
USB_LOG_INFO("GSNPSID:%08x\r\n", USB_OTG_GLB->GSNPSID);
|
||||
USB_LOG_INFO("GHWCFG1:%08x\r\n", USB_OTG_GLB->GHWCFG1);
|
||||
@@ -583,69 +561,54 @@ int usb_dc_init(void)
|
||||
USB_LOG_INFO("GHWCFG4:%08x\r\n", USB_OTG_GLB->GHWCFG4);
|
||||
|
||||
USB_LOG_INFO("dwc2 fsphy type:%d, hsphy type:%d, dma support:%d\r\n", fsphy_type, hsphy_type, dma_support);
|
||||
USB_LOG_INFO("dwc2 has %d endpoints, default config: %d endpoints\r\n", endpoints, USB_NUM_BIDIR_ENDPOINTS);
|
||||
USB_LOG_INFO("dwc2 has %d endpoints, default config: %d endpoints\r\n", endpoints, CONFIG_USBDEV_EP_NUM);
|
||||
USB_LOG_INFO("=================================\r\n");
|
||||
|
||||
if (endpoints < CONFIG_USBDEV_EP_NUM) {
|
||||
USB_LOG_ERR("dwc2 has less endpoints than config, please check\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((hsphy_type == 0) && (CONFIG_USB_DWC2_RAM_SIZE != 1280)) {
|
||||
USB_LOG_ERR("dwc2 hsphy type is 0, but ram size is not 1280, please check\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
|
||||
|
||||
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
|
||||
|
||||
/* This is vendor register */
|
||||
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf();
|
||||
|
||||
ret = dwc2_core_init();
|
||||
|
||||
/* Force Device Mode*/
|
||||
dwc2_set_mode(USB_OTG_MODE_DEVICE);
|
||||
|
||||
/* B-peripheral session valid override enable */
|
||||
// USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
// USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
|
||||
for (uint8_t i = 0U; i < 15U; i++) {
|
||||
USB_OTG_GLB->DIEPTXF[i] = 0U;
|
||||
}
|
||||
|
||||
#if defined(STM32F7) || defined(STM32H7) || defined(STM32L4)
|
||||
#ifdef CONFIG_DWC2_VBUS_SENSING_ENABLE
|
||||
/* Enable HW VBUS sensing */
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_VBDEN;
|
||||
#else
|
||||
/* Deactivate VBUS Sensing B */
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBDEN;
|
||||
|
||||
/* B-peripheral session valid override enable */
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
#endif
|
||||
#else
|
||||
#ifdef CONFIG_DWC2_VBUS_SENSING_ENABLE
|
||||
/* Enable HW VBUS sensing */
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS;
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
|
||||
#else
|
||||
#ifdef CONFIG_DWC2_GD32
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_VBUSASEN;
|
||||
#else
|
||||
/*
|
||||
* Disable HW VBUS sensing. VBUS is internally considered to be always
|
||||
* at VBUS-Valid level (5V).
|
||||
*/
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
/* Restart the Phy Clock */
|
||||
USB_OTG_PCGCCTL = 0U;
|
||||
|
||||
/* Device mode configuration */
|
||||
USB_OTG_DEV->DCFG |= DCFG_FRAME_INTERVAL_80;
|
||||
|
||||
#if CONFIG_USB_DWC2_PORT == HS_PORT
|
||||
/* Device speed configuration */
|
||||
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DSPD;
|
||||
#if defined(CONFIG_USB_HS)
|
||||
/* Set Core speed to High speed mode */
|
||||
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH;
|
||||
#else
|
||||
|
||||
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
|
||||
#endif
|
||||
#else
|
||||
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
|
||||
if (hsphy_type == 0) {
|
||||
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
|
||||
} else {
|
||||
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = dwc2_flush_txfifo(0x10U);
|
||||
@@ -692,19 +655,19 @@ int usb_dc_init(void)
|
||||
dwc2_set_txfifo(1, CONFIG_USB_DWC2_TX1_FIFO_SIZE / 4);
|
||||
dwc2_set_txfifo(2, CONFIG_USB_DWC2_TX2_FIFO_SIZE / 4);
|
||||
dwc2_set_txfifo(3, CONFIG_USB_DWC2_TX3_FIFO_SIZE / 4);
|
||||
#if USB_NUM_BIDIR_ENDPOINTS > 4
|
||||
#if CONFIG_USBDEV_EP_NUM > 4
|
||||
dwc2_set_txfifo(4, CONFIG_USB_DWC2_TX4_FIFO_SIZE / 4);
|
||||
#endif
|
||||
#if USB_NUM_BIDIR_ENDPOINTS > 5
|
||||
#if CONFIG_USBDEV_EP_NUM > 5
|
||||
dwc2_set_txfifo(5, CONFIG_USB_DWC2_TX5_FIFO_SIZE / 4);
|
||||
#endif
|
||||
#if USB_NUM_BIDIR_ENDPOINTS > 6
|
||||
#if CONFIG_USBDEV_EP_NUM > 6
|
||||
dwc2_set_txfifo(6, CONFIG_USB_DWC2_TX6_FIFO_SIZE / 4);
|
||||
#endif
|
||||
#if USB_NUM_BIDIR_ENDPOINTS > 7
|
||||
#if CONFIG_USBDEV_EP_NUM > 7
|
||||
dwc2_set_txfifo(7, CONFIG_USB_DWC2_TX7_FIFO_SIZE / 4);
|
||||
#endif
|
||||
#if USB_NUM_BIDIR_ENDPOINTS > 8
|
||||
#if CONFIG_USBDEV_EP_NUM > 8
|
||||
dwc2_set_txfifo(8, CONFIG_USB_DWC2_TX8_FIFO_SIZE / 4);
|
||||
#endif
|
||||
USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
|
||||
@@ -760,36 +723,36 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return speed;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
|
||||
USB_LOG_ERR("Ep addr %d overflow\r\n", ep_cfg->ep_addr);
|
||||
if (ep_idx > (CONFIG_USBDEV_EP_NUM - 1)) {
|
||||
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_dwc2_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_dwc2_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_dwc2_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
|
||||
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & (uint32_t)(1UL << (16 + ep_idx));
|
||||
|
||||
if ((USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP) == 0) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (ep_cfg->ep_mps & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)ep_cfg->ep_type << 18) |
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DOEPCTL_USBAEP;
|
||||
}
|
||||
} else {
|
||||
g_dwc2_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_dwc2_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_dwc2_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
|
||||
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << ep_idx);
|
||||
|
||||
if ((USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0) {
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= (ep_cfg->ep_mps & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)ep_cfg->ep_type << 18) | (ep_idx << 22) |
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | (ep_idx << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
}
|
||||
@@ -1145,7 +1108,7 @@ void USBD_IRQHandler(void)
|
||||
dwc2_flush_txfifo(0x10U);
|
||||
dwc2_flush_rxfifo();
|
||||
|
||||
for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
|
||||
for (uint8_t i = 0U; i < CONFIG_USBDEV_EP_NUM; i++) {
|
||||
if (i == 0U) {
|
||||
USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
|
||||
USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
|
||||
@@ -1189,7 +1152,7 @@ void USBD_IRQHandler(void)
|
||||
daintmask = USB_OTG_DEV->DAINTMSK;
|
||||
daintmask >>= 16;
|
||||
|
||||
for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
|
||||
for (ep_idx = 1; ep_idx < CONFIG_USBDEV_EP_NUM; ep_idx++) {
|
||||
if ((BIT(ep_idx) & ~daintmask) || (g_dwc2_udc.out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
|
||||
continue;
|
||||
if (!(USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP))
|
||||
@@ -1211,7 +1174,7 @@ void USBD_IRQHandler(void)
|
||||
daintmask = USB_OTG_DEV->DAINTMSK;
|
||||
daintmask >>= 16;
|
||||
|
||||
for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
|
||||
for (ep_idx = 1; ep_idx < CONFIG_USBDEV_EP_NUM; ep_idx++) {
|
||||
if (((BIT(ep_idx) & ~daintmask)) || (g_dwc2_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -1705,4 +1705,7 @@ typedef struct
|
||||
#define USB_MASK_HALT_HC_INT(chnum) (USB_OTG_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINTMSK_CHHM)
|
||||
#define USB_UNMASK_HALT_HC_INT(chnum) (USB_OTG_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM)
|
||||
#define CLEAR_HC_INT(chnum, __INTERRUPT__) (USB_OTG_HC(chnum)->HCINT = (__INTERRUPT__))
|
||||
|
||||
uint32_t usbd_get_dwc2_gccfg_conf(void);
|
||||
uint32_t usbh_get_dwc2_gccfg_conf(void);
|
||||
#endif
|
||||
|
||||
47
port/dwc2/usb_glue_at.c
Normal file
47
port/dwc2/usb_glue_at.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "usb_config.h"
|
||||
#include "stdint.h"
|
||||
#include "usb_dwc2_reg.h"
|
||||
|
||||
/* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example:
|
||||
*
|
||||
* usbx->gccfg_bit.pwrdown = TRUE;
|
||||
* usbx->gccfg_bit.avalidsesen = TRUE;
|
||||
* usbx->gccfg_bit.bvalidsesen = TRUE;
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t usbd_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_HS
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#else
|
||||
// AT32F415
|
||||
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
|
||||
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
|
||||
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
|
||||
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
|
||||
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
|
||||
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
|
||||
#else
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t usbh_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_DWC2_ULPI_PHY
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#else
|
||||
// AT32F415
|
||||
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
|
||||
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
|
||||
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
|
||||
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
|
||||
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
|
||||
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
|
||||
#else
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
27
port/dwc2/usb_glue_gd.c
Normal file
27
port/dwc2/usb_glue_gd.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "usb_config.h"
|
||||
#include "stdint.h"
|
||||
#include "usb_dwc2_reg.h"
|
||||
|
||||
/* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example:
|
||||
*
|
||||
* usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t usbd_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_HS
|
||||
return 0;
|
||||
#else
|
||||
return ((1 << 16) | (1 << 18) | (1 << 19));
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t usbh_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_DWC2_ULPI_PHY
|
||||
return 0;
|
||||
#else
|
||||
return ((1 << 16) | (1 << 18) | (1 << 19));
|
||||
#endif
|
||||
}
|
||||
46
port/dwc2/usb_glue_st.c
Normal file
46
port/dwc2/usb_glue_st.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "usb_config.h"
|
||||
#include "stdint.h"
|
||||
#include "usb_dwc2_reg.h"
|
||||
|
||||
/* you can find this config in function: USB_DevInit, file:stm32xxx_ll_usb.c, for example:
|
||||
*
|
||||
* USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
* USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
|
||||
* USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
|
||||
* USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t usbd_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_HS
|
||||
return 0;
|
||||
#else
|
||||
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
|
||||
/* B-peripheral session valid override enable */
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
return (1 << 16);
|
||||
#else
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t usbh_get_dwc2_gccfg_conf(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_DWC2_ULPI_PHY
|
||||
return 0;
|
||||
#else
|
||||
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBD_BASE))
|
||||
/* B-peripheral session valid override enable */
|
||||
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
|
||||
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
|
||||
return (1 << 16);
|
||||
#else
|
||||
return ((1 << 16) | (1 << 21));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -8,46 +8,31 @@
|
||||
#include "usb_dwc2_reg.h"
|
||||
|
||||
#ifndef USBH_IRQHandler
|
||||
#define USBH_IRQHandler OTG_HS_IRQHandler
|
||||
#error "please define USBH_IRQHandler in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x40040000UL)
|
||||
#ifndef USBH_BASE
|
||||
#error "please define USBH_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USBHOST_PIPE_NUM 12
|
||||
#endif
|
||||
|
||||
#if defined(STM32F7) || defined(STM32H7)
|
||||
#warning please check your buf addr is not in tcm and use nocache ram.
|
||||
#endif
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USBH_BASE))
|
||||
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USBH_BASE + USB_OTG_PCGCCTL_BASE)
|
||||
#define USB_OTG_HPRT *(__IO uint32_t *)((uint32_t)USBH_BASE + USB_OTG_HOST_PORT_BASE)
|
||||
#define USB_OTG_HOST ((USB_OTG_HostTypeDef *)(USBH_BASE + USB_OTG_HOST_BASE))
|
||||
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USBH_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
|
||||
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USBH_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
||||
|
||||
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USB_BASE))
|
||||
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_PCGCCTL_BASE)
|
||||
#define USB_OTG_HPRT *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_HOST_PORT_BASE)
|
||||
#define USB_OTG_HOST ((USB_OTG_HostTypeDef *)(USB_BASE + USB_OTG_HOST_BASE))
|
||||
#define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USB_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE)))
|
||||
#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE))
|
||||
|
||||
struct dwc2_pipe {
|
||||
uint8_t dev_addr;
|
||||
uint8_t ep_addr;
|
||||
uint8_t ep_type;
|
||||
uint8_t ep_interval;
|
||||
uint8_t speed;
|
||||
uint16_t ep_mps;
|
||||
uint8_t data_pid;
|
||||
uint8_t chidx;
|
||||
volatile uint8_t ep0_state;
|
||||
struct dwc2_chan {
|
||||
uint8_t ep0_state;
|
||||
uint16_t num_packets;
|
||||
uint32_t xferlen;
|
||||
uint8_t chidx;
|
||||
bool inuse;
|
||||
uint32_t xfrd;
|
||||
int errorcode;
|
||||
volatile bool waiter;
|
||||
usb_osal_sem_t waitsem;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_urb *urb;
|
||||
uint32_t iso_frame_idx;
|
||||
};
|
||||
@@ -56,7 +41,7 @@ struct dwc2_hcd {
|
||||
volatile bool port_csc;
|
||||
volatile bool port_pec;
|
||||
volatile bool port_occ;
|
||||
struct dwc2_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM];
|
||||
struct dwc2_chan chan_pool[CONFIG_USBHOST_PIPE_NUM];
|
||||
} g_dwc2_hcd;
|
||||
|
||||
#define DWC2_EP0_STATE_SETUP 0
|
||||
@@ -93,7 +78,6 @@ static inline int dwc2_core_init(void)
|
||||
{
|
||||
int ret;
|
||||
#if defined(CONFIG_USB_DWC2_ULPI_PHY)
|
||||
USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
|
||||
/* Init The ULPI Interface */
|
||||
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
|
||||
|
||||
@@ -108,9 +92,6 @@ static inline int dwc2_core_init(void)
|
||||
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
|
||||
/* Reset after a PHY select */
|
||||
ret = dwc2_reset();
|
||||
|
||||
/* Activate the USB Transceiver */
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -173,7 +154,7 @@ static inline void dwc2_drivebus(uint8_t state)
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
|
||||
static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
@@ -236,7 +217,7 @@ static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
|
||||
}
|
||||
|
||||
/* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/
|
||||
static inline void dwc2_pipe_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
|
||||
static inline void dwc2_chan_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
|
||||
{
|
||||
__IO uint32_t tmpreg;
|
||||
uint8_t is_oddframe;
|
||||
@@ -361,13 +342,13 @@ static inline uint32_t dwc2_get_glb_intstatus(void)
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
static int dwc2_pipe_alloc(void)
|
||||
static int dwc2_chan_alloc(void)
|
||||
{
|
||||
int chidx;
|
||||
|
||||
for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
|
||||
if (!g_dwc2_hcd.pipe_pool[chidx].inuse) {
|
||||
g_dwc2_hcd.pipe_pool[chidx].inuse = true;
|
||||
if (!g_dwc2_hcd.chan_pool[chidx].inuse) {
|
||||
g_dwc2_hcd.chan_pool[chidx].inuse = true;
|
||||
return chidx;
|
||||
}
|
||||
}
|
||||
@@ -375,9 +356,9 @@ static int dwc2_pipe_alloc(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void dwc2_pipe_free(struct dwc2_pipe *pipe)
|
||||
static void dwc2_chan_free(struct dwc2_chan *chan)
|
||||
{
|
||||
pipe->inuse = false;
|
||||
chan->inuse = false;
|
||||
}
|
||||
|
||||
static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size)
|
||||
@@ -403,46 +384,60 @@ static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, u
|
||||
return num_packets;
|
||||
}
|
||||
|
||||
static void dwc2_control_pipe_init(struct dwc2_pipe *chan, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
static void dwc2_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct dwc2_chan *chan;
|
||||
|
||||
chan = &g_dwc2_hcd.chan_pool[chidx];
|
||||
|
||||
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(8, 0x00, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed);
|
||||
dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
|
||||
chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed);
|
||||
dwc2_pipe_transfer(chan->chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed);
|
||||
dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed);
|
||||
dwc2_pipe_transfer(chan->chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) /* fill out status */
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed);
|
||||
dwc2_pipe_transfer(chan->chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
chan->num_packets = dwc2_calculate_packet_num(0, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc2_bulk_intr_pipe_init(struct dwc2_pipe *chan, uint8_t *buffer, uint32_t buflen)
|
||||
static void dwc2_bulk_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
|
||||
struct dwc2_chan *chan;
|
||||
|
||||
chan = &g_dwc2_hcd.chan_pool[chidx];
|
||||
|
||||
chan->num_packets = dwc2_calculate_packet_num(buflen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle);
|
||||
}
|
||||
|
||||
static void dwc2_iso_pipe_init(struct dwc2_pipe *chan, struct usbh_iso_frame_packet *iso_packet)
|
||||
static void dwc2_iso_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet)
|
||||
{
|
||||
chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, chan->ep_addr, chan->ep_mps, &chan->xferlen);
|
||||
dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
|
||||
struct dwc2_chan *chan;
|
||||
|
||||
chan = &g_dwc2_hcd.chan_pool[chidx];
|
||||
|
||||
chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
|
||||
dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
|
||||
dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
|
||||
}
|
||||
|
||||
__WEAK void usb_hc_low_level_init(void)
|
||||
@@ -456,12 +451,13 @@ int usb_hc_init(void)
|
||||
memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd));
|
||||
|
||||
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
|
||||
g_dwc2_hcd.pipe_pool[chidx].waitsem = usb_osal_sem_create(0);
|
||||
g_dwc2_hcd.chan_pool[chidx].waitsem = usb_osal_sem_create(0);
|
||||
}
|
||||
|
||||
usb_hc_low_level_init();
|
||||
|
||||
USB_LOG_INFO("========== dwc2 hcd params ==========\r\n");
|
||||
USB_LOG_INFO("GCCFG:%08x\r\n", USB_OTG_GLB->GCCFG);
|
||||
USB_LOG_INFO("CID:%08x\r\n", USB_OTG_GLB->CID);
|
||||
USB_LOG_INFO("GSNPSID:%08x\r\n", USB_OTG_GLB->GSNPSID);
|
||||
USB_LOG_INFO("GHWCFG1:%08x\r\n", USB_OTG_GLB->GHWCFG1);
|
||||
@@ -479,7 +475,11 @@ int usb_hc_init(void)
|
||||
|
||||
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
|
||||
|
||||
/* This is vendor register */
|
||||
USB_OTG_GLB->GCCFG = usbh_get_dwc2_gccfg_conf();
|
||||
|
||||
ret = dwc2_core_init();
|
||||
|
||||
/* Force Host Mode*/
|
||||
dwc2_set_mode(USB_OTG_MODE_HOST);
|
||||
usb_osal_msleep(50);
|
||||
@@ -487,21 +487,6 @@ int usb_hc_init(void)
|
||||
/* Restart the Phy Clock */
|
||||
USB_OTG_PCGCCTL = 0U;
|
||||
|
||||
#if defined(STM32F7) || defined(STM32H7)
|
||||
/* Disable HW VBUS sensing */
|
||||
USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_VBDEN);
|
||||
/* Disable Battery chargin detector */
|
||||
USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
|
||||
#else
|
||||
/*
|
||||
* Disable HW VBUS sensing. VBUS is internally considered to be always
|
||||
* at VBUS-Valid level (5V).
|
||||
*/
|
||||
USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
|
||||
USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
|
||||
#endif
|
||||
|
||||
/* Set default Max speed support */
|
||||
USB_OTG_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
|
||||
|
||||
@@ -540,6 +525,57 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_hc_deinit(void)
|
||||
{
|
||||
volatile uint32_t count = 0U;
|
||||
uint32_t value;
|
||||
|
||||
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
|
||||
|
||||
dwc2_flush_txfifo(0x10U);
|
||||
dwc2_flush_rxfifo();
|
||||
|
||||
/* Flush out any leftover queued requests. */
|
||||
for (uint32_t i = 0U; i <= 15U; i++) {
|
||||
value = USB_OTG_HC(i)->HCCHAR;
|
||||
value |= USB_OTG_HCCHAR_CHDIS;
|
||||
value &= ~USB_OTG_HCCHAR_CHENA;
|
||||
value &= ~USB_OTG_HCCHAR_EPDIR;
|
||||
USB_OTG_HC(i)->HCCHAR = value;
|
||||
}
|
||||
|
||||
/* Halt all channels to put them into a known state. */
|
||||
for (uint32_t i = 0U; i <= 15U; i++) {
|
||||
value = USB_OTG_HC(i)->HCCHAR;
|
||||
value |= USB_OTG_HCCHAR_CHDIS;
|
||||
value |= USB_OTG_HCCHAR_CHENA;
|
||||
value &= ~USB_OTG_HCCHAR_EPDIR;
|
||||
USB_OTG_HC(i)->HCCHAR = value;
|
||||
|
||||
do {
|
||||
if (++count > 1000U) {
|
||||
return -USB_ERR_TIMEOUT;
|
||||
}
|
||||
} while ((USB_OTG_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
|
||||
}
|
||||
|
||||
/* Disable all interrupts. */
|
||||
USB_OTG_GLB->GINTMSK = 0U;
|
||||
|
||||
/* Clear any pending Host interrupts */
|
||||
USB_OTG_HOST->HAINT = 0xFFFFFFFFU;
|
||||
USB_OTG_GLB->GINTSTS = 0xFFFFFFFFU;
|
||||
|
||||
dwc2_drivebus(0);
|
||||
usb_osal_msleep(200);
|
||||
|
||||
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
|
||||
usb_osal_sem_delete(g_dwc2_hcd.chan_pool[chidx].waitsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t usbh_get_frame_number(void)
|
||||
{
|
||||
return (USB_OTG_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
|
||||
@@ -563,7 +599,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
@@ -573,7 +609,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_DESCRIPTOR:
|
||||
@@ -588,7 +624,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
switch (setup->bRequest) {
|
||||
case HUB_REQUEST_CLEAR_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
@@ -612,12 +648,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_PORT_FEATURE_C_RESET:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
@@ -631,12 +667,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_STATUS:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
hprt0 = USB_OTG_HPRT;
|
||||
|
||||
@@ -681,137 +717,58 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult)
|
||||
{
|
||||
struct dwc2_pipe *chan;
|
||||
|
||||
chan = (struct dwc2_pipe *)pipe;
|
||||
|
||||
chan->dev_addr = dev_addr;
|
||||
chan->ep_mps = ep_mps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
|
||||
{
|
||||
struct dwc2_pipe *chan;
|
||||
int chidx;
|
||||
usb_osal_sem_t waitsem;
|
||||
|
||||
chidx = dwc2_pipe_alloc();
|
||||
if (chidx == -1) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
chan = &g_dwc2_hcd.pipe_pool[chidx];
|
||||
|
||||
/* store variables */
|
||||
waitsem = chan->waitsem;
|
||||
|
||||
memset(chan, 0, sizeof(struct dwc2_pipe));
|
||||
|
||||
chan->chidx = chidx;
|
||||
chan->ep_addr = ep_cfg->ep_addr;
|
||||
chan->ep_type = ep_cfg->ep_type;
|
||||
chan->ep_mps = ep_cfg->ep_mps;
|
||||
chan->ep_interval = ep_cfg->ep_interval;
|
||||
chan->speed = ep_cfg->hport->speed;
|
||||
chan->dev_addr = ep_cfg->hport->dev_addr;
|
||||
chan->hport = ep_cfg->hport;
|
||||
|
||||
if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
chan->data_pid = HC_PID_DATA1;
|
||||
} else {
|
||||
dwc2_pipe_init(chidx, chan->dev_addr, ep_cfg->ep_addr, ep_cfg->ep_type, ep_cfg->ep_mps, chan->speed);
|
||||
chan->data_pid = HC_PID_DATA0;
|
||||
}
|
||||
|
||||
if (chan->speed == USB_SPEED_HIGH) {
|
||||
chan->ep_interval = (1 << (chan->ep_interval - 1));
|
||||
}
|
||||
|
||||
/* restore variables */
|
||||
chan->inuse = true;
|
||||
chan->waitsem = waitsem;
|
||||
|
||||
*pipe = (usbh_pipe_t)chan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_free(usbh_pipe_t pipe)
|
||||
{
|
||||
struct dwc2_pipe *chan;
|
||||
struct usbh_urb *urb;
|
||||
|
||||
chan = (struct dwc2_pipe *)pipe;
|
||||
|
||||
if (!chan) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
urb = chan->urb;
|
||||
|
||||
if (urb) {
|
||||
usbh_kill_urb(urb);
|
||||
}
|
||||
|
||||
dwc2_pipe_free(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_submit_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct dwc2_pipe *pipe;
|
||||
struct dwc2_chan *chan;
|
||||
size_t flags;
|
||||
int ret = 0;
|
||||
int chidx;
|
||||
|
||||
if (!urb || !urb->pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hport || !urb->ep) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
/* dma addr must be aligned 4 bytes */
|
||||
if ((((uint32_t)urb->setup) & 0x03) || (((uint32_t)urb->transfer_buffer) & 0x03)) {
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !pipe->hport->connected) {
|
||||
return -ENODEV;
|
||||
if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !urb->hport->connected) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (pipe->urb) {
|
||||
return -EBUSY;
|
||||
if (urb->errorcode == -USB_ERR_BUSY) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
pipe->waiter = false;
|
||||
pipe->xfrd = 0;
|
||||
pipe->urb = urb;
|
||||
pipe->errorcode = -EBUSY;
|
||||
urb->errorcode = -EBUSY;
|
||||
chidx = dwc2_chan_alloc();
|
||||
if (chidx == -1) {
|
||||
usb_osal_leave_critical_section(flags);
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
chan = &g_dwc2_hcd.chan_pool[chidx];
|
||||
chan->chidx = chidx;
|
||||
chan->urb = urb;
|
||||
|
||||
urb->hcpriv = chan;
|
||||
urb->errorcode = -USB_ERR_BUSY;
|
||||
urb->actual_length = 0;
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
pipe->waiter = true;
|
||||
}
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
switch (pipe->ep_type) {
|
||||
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
pipe->ep0_state = DWC2_EP0_STATE_SETUP;
|
||||
dwc2_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
chan->ep0_state = DWC2_EP0_STATE_SETUP;
|
||||
dwc2_control_urb_init(chidx, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
dwc2_bulk_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
dwc2_bulk_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
pipe->iso_frame_idx = 0;
|
||||
dwc2_iso_pipe_init(pipe, &urb->iso_packet[pipe->iso_frame_idx]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -819,41 +776,47 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
/* wait until timeout or sem give */
|
||||
ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
|
||||
ret = usb_osal_sem_take(chan->waitsem, urb->timeout);
|
||||
if (ret < 0) {
|
||||
goto errout_timeout;
|
||||
}
|
||||
|
||||
urb->timeout = 0;
|
||||
ret = urb->errorcode;
|
||||
/* we can free chan when waitsem is done */
|
||||
dwc2_chan_free(chan);
|
||||
}
|
||||
return ret;
|
||||
errout_timeout:
|
||||
pipe->waiter = false;
|
||||
urb->timeout = 0;
|
||||
usbh_kill_urb(urb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_kill_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct dwc2_pipe *pipe;
|
||||
struct dwc2_chan *chan;
|
||||
size_t flags;
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
if (!urb || !pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hcpriv) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
dwc2_halt(pipe->chidx);
|
||||
CLEAR_HC_INT(pipe->chidx, USB_OTG_HCINT_CHH);
|
||||
pipe->urb = NULL;
|
||||
chan = (struct dwc2_chan *)urb->hcpriv;
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
urb->errorcode = -ESHUTDOWN;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
dwc2_halt(chan->chidx);
|
||||
CLEAR_HC_INT(chan->chidx, USB_OTG_HCINT_CHH);
|
||||
|
||||
chan->urb = NULL;
|
||||
urb->hcpriv = NULL;
|
||||
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
urb->errorcode = -USB_ERR_SHUTDOWN;
|
||||
usb_osal_sem_give(chan->waitsem);
|
||||
} else {
|
||||
dwc2_chan_free(chan);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
@@ -861,16 +824,19 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dwc2_pipe_waitup(struct dwc2_pipe *pipe)
|
||||
static inline void dwc2_urb_waitup(struct usbh_urb *urb)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct dwc2_chan *chan;
|
||||
|
||||
urb = pipe->urb;
|
||||
pipe->urb = NULL;
|
||||
chan = (struct dwc2_chan *)urb->hcpriv;
|
||||
chan->urb = NULL;
|
||||
urb->hcpriv = NULL;
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
usb_osal_sem_give(chan->waitsem);
|
||||
} else {
|
||||
dwc2_chan_free(chan);
|
||||
}
|
||||
|
||||
if (urb->complete) {
|
||||
@@ -885,214 +851,191 @@ static inline void dwc2_pipe_waitup(struct dwc2_pipe *pipe)
|
||||
static void dwc2_inchan_irq_handler(uint8_t ch_num)
|
||||
{
|
||||
uint32_t chan_intstatus;
|
||||
struct dwc2_pipe *chan;
|
||||
struct dwc2_chan *chan;
|
||||
struct usbh_urb *urb;
|
||||
|
||||
chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK);
|
||||
|
||||
chan = &g_dwc2_hcd.pipe_pool[ch_num];
|
||||
chan = &g_dwc2_hcd.chan_pool[ch_num];
|
||||
urb = chan->urb;
|
||||
//printf("s1:%08x\r\n", chan_intstatus);
|
||||
|
||||
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
|
||||
chan->errorcode = 0;
|
||||
urb->errorcode = 0;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
|
||||
chan->errorcode = -EPERM;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
|
||||
chan->errorcode = -EAGAIN;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
|
||||
chan->errorcode = -EAGAIN;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_BABBLE;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
|
||||
chan->errorcode = -EPIPE;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_DT;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
|
||||
USB_MASK_HALT_HC_INT(ch_num);
|
||||
|
||||
if (urb == NULL) {
|
||||
goto chhout;
|
||||
}
|
||||
|
||||
urb->errorcode = chan->errorcode;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (urb->errorcode == 0) {
|
||||
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */
|
||||
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */
|
||||
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
|
||||
|
||||
chan->xfrd += count;
|
||||
urb->actual_length += count;
|
||||
|
||||
if ((has_used_packets % 2) == 1) /* toggle in odd numbers */
|
||||
{
|
||||
if (chan->data_pid == HC_PID_DATA0) {
|
||||
chan->data_pid = HC_PID_DATA1;
|
||||
if (urb->data_toggle == HC_PID_DATA0) {
|
||||
urb->data_toggle = HC_PID_DATA1;
|
||||
} else {
|
||||
chan->data_pid = HC_PID_DATA0;
|
||||
urb->data_toggle = HC_PID_DATA0;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan->ep_type == 0x00) {
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
if (chan->ep0_state == DWC2_EP0_STATE_INDATA) {
|
||||
chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS;
|
||||
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) {
|
||||
chan->ep0_state = DWC2_EP0_STATE_SETUP;
|
||||
urb->actual_length = chan->xfrd;
|
||||
dwc2_pipe_waitup(chan);
|
||||
}
|
||||
} else if (chan->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
urb->iso_packet[chan->iso_frame_idx].actual_length = chan->xfrd;
|
||||
urb->iso_packet[chan->iso_frame_idx].errorcode = urb->errorcode;
|
||||
chan->iso_frame_idx++;
|
||||
|
||||
if (chan->iso_frame_idx == urb->num_of_iso_packets) {
|
||||
dwc2_pipe_waitup(chan);
|
||||
} else {
|
||||
dwc2_iso_pipe_init(chan, &urb->iso_packet[chan->iso_frame_idx]);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
} else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
} else {
|
||||
urb->actual_length = chan->xfrd;
|
||||
dwc2_pipe_waitup(chan);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
} else if (urb->errorcode == -EAGAIN) {
|
||||
} else if (urb->errorcode == -USB_ERR_NAK) {
|
||||
/* re-activate the channel */
|
||||
if (chan->ep_type == 0x00) {
|
||||
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if ((chan->ep_type == 0x03) || (chan->ep_type == 0x02)) {
|
||||
dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) {
|
||||
dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
dwc2_pipe_waitup(chan);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
chhout:
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc2_outchan_irq_handler(uint8_t ch_num)
|
||||
{
|
||||
uint32_t chan_intstatus;
|
||||
struct dwc2_pipe *chan;
|
||||
struct dwc2_chan *chan;
|
||||
struct usbh_urb *urb;
|
||||
uint16_t buflen;
|
||||
|
||||
chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK);
|
||||
|
||||
chan = &g_dwc2_hcd.pipe_pool[ch_num];
|
||||
chan = &g_dwc2_hcd.chan_pool[ch_num];
|
||||
urb = chan->urb;
|
||||
//printf("s2:%08x\r\n", chan_intstatus);
|
||||
|
||||
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
|
||||
chan->errorcode = 0;
|
||||
urb->errorcode = 0;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
|
||||
dwc2_halt(ch_num);
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) {
|
||||
chan->errorcode = -EPERM;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
|
||||
chan->errorcode = -EAGAIN;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) {
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) {
|
||||
chan->errorcode = -EAGAIN;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_BABBLE;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) {
|
||||
chan->errorcode = -EPIPE;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) {
|
||||
chan->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_DT;
|
||||
USB_UNMASK_HALT_HC_INT(ch_num);
|
||||
dwc2_halt(ch_num);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
|
||||
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
|
||||
USB_MASK_HALT_HC_INT(ch_num);
|
||||
|
||||
if (urb == NULL) {
|
||||
goto chhout;
|
||||
}
|
||||
|
||||
urb->errorcode = chan->errorcode;
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (urb->errorcode == 0) {
|
||||
uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* how many size has sent */
|
||||
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */
|
||||
|
||||
chan->xfrd += count;
|
||||
uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* last packet size */
|
||||
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
|
||||
|
||||
urb->actual_length += (has_used_packets - 1) * USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) + count; //the same with urb->actual_length += chan->xferlen;
|
||||
|
||||
if (has_used_packets % 2) /* toggle in odd numbers */
|
||||
{
|
||||
if (chan->data_pid == HC_PID_DATA0) {
|
||||
chan->data_pid = HC_PID_DATA1;
|
||||
if (urb->data_toggle == HC_PID_DATA0) {
|
||||
urb->data_toggle = HC_PID_DATA1;
|
||||
} else {
|
||||
chan->data_pid = HC_PID_DATA0;
|
||||
urb->data_toggle = HC_PID_DATA0;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan->ep_type == 0x00) {
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) {
|
||||
if (urb->setup->wLength) {
|
||||
if (urb->setup->bmRequestType & 0x80) {
|
||||
@@ -1103,42 +1046,29 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
|
||||
} else {
|
||||
chan->ep0_state = DWC2_EP0_STATE_INSTATUS;
|
||||
}
|
||||
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) {
|
||||
chan->ep0_state = DWC2_EP0_STATE_INSTATUS;
|
||||
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) {
|
||||
chan->ep0_state = DWC2_EP0_STATE_SETUP;
|
||||
urb->actual_length = chan->xfrd;
|
||||
dwc2_pipe_waitup(chan);
|
||||
}
|
||||
} else if (chan->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
urb->iso_packet[chan->iso_frame_idx].actual_length = chan->xfrd;
|
||||
urb->iso_packet[chan->iso_frame_idx].errorcode = urb->errorcode;
|
||||
chan->iso_frame_idx++;
|
||||
|
||||
if (chan->iso_frame_idx == urb->num_of_iso_packets) {
|
||||
dwc2_pipe_waitup(chan);
|
||||
} else {
|
||||
dwc2_iso_pipe_init(chan, &urb->iso_packet[chan->iso_frame_idx]);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
} else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
} else {
|
||||
urb->actual_length = chan->xfrd;
|
||||
dwc2_pipe_waitup(chan);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
} else if (urb->errorcode == -EAGAIN) {
|
||||
} else if (urb->errorcode == -USB_ERR_NAK) {
|
||||
/* re-activate the channel */
|
||||
if (chan->ep_type == 0x00) {
|
||||
dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if ((chan->ep_type == 0x03) || (chan->ep_type == 0x02)) {
|
||||
dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) {
|
||||
dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
dwc2_pipe_waitup(chan);
|
||||
dwc2_urb_waitup(urb);
|
||||
}
|
||||
chhout:
|
||||
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
|
||||
- Nuvoton all series
|
||||
|
||||
### Artinchip
|
||||
|
||||
- d13x, d21x
|
||||
|
||||
### Intel
|
||||
|
||||
Intel 6 Series Chipset and Intel C200 Series Chipset
|
||||
|
||||
## Before Use
|
||||
|
||||
Your should implement `usb_hc_low_level_init`.
|
||||
|
||||
@@ -28,39 +28,17 @@
|
||||
#endif
|
||||
|
||||
#define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM * 3)
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM + 3)
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 20
|
||||
|
||||
extern uint8_t usbh_get_port_speed(const uint8_t port);
|
||||
|
||||
struct ehci_qh_hw;
|
||||
struct ehci_itd_hw;
|
||||
struct ehci_pipe {
|
||||
uint8_t dev_addr;
|
||||
uint8_t ep_addr;
|
||||
uint8_t ep_type;
|
||||
uint8_t ep_interval;
|
||||
uint8_t speed;
|
||||
uint8_t mult;
|
||||
uint16_t ep_mps;
|
||||
bool toggle;
|
||||
bool inuse;
|
||||
uint32_t xfrd;
|
||||
bool waiter;
|
||||
usb_osal_sem_t waitsem;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_urb *urb;
|
||||
uint8_t mf_unmask;
|
||||
uint8_t mf_valid;
|
||||
uint8_t iso_packet_idx;
|
||||
uint8_t remain_itd_num;
|
||||
};
|
||||
|
||||
struct ehci_qh_hw {
|
||||
struct ehci_qh hw;
|
||||
uint32_t first_qtd;
|
||||
struct usbh_urb *urb;
|
||||
uint8_t remove_in_iaad;
|
||||
usb_osal_sem_t waitsem;
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
struct ehci_qtd_hw {
|
||||
@@ -72,8 +50,10 @@ struct ehci_qtd_hw {
|
||||
struct ehci_itd_hw {
|
||||
struct ehci_itd hw;
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_pipe *pipe;
|
||||
uint16_t start_frame;
|
||||
uint8_t mf_unmask;
|
||||
uint8_t mf_valid;
|
||||
uint32_t pkt_idx[8];
|
||||
usb_slist_t list;
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
@@ -81,14 +61,13 @@ struct ehci_hcd {
|
||||
bool ehci_qh_used[CONFIG_USB_EHCI_QH_NUM];
|
||||
bool ehci_qtd_used[CONFIG_USB_EHCI_QTD_NUM];
|
||||
bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM];
|
||||
struct ehci_pipe pipe_pool[CONFIG_USB_EHCI_QH_NUM];
|
||||
};
|
||||
|
||||
extern struct ehci_hcd g_ehci_hcd;
|
||||
extern uint32_t g_framelist[];
|
||||
|
||||
int ehci_iso_pipe_init(struct ehci_pipe *pipe, struct usbh_urb *urb);
|
||||
int ehci_iso_urb_init(struct usbh_urb *urb);
|
||||
void ehci_remove_itd_urb(struct usbh_urb *urb);
|
||||
void ehci_scan_isochronous_list(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
91
port/ehci/usb_glue_aic.c
Normal file
91
port/ehci/usb_glue_aic.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Artinchip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <aic_core.h>
|
||||
#include <aic_hal.h>
|
||||
#include <hal_syscfg.h>
|
||||
#include "usbh_core.h"
|
||||
#include "usb_ehci_priv.h"
|
||||
|
||||
extern void USBH_IRQHandler(void);
|
||||
|
||||
void usb_hc_low_level_init(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* set usb0 phy switch: Host/Device */
|
||||
#ifdef AIC_USING_USB0_HOST
|
||||
syscfg_usb_phy0_sw_host(1);
|
||||
#endif
|
||||
|
||||
/* set phy type: UTMI/ULPI */
|
||||
val = readl((volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
#ifdef FPGA_BOARD_ARTINCHIP
|
||||
/* fpga phy type = ULPI */
|
||||
writel((val & ~0x1U), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
#else
|
||||
/* board phy type = UTMI */
|
||||
writel((val | 0x1), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Set AHB2STBUS_INSREG01
|
||||
Set EHCI packet buffer IN/OUT threshold (in DWORDs)
|
||||
Must increase the OUT threshold to avoid underrun. (FIFO size - 4)
|
||||
*/
|
||||
#ifdef FPGA_BOARD_ARTINCHIP
|
||||
writel((32 | (127 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94));
|
||||
#else
|
||||
writel((32 | (32 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* enable clock */
|
||||
hal_clk_enable(CONFIG_USB_EHCI_PHY_CLK);
|
||||
hal_clk_enable(CONFIG_USB_EHCI_CLK);
|
||||
aicos_udelay(300);
|
||||
hal_reset_assert(CONFIG_USB_EHCI_PHY_RESET);
|
||||
hal_reset_assert(CONFIG_USB_EHCI_RESET);
|
||||
aicos_udelay(300);
|
||||
hal_reset_deassert(CONFIG_USB_EHCI_PHY_RESET);
|
||||
hal_reset_deassert(CONFIG_USB_EHCI_RESET);
|
||||
aicos_udelay(300);
|
||||
|
||||
/* register interrupt callback */
|
||||
aicos_request_irq(CONFIG_USB_EHCI_IRQ_NUM, (irq_handler_t)USBH_IRQHandler,
|
||||
0, "usb_host_ehci", NULL);
|
||||
aicos_irq_enable(CONFIG_USB_EHCI_IRQ_NUM);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
{
|
||||
/* Defined by individual manufacturers */
|
||||
uint32_t regval;
|
||||
|
||||
regval = EHCI_HCOR->portsc[port-1];
|
||||
if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE)
|
||||
return USB_SPEED_LOW;
|
||||
|
||||
if (regval & EHCI_PORTSC_PE)
|
||||
return USB_SPEED_HIGH;
|
||||
else
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len)
|
||||
{
|
||||
aicos_dcache_clean_range((size_t *)addr, len);
|
||||
}
|
||||
|
||||
void usb_ehci_dcache_invalidate(uintptr_t addr, uint32_t len)
|
||||
{
|
||||
aicos_dcache_invalid_range((size_t *)addr, len);
|
||||
}
|
||||
|
||||
void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len)
|
||||
{
|
||||
aicos_dcache_clean_invalid_range((size_t *)addr, len);
|
||||
}
|
||||
@@ -30,19 +30,20 @@ static void usb_host_mode_init(USB_Type *ptr)
|
||||
ptr->USBCMD &= ~USB_USBCMD_ITC_MASK;
|
||||
}
|
||||
|
||||
void usb_hc_low_level_init()
|
||||
void usb_hc_low_level_init(void)
|
||||
{
|
||||
usb_phy_init((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
intc_m_enable_irq(CONFIG_HPM_USBH_IRQn);
|
||||
}
|
||||
|
||||
void usb_hc_low_level2_init()
|
||||
void usb_hc_low_level2_init(void)
|
||||
{
|
||||
usb_host_mode_init((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
{
|
||||
(void)port;
|
||||
uint8_t speed;
|
||||
|
||||
speed = usb_get_port_speed((USB_Type *)CONFIG_HPM_USBH_BASE);
|
||||
@@ -62,8 +63,8 @@ uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
|
||||
extern void USBH_IRQHandler(void);
|
||||
|
||||
void isr_usb(void)
|
||||
void isr_usbh(void)
|
||||
{
|
||||
USBH_IRQHandler();
|
||||
}
|
||||
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBH_IRQn, isr_usb)
|
||||
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBH_IRQn, isr_usbh)
|
||||
55
port/ehci/usb_glue_intel.c
Normal file
55
port/ehci/usb_glue_intel.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifdef __rtems__
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/pci.h>
|
||||
#include <bsp/irq.h>
|
||||
#include "usbh_core.h"
|
||||
|
||||
uint32_t echi_base;
|
||||
static int ehci_bus;
|
||||
static int ehci_slot;
|
||||
static int ehci_function;
|
||||
static int ehci_vector;
|
||||
|
||||
extern void USBH_IRQHandler(void *para);
|
||||
|
||||
void ehci_pci_scan(int bus, int slot, int fun, int vector)
|
||||
{
|
||||
ehci_bus = bus;
|
||||
ehci_slot = slot;
|
||||
ehci_function = fun;
|
||||
ehci_vector = vector;
|
||||
pci_read_config_dword(bus, slot, fun, PCI_BASE_ADDRESS_0, &echi_base);
|
||||
}
|
||||
void usb_hc_low_level_init(void)
|
||||
{
|
||||
//set software own ehci
|
||||
uint32_t legacy_val;
|
||||
pci_write_config_dword(ehci_bus, ehci_slot, ehci_function, 0x68, 1 << 24);
|
||||
pci_read_config_dword(ehci_bus, ehci_slot, ehci_function, 0x68, &legacy_val);
|
||||
if ((legacy_val & 0x01010000) == 0x01000000)
|
||||
printf("OS owned echi\n");
|
||||
else
|
||||
printf("BIOS owned echi\n");
|
||||
|
||||
rtems_status_code sc;
|
||||
sc = rtems_interrupt_handler_install(
|
||||
ehci_vector,
|
||||
"USBirq",
|
||||
RTEMS_INTERRUPT_SHARED,
|
||||
USBH_IRQHandler,
|
||||
(void *)0);
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
printf("USB install isr falied,%s\n", rtems_status_text(sc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
{
|
||||
printf("USB_SPEED_HIGH present\n");
|
||||
return USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@ USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USB_EHCI_FRAME_LIST_SIZE] __
|
||||
static struct ehci_qh_hw *ehci_qh_alloc(void)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
usb_osal_sem_t waitsem;
|
||||
size_t flags;
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
|
||||
@@ -36,10 +37,12 @@ static struct ehci_qh_hw *ehci_qh_alloc(void)
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
qh = &ehci_qh_pool[i];
|
||||
waitsem = qh->waitsem;
|
||||
memset(qh, 0, sizeof(struct ehci_qh_hw));
|
||||
qh->hw.hlp = QTD_LIST_END;
|
||||
qh->hw.overlay.next_qtd = QTD_LIST_END;
|
||||
qh->hw.overlay.alt_next_qtd = QTD_LIST_END;
|
||||
qh->waitsem = waitsem;
|
||||
return qh;
|
||||
}
|
||||
}
|
||||
@@ -100,24 +103,6 @@ static void ehci_qtd_free(struct ehci_qtd_hw *qtd)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ehci_pipe *ehci_pipe_alloc(void)
|
||||
{
|
||||
int pipe;
|
||||
|
||||
for (pipe = 0; pipe < CONFIG_USB_EHCI_QH_NUM; pipe++) {
|
||||
if (!g_ehci_hcd.pipe_pool[pipe].inuse) {
|
||||
g_ehci_hcd.pipe_pool[pipe].inuse = true;
|
||||
return &g_ehci_hcd.pipe_pool[pipe];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ehci_pipe_free(struct ehci_pipe *pipe)
|
||||
{
|
||||
pipe->inuse = false;
|
||||
}
|
||||
|
||||
static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
|
||||
{
|
||||
n->hw.hlp = head->hw.hlp;
|
||||
@@ -312,7 +297,7 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl
|
||||
qtd->total_len = buflen;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd_setup = NULL;
|
||||
@@ -344,15 +329,15 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
}
|
||||
|
||||
ehci_qh_fill(qh,
|
||||
pipe->dev_addr,
|
||||
pipe->ep_addr,
|
||||
pipe->ep_type,
|
||||
pipe->ep_mps,
|
||||
urb->hport->dev_addr,
|
||||
urb->ep->bEndpointAddress,
|
||||
USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes),
|
||||
USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
|
||||
0,
|
||||
pipe->ep_interval,
|
||||
pipe->hport->speed,
|
||||
pipe->hport->parent->hub_addr,
|
||||
pipe->hport->port);
|
||||
0,
|
||||
urb->hport->speed,
|
||||
urb->hport->parent->hub_addr,
|
||||
urb->hport->port);
|
||||
|
||||
/* fill setup qtd */
|
||||
token = QTD_TOKEN_STATUS_ACTIVE |
|
||||
@@ -361,7 +346,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
((uint32_t)8 << QTD_TOKEN_NBYTES_SHIFT);
|
||||
|
||||
ehci_qtd_fill(qtd_setup, (uintptr_t)setup, 8, token);
|
||||
qtd_setup->urb = pipe->urb;
|
||||
qtd_setup->urb = urb;
|
||||
|
||||
/* fill data qtd */
|
||||
if (setup->wLength > 0) {
|
||||
@@ -377,7 +362,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
((uint32_t)buflen << QTD_TOKEN_NBYTES_SHIFT);
|
||||
|
||||
ehci_qtd_fill(qtd_data, (uintptr_t)buffer, buflen, token);
|
||||
qtd_data->urb = pipe->urb;
|
||||
qtd_data->urb = urb;
|
||||
qtd_setup->hw.next_qtd = EHCI_PTR2ADDR(qtd_data);
|
||||
qtd_data->hw.next_qtd = EHCI_PTR2ADDR(qtd_status);
|
||||
} else {
|
||||
@@ -397,7 +382,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
((uint32_t)0 << QTD_TOKEN_NBYTES_SHIFT);
|
||||
|
||||
ehci_qtd_fill(qtd_status, 0, 0, token);
|
||||
qtd_status->urb = pipe->urb;
|
||||
qtd_status->urb = urb;
|
||||
qtd_status->hw.next_qtd = QTD_LIST_END;
|
||||
|
||||
/* update qh first qtd */
|
||||
@@ -409,7 +394,8 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
qh->urb = pipe->urb;
|
||||
qh->urb = urb;
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into async list */
|
||||
ehci_qh_add_head(&g_async_qh_head, qh);
|
||||
|
||||
@@ -419,7 +405,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct
|
||||
return qh;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd = NULL;
|
||||
@@ -447,15 +433,15 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
}
|
||||
|
||||
ehci_qh_fill(qh,
|
||||
pipe->dev_addr,
|
||||
pipe->ep_addr,
|
||||
pipe->ep_type,
|
||||
pipe->ep_mps,
|
||||
urb->hport->dev_addr,
|
||||
urb->ep->bEndpointAddress,
|
||||
USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes),
|
||||
USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
|
||||
0,
|
||||
pipe->ep_interval,
|
||||
pipe->hport->speed,
|
||||
pipe->hport->parent->hub_addr,
|
||||
pipe->hport->port);
|
||||
0,
|
||||
urb->hport->speed,
|
||||
urb->hport->parent->hub_addr,
|
||||
urb->hport->port);
|
||||
|
||||
while (buflen >= 0) {
|
||||
qtd = ehci_qtd_alloc();
|
||||
@@ -468,7 +454,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
if (pipe->ep_addr & 0x80) {
|
||||
if (urb->ep->bEndpointAddress & 0x80) {
|
||||
token = QTD_TOKEN_PID_IN;
|
||||
} else {
|
||||
token = QTD_TOKEN_PID_OUT;
|
||||
@@ -483,7 +469,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
}
|
||||
|
||||
ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
|
||||
qtd->urb = pipe->urb;
|
||||
qtd->urb = urb;
|
||||
qtd->hw.next_qtd = QTD_LIST_END;
|
||||
buffer += xfer_len;
|
||||
|
||||
@@ -504,7 +490,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
|
||||
|
||||
/* update data toggle */
|
||||
if (pipe->toggle) {
|
||||
if (urb->data_toggle) {
|
||||
qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
|
||||
} else {
|
||||
qh->hw.overlay.token = 0;
|
||||
@@ -515,7 +501,8 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
qh->urb = pipe->urb;
|
||||
qh->urb = urb;
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into async list */
|
||||
ehci_qh_add_head(&g_async_qh_head, qh);
|
||||
|
||||
@@ -525,7 +512,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
return qh;
|
||||
}
|
||||
|
||||
static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen)
|
||||
static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
struct ehci_qtd_hw *qtd = NULL;
|
||||
@@ -553,15 +540,15 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
}
|
||||
|
||||
ehci_qh_fill(qh,
|
||||
pipe->dev_addr,
|
||||
pipe->ep_addr,
|
||||
pipe->ep_type,
|
||||
pipe->ep_mps,
|
||||
pipe->mult + 1,
|
||||
pipe->ep_interval,
|
||||
pipe->hport->speed,
|
||||
pipe->hport->parent->hub_addr,
|
||||
pipe->hport->port);
|
||||
urb->hport->dev_addr,
|
||||
urb->ep->bEndpointAddress,
|
||||
USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes),
|
||||
USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
|
||||
USB_GET_MULT(urb->ep->wMaxPacketSize) + 1,
|
||||
urb->ep->bInterval,
|
||||
urb->hport->speed,
|
||||
urb->hport->parent->hub_addr,
|
||||
urb->hport->port);
|
||||
|
||||
while (buflen >= 0) {
|
||||
qtd = ehci_qtd_alloc();
|
||||
@@ -574,7 +561,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
if (pipe->ep_addr & 0x80) {
|
||||
if (urb->ep->bEndpointAddress & 0x80) {
|
||||
token = QTD_TOKEN_PID_IN;
|
||||
} else {
|
||||
token = QTD_TOKEN_PID_OUT;
|
||||
@@ -589,7 +576,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
}
|
||||
|
||||
ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
|
||||
qtd->urb = pipe->urb;
|
||||
qtd->urb = urb;
|
||||
qtd->hw.next_qtd = QTD_LIST_END;
|
||||
buffer += xfer_len;
|
||||
|
||||
@@ -610,7 +597,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
|
||||
|
||||
/* update data toggle */
|
||||
if (pipe->toggle) {
|
||||
if (urb->data_toggle) {
|
||||
qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
|
||||
} else {
|
||||
qh->hw.overlay.token = 0;
|
||||
@@ -621,12 +608,13 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
qh->urb = pipe->urb;
|
||||
qh->urb = urb;
|
||||
urb->hcpriv = qh;
|
||||
/* add qh into periodic list */
|
||||
if (pipe->speed == USB_SPEED_HIGH) {
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval), qh);
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
|
||||
ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN;
|
||||
@@ -635,16 +623,21 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b
|
||||
return qh;
|
||||
}
|
||||
|
||||
void ehci_pipe_waitup(struct ehci_pipe *pipe)
|
||||
static void ehci_urb_waitup(struct usbh_urb *urb)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
urb = pipe->urb;
|
||||
pipe->urb = NULL;
|
||||
qh = (struct ehci_qh_hw *)urb->hcpriv;
|
||||
qh->urb = NULL;
|
||||
urb->hcpriv = NULL;
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
qh->remove_in_iaad = 0;
|
||||
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
usb_osal_sem_give(qh->waitsem);
|
||||
} else {
|
||||
ehci_qh_free(qh);
|
||||
}
|
||||
|
||||
if (urb->complete) {
|
||||
@@ -676,54 +669,52 @@ static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_pipe *pipe;
|
||||
struct ehci_qtd_hw *qtd;
|
||||
uint32_t token;
|
||||
|
||||
token = qh->hw.overlay.token;
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
|
||||
/* Check if token is only in active status without errors */
|
||||
if ((token & (QTD_TOKEN_STATUS_ERRORS | QTD_TOKEN_STATUS_ACTIVE)) == QTD_TOKEN_STATUS_ACTIVE) {
|
||||
if (qtd == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (qtd) {
|
||||
token = qtd->hw.token;
|
||||
|
||||
if (token & QTD_TOKEN_STATUS_ERRORS) {
|
||||
break;
|
||||
} else if (token & QTD_TOKEN_STATUS_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
|
||||
}
|
||||
|
||||
urb = qh->urb;
|
||||
pipe = urb->pipe;
|
||||
|
||||
if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) {
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
|
||||
while (qtd) {
|
||||
if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
|
||||
}
|
||||
|
||||
if (token & QTD_TOKEN_TOGGLE) {
|
||||
pipe->toggle = true;
|
||||
if (qh->hw.overlay.token & QTD_TOKEN_TOGGLE) {
|
||||
urb->data_toggle = true;
|
||||
} else {
|
||||
pipe->toggle = false;
|
||||
urb->data_toggle = false;
|
||||
}
|
||||
urb->errorcode = 0;
|
||||
} else {
|
||||
if (token & QTD_TOKEN_STATUS_BABBLE) {
|
||||
urb->errorcode = -EPERM;
|
||||
pipe->toggle = 0;
|
||||
urb->errorcode = -USB_ERR_BABBLE;
|
||||
urb->data_toggle = 0;
|
||||
} else if (token & QTD_TOKEN_STATUS_HALTED) {
|
||||
urb->errorcode = -EPERM;
|
||||
pipe->toggle = 0;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
urb->data_toggle = 0;
|
||||
} else if (token & (QTD_TOKEN_STATUS_DBERR | QTD_TOKEN_STATUS_XACTERR)) {
|
||||
urb->errorcode = -EIO;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
}
|
||||
}
|
||||
|
||||
ehci_qh_scan_qtds(qhead, qh);
|
||||
|
||||
if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
qh->remove_in_iaad = 0;
|
||||
ehci_qh_free(qh);
|
||||
ehci_pipe_waitup(pipe);
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
ehci_urb_waitup(urb);
|
||||
} else {
|
||||
qh->remove_in_iaad = 1;
|
||||
|
||||
@@ -744,8 +735,6 @@ static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
|
||||
qh->first_qtd = qtd->hw.next_qtd;
|
||||
qtd = EHCI_ADDR2QTD(qh->first_qtd);
|
||||
}
|
||||
|
||||
ehci_qh_free(qh);
|
||||
}
|
||||
|
||||
static int usbh_reset_port(const uint8_t port)
|
||||
@@ -771,7 +760,7 @@ static int usbh_reset_port(const uint8_t port)
|
||||
usb_osal_msleep(1);
|
||||
timeout++;
|
||||
if (timeout > 100) {
|
||||
return -ETIMEDOUT;
|
||||
return -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,18 +787,16 @@ int usb_hc_init(void)
|
||||
|
||||
if (sizeof(struct ehci_qh_hw) % 32) {
|
||||
USB_LOG_ERR("struct ehci_qh_hw is not align 32\r\n");
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
if (sizeof(struct ehci_qtd_hw) % 32) {
|
||||
USB_LOG_ERR("struct ehci_qtd_hw is not align 32\r\n");
|
||||
return -EINVAL;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
struct ehci_pipe *pipe;
|
||||
|
||||
pipe = &g_ehci_hcd.pipe_pool[index];
|
||||
pipe->waitsem = usb_osal_sem_create(0);
|
||||
qh = &ehci_qh_pool[index];
|
||||
qh->waitsem = usb_osal_sem_create(0);
|
||||
}
|
||||
|
||||
memset(&g_async_qh_head, 0, sizeof(struct ehci_qh_hw));
|
||||
@@ -859,7 +846,7 @@ int usb_hc_init(void)
|
||||
usb_osal_msleep(1);
|
||||
timeout++;
|
||||
if (timeout > 100) {
|
||||
return -ETIMEDOUT;
|
||||
return -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,7 +890,7 @@ int usb_hc_init(void)
|
||||
usb_osal_msleep(1);
|
||||
timeout++;
|
||||
if (timeout > 100) {
|
||||
return -ETIMEDOUT;
|
||||
return -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_USB_EHCI_PORT_POWER
|
||||
@@ -919,6 +906,51 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_hc_deinit(void)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
|
||||
volatile uint32_t timeout = 0;
|
||||
uint32_t regval;
|
||||
|
||||
EHCI_HCOR->usbintr = 0;
|
||||
|
||||
regval = EHCI_HCOR->usbcmd;
|
||||
regval &= ~EHCI_USBCMD_ASEN;
|
||||
regval &= ~EHCI_USBCMD_PSEN;
|
||||
regval &= ~EHCI_USBCMD_RUN;
|
||||
EHCI_HCOR->usbcmd = regval;
|
||||
|
||||
while ((EHCI_HCOR->usbsts & (EHCI_USBSTS_PSS | EHCI_USBSTS_ASS))) {
|
||||
usb_osal_msleep(1);
|
||||
timeout++;
|
||||
if (timeout > 100) {
|
||||
return -USB_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_PORT_POWER
|
||||
for (uint8_t port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) {
|
||||
regval = EHCI_HCOR->portsc[port];
|
||||
regval &= ~EHCI_PORTSC_PP;
|
||||
EHCI_HCOR->portsc[port] = regval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_CONFIGFLAG
|
||||
EHCI_HCOR->configflag = 0;
|
||||
#endif
|
||||
|
||||
EHCI_HCOR->usbsts = EHCI_HCOR->usbsts;
|
||||
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
qh = &ehci_qh_pool[index];
|
||||
usb_osal_sem_delete(qh->waitsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t usbh_get_frame_number(void)
|
||||
{
|
||||
return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff);
|
||||
@@ -942,7 +974,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
@@ -952,7 +984,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_DESCRIPTOR:
|
||||
@@ -967,7 +999,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
switch (setup->bRequest) {
|
||||
case HUB_REQUEST_CLEAR_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
@@ -975,6 +1007,19 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_PE;
|
||||
break;
|
||||
case HUB_PORT_FEATURE_SUSPEND:
|
||||
EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_RESUME;
|
||||
usb_osal_msleep(20);
|
||||
EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_RESUME;
|
||||
while (EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_RESUME) {}
|
||||
|
||||
temp = EHCI_HCOR->usbcmd;
|
||||
temp |= EHCI_USBCMD_ASEN;
|
||||
temp |= EHCI_USBCMD_PSEN;
|
||||
temp |= EHCI_USBCMD_RUN;
|
||||
EHCI_HCOR->usbcmd = temp;
|
||||
|
||||
while ((EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) == 0) {}
|
||||
|
||||
case HUB_PORT_FEATURE_C_SUSPEND:
|
||||
break;
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
@@ -994,16 +1039,26 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_PORT_FEATURE_C_RESET:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
case HUB_PORT_FEATURE_SUSPEND:
|
||||
temp = EHCI_HCOR->usbcmd;
|
||||
temp &= ~EHCI_USBCMD_ASEN;
|
||||
temp &= ~EHCI_USBCMD_PSEN;
|
||||
temp &= ~EHCI_USBCMD_RUN;
|
||||
EHCI_HCOR->usbcmd = temp;
|
||||
|
||||
while (EHCI_HCOR->usbcmd & EHCI_USBCMD_RUN) {}
|
||||
|
||||
EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_SUSPEND;
|
||||
while ((EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_SUSPEND) == 0) {}
|
||||
break;
|
||||
case HUB_PORT_FEATURE_POWER:
|
||||
#ifdef CONFIG_USB_EHCI_PORT_POWER
|
||||
@@ -1015,12 +1070,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_STATUS:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
temp = EHCI_HCOR->portsc[port - 1];
|
||||
|
||||
@@ -1068,144 +1123,67 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult)
|
||||
{
|
||||
struct ehci_pipe *ppipe = (struct ehci_pipe *)pipe;
|
||||
|
||||
ppipe->dev_addr = dev_addr;
|
||||
ppipe->ep_mps = ep_mps;
|
||||
ppipe->mult = mult;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
|
||||
{
|
||||
struct ehci_pipe *ppipe;
|
||||
usb_osal_sem_t waitsem;
|
||||
|
||||
ppipe = ehci_pipe_alloc();
|
||||
if (ppipe == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* store variables */
|
||||
waitsem = ppipe->waitsem;
|
||||
|
||||
memset(ppipe, 0, sizeof(struct ehci_pipe));
|
||||
|
||||
ppipe->ep_addr = ep_cfg->ep_addr;
|
||||
ppipe->ep_type = ep_cfg->ep_type;
|
||||
ppipe->ep_mps = ep_cfg->ep_mps;
|
||||
ppipe->ep_interval = ep_cfg->ep_interval;
|
||||
ppipe->mult = ep_cfg->mult;
|
||||
ppipe->speed = ep_cfg->hport->speed;
|
||||
ppipe->dev_addr = ep_cfg->hport->dev_addr;
|
||||
ppipe->hport = ep_cfg->hport;
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
if ((ppipe->speed == USB_SPEED_HIGH) && (ppipe->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
|
||||
if (ep_cfg->ep_interval == 0x01) { /* transfer interval 1 mf */
|
||||
ppipe->mf_unmask = 0xff;
|
||||
ppipe->mf_valid = 8;
|
||||
} else if (ep_cfg->ep_interval == 0x02) { /* transfer interval 2 mf */
|
||||
ppipe->mf_unmask = 0x55;
|
||||
ppipe->mf_valid = 4;
|
||||
} else if (ep_cfg->ep_interval == 0x03) { /* transfer interval 4 mf */
|
||||
ppipe->mf_unmask = 0x44;
|
||||
ppipe->mf_valid = 2;
|
||||
} else if (ep_cfg->ep_interval == 0x04) { /* transfer interval 8 mf */
|
||||
ppipe->mf_unmask = 0x01;
|
||||
ppipe->mf_valid = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* restore variable */
|
||||
ppipe->inuse = true;
|
||||
ppipe->waitsem = waitsem;
|
||||
|
||||
*pipe = (usbh_pipe_t)ppipe;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_free(usbh_pipe_t pipe)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_pipe *ppipe;
|
||||
|
||||
ppipe = (struct ehci_pipe *)pipe;
|
||||
|
||||
if (!ppipe) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
urb = ppipe->urb;
|
||||
|
||||
if (urb) {
|
||||
usbh_kill_urb(urb);
|
||||
}
|
||||
|
||||
ehci_pipe_free(ppipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_submit_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct ehci_pipe *pipe;
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
size_t flags;
|
||||
int ret = 0;
|
||||
struct usbh_hub *hub;
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
if (!urb || !urb->pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hport || !urb->ep) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
if (!pipe->inuse /*|| !(EHCI_HCOR->portsc[pipe->hport->port-1] & EHCI_PORTSC_CCS)*/ || !pipe->hport->connected) {
|
||||
return -ENODEV;
|
||||
/* find active hubport in roothub */
|
||||
hport = urb->hport;
|
||||
hub = urb->hport->parent;
|
||||
while (!hub->is_roothub) {
|
||||
hport = hub->parent;
|
||||
hub = hub->parent->parent;
|
||||
}
|
||||
|
||||
if (pipe->urb && (pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
|
||||
return -EBUSY;
|
||||
if (!urb->hport->connected || !(EHCI_HCOR->portsc[hport->port - 1] & EHCI_PORTSC_CCS)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if ((urb->errorcode == -USB_ERR_BUSY) && (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
pipe->waiter = false;
|
||||
pipe->xfrd = 0;
|
||||
pipe->urb = urb;
|
||||
urb->errorcode = -EBUSY;
|
||||
urb->hcpriv = NULL;
|
||||
urb->errorcode = -USB_ERR_BUSY;
|
||||
urb->actual_length = 0;
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
pipe->waiter = true;
|
||||
}
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
switch (pipe->ep_type) {
|
||||
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
qh = ehci_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_control_urb_init(urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
urb->hcpriv = qh;
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
qh = ehci_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_bulk_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
urb->hcpriv = qh;
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
qh = ehci_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
qh = ehci_intr_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
if (qh == NULL) {
|
||||
return -ENOMEM;
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
urb->hcpriv = qh;
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
ehci_iso_pipe_init(pipe, urb);
|
||||
ret = ehci_iso_urb_init(urb);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
@@ -1214,42 +1192,36 @@ int usbh_submit_urb(struct usbh_urb *urb)
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
/* wait until timeout or sem give */
|
||||
ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
|
||||
ret = usb_osal_sem_take(qh->waitsem, urb->timeout);
|
||||
if (ret < 0) {
|
||||
goto errout_timeout;
|
||||
}
|
||||
urb->timeout = 0;
|
||||
ret = urb->errorcode;
|
||||
/* we can free qh when waitsem is done */
|
||||
ehci_qh_free(qh);
|
||||
}
|
||||
return ret;
|
||||
errout_timeout:
|
||||
/* Timeout will run here */
|
||||
pipe->waiter = false;
|
||||
urb->timeout = 0;
|
||||
usbh_kill_urb(urb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_kill_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct ehci_pipe *pipe;
|
||||
struct ehci_qh_hw *qh = NULL;
|
||||
|
||||
struct ehci_qh_hw *qh;
|
||||
size_t flags;
|
||||
|
||||
if (!urb) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
if (!pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hcpriv) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
EHCI_HCOR->usbcmd &= ~(EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
|
||||
|
||||
if ((pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) || (pipe->ep_type == USB_ENDPOINT_TYPE_BULK)) {
|
||||
if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK)) {
|
||||
qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
|
||||
while ((qh != &g_async_qh_head) && qh) {
|
||||
if (qh->urb == urb) {
|
||||
@@ -1257,14 +1229,14 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
}
|
||||
} else if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
} else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
while (qh) {
|
||||
if (qh->urb == urb) {
|
||||
if (pipe->speed == USB_SPEED_HIGH) {
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
|
||||
ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
@@ -1272,17 +1244,24 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
} else {
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
ehci_remove_itd_urb(urb);
|
||||
EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
|
||||
usb_osal_leave_critical_section(flags);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
|
||||
|
||||
pipe->urb = NULL;
|
||||
qh = (struct ehci_qh_hw *)urb->hcpriv;
|
||||
urb->hcpriv = NULL;
|
||||
qh->urb = NULL;
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
urb->errorcode = -ESHUTDOWN;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
urb->errorcode = -USB_ERR_SHUTDOWN;
|
||||
usb_osal_sem_give(qh->waitsem);
|
||||
} else {
|
||||
ehci_qh_free(qh);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
@@ -1306,16 +1285,14 @@ static void ehci_scan_async_list(void)
|
||||
static void ehci_scan_periodic_list(void)
|
||||
{
|
||||
struct ehci_qh_hw *qh;
|
||||
struct ehci_pipe *pipe;
|
||||
|
||||
qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
|
||||
while (qh) {
|
||||
if (qh->urb && qh->urb->pipe) {
|
||||
pipe = (struct ehci_pipe *)qh->urb->pipe;
|
||||
if (pipe->speed == USB_SPEED_HIGH) {
|
||||
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
|
||||
if (qh->urb) {
|
||||
if (qh->urb->hport->speed == USB_SPEED_HIGH) {
|
||||
ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval), qh);
|
||||
} else {
|
||||
ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
|
||||
ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval * 8), qh);
|
||||
}
|
||||
}
|
||||
qh = EHCI_ADDR2QH(qh->hw.hlp);
|
||||
@@ -1372,16 +1349,7 @@ void USBH_IRQHandler(void)
|
||||
for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
|
||||
struct ehci_qh_hw *qh = &ehci_qh_pool[index];
|
||||
if (g_ehci_hcd.ehci_qh_used[index] && qh->remove_in_iaad) {
|
||||
struct usbh_urb *urb;
|
||||
struct ehci_pipe *pipe;
|
||||
|
||||
urb = qh->urb;
|
||||
pipe = urb->pipe;
|
||||
|
||||
qh->remove_in_iaad = 0;
|
||||
ehci_qh_free(qh);
|
||||
|
||||
ehci_pipe_waitup(pipe);
|
||||
ehci_urb_waitup(qh->urb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
#include "usbd_core.h"
|
||||
|
||||
#ifndef CONFIG_USBDEV_FSDEV_PMA_ACCESS
|
||||
#error "please define USBD_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#define PMA_ACCESS CONFIG_USBDEV_FSDEV_PMA_ACCESS
|
||||
#include "usb_fsdev_reg.h"
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler USB_LP_CAN1_RX0_IRQHandler //use actual usb irq name instead
|
||||
#error "please define USBD_IRQHandler in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x40005C00UL) /*!< USB_IP Peripheral Registers base address */
|
||||
#ifndef USBD_BASE
|
||||
#error "please define USBD_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 8
|
||||
#ifndef CONFIG_USB_FSDEV_RAM_SIZE
|
||||
#define CONFIG_USB_FSDEV_RAM_SIZE 512
|
||||
#endif
|
||||
|
||||
#ifndef USB_RAM_SIZE
|
||||
#define USB_RAM_SIZE 512
|
||||
#ifndef CONFIG_USBDEV_EP_NUM
|
||||
#define CONFIG_USBDEV_EP_NUM 8
|
||||
#endif
|
||||
|
||||
#warning please check your PMA_ACCESS is 1 or 2
|
||||
#define USB ((USB_TypeDef *)USBD_BASE)
|
||||
|
||||
#define USB ((USB_TypeDef *)USB_BASE)
|
||||
|
||||
#define USB_BTABLE_SIZE (8 * USB_NUM_BIDIR_ENDPOINTS)
|
||||
#define USB_BTABLE_SIZE (8 * CONFIG_USBDEV_EP_NUM)
|
||||
|
||||
static void fsdev_write_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
|
||||
static void fsdev_read_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
|
||||
@@ -42,10 +46,10 @@ struct fsdev_ep_state {
|
||||
/* Driver state */
|
||||
struct fsdev_udc {
|
||||
struct usb_setup_packet setup;
|
||||
volatile uint8_t dev_addr; /*!< USB Address */
|
||||
volatile uint32_t pma_offset; /*!< pma offset */
|
||||
struct fsdev_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct fsdev_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
volatile uint8_t dev_addr; /*!< USB Address */
|
||||
volatile uint32_t pma_offset; /*!< pma offset */
|
||||
struct fsdev_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
|
||||
struct fsdev_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
|
||||
} g_fsdev_udc;
|
||||
|
||||
__WEAK void usb_dc_low_level_init(void)
|
||||
@@ -121,19 +125,19 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
|
||||
USB_LOG_ERR("Ep addr %d overflow\r\n", ep_cfg->ep_addr);
|
||||
if (ep_idx > (CONFIG_USBDEV_EP_NUM - 1)) {
|
||||
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t wEpRegVal;
|
||||
|
||||
/* initialize Endpoint */
|
||||
switch (ep_cfg->ep_type) {
|
||||
switch (USB_GET_ENDPOINT_TYPE(ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
wEpRegVal = USB_EP_CONTROL;
|
||||
break;
|
||||
@@ -157,42 +161,42 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
PCD_SET_EPTYPE(USB, ep_idx, wEpRegVal);
|
||||
|
||||
PCD_SET_EP_ADDRESS(USB, ep_idx, ep_idx);
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_enable = true;
|
||||
if (g_fsdev_udc.out_ep[ep_idx].ep_mps > g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len) {
|
||||
if (g_fsdev_udc.pma_offset + g_fsdev_udc.out_ep[ep_idx].ep_mps > USB_RAM_SIZE) {
|
||||
USB_LOG_ERR("Ep pma %d overflow\r\n", ep_cfg->ep_addr);
|
||||
if (g_fsdev_udc.pma_offset + g_fsdev_udc.out_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
|
||||
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len = ep_cfg->ep_mps;
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_fsdev_udc.out_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
|
||||
/*Set the endpoint Receive buffer address */
|
||||
PCD_SET_EP_RX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
|
||||
g_fsdev_udc.pma_offset += ep_cfg->ep_mps;
|
||||
g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
}
|
||||
/*Set the endpoint Receive buffer counter*/
|
||||
PCD_SET_EP_RX_CNT(USB, ep_idx, ep_cfg->ep_mps);
|
||||
PCD_SET_EP_RX_CNT(USB, ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
||||
PCD_CLEAR_RX_DTOG(USB, ep_idx);
|
||||
} else {
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_enable = true;
|
||||
if (g_fsdev_udc.in_ep[ep_idx].ep_mps > g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len) {
|
||||
if (g_fsdev_udc.pma_offset + g_fsdev_udc.in_ep[ep_idx].ep_mps > USB_RAM_SIZE) {
|
||||
USB_LOG_ERR("Ep pma %d overflow\r\n", ep_cfg->ep_addr);
|
||||
if (g_fsdev_udc.pma_offset + g_fsdev_udc.in_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
|
||||
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len = ep_cfg->ep_mps;
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_fsdev_udc.in_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
|
||||
/*Set the endpoint Transmit buffer address */
|
||||
PCD_SET_EP_TX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
|
||||
g_fsdev_udc.pma_offset += ep_cfg->ep_mps;
|
||||
g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
PCD_CLEAR_TX_DTOG(USB, ep_idx);
|
||||
if (ep_cfg->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_NAK);
|
||||
} else {
|
||||
|
||||
@@ -93,6 +93,7 @@ int usbd_set_address(const uint8_t addr)
|
||||
|
||||
uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
{
|
||||
(void)port;
|
||||
uint8_t speed;
|
||||
|
||||
speed = usb_get_port_speed(g_hpm_udc.handle->regs);
|
||||
@@ -110,26 +111,26 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
usb_endpoint_config_t tmp_ep_cfg;
|
||||
usb_device_handle_t *handle = g_hpm_udc.handle;
|
||||
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_hpm_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_hpm_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_hpm_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_hpm_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_hpm_udc.out_ep[ep_idx].ep_enable = true;
|
||||
} else {
|
||||
g_hpm_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_hpm_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_hpm_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_hpm_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_hpm_udc.in_ep[ep_idx].ep_enable = true;
|
||||
}
|
||||
|
||||
tmp_ep_cfg.xfer = ep_cfg->ep_type;
|
||||
tmp_ep_cfg.ep_addr = ep_cfg->ep_addr;
|
||||
tmp_ep_cfg.max_packet_size = ep_cfg->ep_mps;
|
||||
tmp_ep_cfg.xfer = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
tmp_ep_cfg.ep_addr = ep->bEndpointAddress;
|
||||
tmp_ep_cfg.max_packet_size = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
|
||||
usb_device_edpt_open(handle, &tmp_ep_cfg);
|
||||
return 0;
|
||||
@@ -161,6 +162,9 @@ int usbd_ep_clear_stall(const uint8_t ep)
|
||||
|
||||
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
usb_device_handle_t *handle = g_hpm_udc.handle;
|
||||
|
||||
*stalled = usb_device_edpt_check_stall(handle, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -210,7 +214,7 @@ void USBD_IRQHandler(void)
|
||||
{
|
||||
uint32_t int_status;
|
||||
usb_device_handle_t *handle = g_hpm_udc.handle;
|
||||
uint32_t transfer_len;
|
||||
uint32_t transfer_len = 0;
|
||||
|
||||
/* Acknowledge handled interrupt */
|
||||
int_status = usb_device_status_flags(handle);
|
||||
@@ -263,19 +267,26 @@ void USBD_IRQHandler(void)
|
||||
if (edpt_complete & (1 << ep_idx2bit(ep_idx))) {
|
||||
/* Failed QTD also get ENDPTCOMPLETE set */
|
||||
dcd_qtd_t *p_qtd = usb_device_qtd_get(handle, ep_idx);
|
||||
|
||||
if (p_qtd->halted || p_qtd->xact_err || p_qtd->buffer_err) {
|
||||
} else {
|
||||
/* only number of bytes in the IOC qtd */
|
||||
uint8_t const ep_addr = (ep_idx / 2) | ((ep_idx & 0x01) ? 0x80 : 0);
|
||||
|
||||
transfer_len = p_qtd->expected_bytes - p_qtd->total_bytes;
|
||||
|
||||
if (ep_addr & 0x80) {
|
||||
usbd_event_ep_in_complete_handler(ep_addr, transfer_len);
|
||||
while (1) {
|
||||
if (p_qtd->halted || p_qtd->xact_err || p_qtd->buffer_err) {
|
||||
USB_LOG_ERR("usbd transfer error!\r\n");
|
||||
return;
|
||||
} else {
|
||||
usbd_event_ep_out_complete_handler(ep_addr, transfer_len);
|
||||
transfer_len += p_qtd->expected_bytes - p_qtd->total_bytes;
|
||||
}
|
||||
|
||||
if (p_qtd->next == USB_SOC_DCD_QTD_NEXT_INVALID){
|
||||
break;
|
||||
} else {
|
||||
p_qtd = (dcd_qtd_t *)p_qtd->next;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t const ep_addr = (ep_idx / 2) | ((ep_idx & 0x01) ? 0x80 : 0);
|
||||
if (ep_addr & 0x80) {
|
||||
usbd_event_ep_in_complete_handler(ep_addr, transfer_len);
|
||||
} else {
|
||||
usbd_event_ep_out_complete_handler(ep_addr, transfer_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,8 +294,8 @@ void USBD_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
|
||||
void isr_usb(void)
|
||||
void isr_usbd(void)
|
||||
{
|
||||
USBD_IRQHandler();
|
||||
}
|
||||
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBD_IRQn, isr_usb)
|
||||
SDK_DECLARE_EXT_ISR_M(CONFIG_HPM_USBD_IRQn, isr_usbd)
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
#define HWREGB(x) \
|
||||
(*((volatile uint8_t *)(x)))
|
||||
|
||||
#if defined(CONFIG_USB_MUSB_SUNXI)
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x01c13000)
|
||||
#endif
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler USBD_IRQHandler //use actual usb irq name instead
|
||||
#error "please define USBD_IRQHandler in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USBD_BASE
|
||||
#error "please define USBD_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#define USB_BASE USBD_BASE
|
||||
|
||||
#if defined(CONFIG_USB_MUSB_SUNXI)
|
||||
#define MUSB_FADDR_OFFSET 0x98
|
||||
#define MUSB_POWER_OFFSET 0x40
|
||||
#define MUSB_TXIS_OFFSET 0x44
|
||||
@@ -51,17 +52,8 @@
|
||||
#define MUSB_RXFIFOADD_OFFSET 0x96
|
||||
|
||||
#elif defined(CONFIG_USB_MUSB_CUSTOM)
|
||||
|
||||
#include "musb_custom.h"
|
||||
#else
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler USB_INT_Handler //use actual usb irq name instead
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x40086400UL)
|
||||
#endif
|
||||
|
||||
#define MUSB_FADDR_OFFSET 0x00
|
||||
#define MUSB_POWER_OFFSET 0x01
|
||||
#define MUSB_TXIS_OFFSET 0x02
|
||||
@@ -94,8 +86,8 @@
|
||||
|
||||
#define USB_FIFO_BASE(ep_idx) (USB_BASE + MUSB_FIFO_OFFSET + 0x4 * ep_idx)
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 8
|
||||
#ifndef CONFIG_USBDEV_EP_NUM
|
||||
#define CONFIG_USBDEV_EP_NUM 8
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
@@ -124,8 +116,8 @@ struct musb_udc {
|
||||
volatile uint8_t dev_addr;
|
||||
volatile uint32_t fifo_size_offset;
|
||||
__attribute__((aligned(32))) struct usb_setup_packet setup;
|
||||
struct musb_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct musb_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
struct musb_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
|
||||
struct musb_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
|
||||
} g_musb_udc;
|
||||
|
||||
static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
@@ -270,7 +262,7 @@ int usbd_set_address(const uint8_t addr)
|
||||
|
||||
uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
{
|
||||
uint8_t speed;
|
||||
uint8_t speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
if (HWREGB(USB_BASE + MUSB_POWER_OFFSET) & USB_POWER_HSMODE)
|
||||
speed = USB_SPEED_HIGH;
|
||||
@@ -288,11 +280,11 @@ uint8_t usbd_force_full_speed(const uint8_t port)
|
||||
return (HWREGB(USB_BASE + MUSB_POWER_OFFSET) & USB_POWER_HSENAB);
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint16_t used = 0;
|
||||
uint16_t fifo_size = 0;
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
uint8_t old_ep_idx;
|
||||
uint32_t ui32Flags = 0;
|
||||
uint16_t ui32Register = 0;
|
||||
@@ -307,20 +299,20 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) {
|
||||
USB_LOG_ERR("Ep addr %d overflow\r\n", ep_cfg->ep_addr);
|
||||
if (ep_idx > (CONFIG_USBDEV_EP_NUM - 1)) {
|
||||
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
|
||||
return -1;
|
||||
}
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_musb_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_musb_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_musb_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_musb_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_musb_udc.out_ep[ep_idx].ep_enable = true;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_IND_RXMAP_OFFSET) = ep_cfg->ep_mps;
|
||||
HWREGH(USB_BASE + MUSB_IND_RXMAP_OFFSET) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
|
||||
//
|
||||
// Allow auto clearing of RxPktRdy when packet of size max packet
|
||||
@@ -348,7 +340,7 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
//
|
||||
// Enable isochronous mode if requested.
|
||||
//
|
||||
if (ep_cfg->ep_type == 0x01) {
|
||||
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == 0x01) {
|
||||
ui32Register |= USB_RXCSRH1_ISO;
|
||||
}
|
||||
|
||||
@@ -360,18 +352,18 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
else
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_CLRDT;
|
||||
|
||||
fifo_size = musb_get_fifo_size(ep_cfg->ep_mps, &used);
|
||||
fifo_size = musb_get_fifo_size(USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize), &used);
|
||||
|
||||
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = fifo_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_RXFIFOADD_OFFSET) = (g_musb_udc.fifo_size_offset >> 3);
|
||||
|
||||
g_musb_udc.fifo_size_offset += used;
|
||||
} else {
|
||||
g_musb_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_musb_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_musb_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_musb_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_musb_udc.in_ep[ep_idx].ep_enable = true;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_IND_TXMAP_OFFSET) = ep_cfg->ep_mps;
|
||||
HWREGH(USB_BASE + MUSB_IND_TXMAP_OFFSET) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
|
||||
//
|
||||
// Allow auto setting of TxPktRdy when max packet size has been loaded
|
||||
@@ -393,7 +385,7 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
//
|
||||
// Enable isochronous mode if requested.
|
||||
//
|
||||
if (ep_cfg->ep_type == 0x01) {
|
||||
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == 0x01) {
|
||||
ui32Register |= USB_TXCSRH1_ISO;
|
||||
}
|
||||
|
||||
@@ -405,7 +397,7 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
else
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_CLRDT;
|
||||
|
||||
fifo_size = musb_get_fifo_size(ep_cfg->ep_mps, &used);
|
||||
fifo_size = musb_get_fifo_size(USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize), &used);
|
||||
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = fifo_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = (g_musb_udc.fifo_size_offset >> 3);
|
||||
@@ -492,21 +484,20 @@ int usb_ep_out_data_avail(uint8_t ep_addr)
|
||||
{
|
||||
uint16_t old_ep_idx, length;
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_addr);
|
||||
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (ep_idx == 0){
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_RXRDY)){
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_RXRDY)) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
length = HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET);
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return length;
|
||||
}
|
||||
else{
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) & USB_RXCSRL1_RXRDY)){
|
||||
} else {
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) & USB_RXCSRL1_RXRDY)) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
@@ -520,18 +511,17 @@ int usb_ep_in_data_avail(uint8_t ep_addr)
|
||||
{
|
||||
uint16_t old_ep_idx, length;
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_addr);
|
||||
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (ep_idx == 0){
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_TXRDY){
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_TXRDY) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_TXRDY){
|
||||
} else {
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_TXRDY) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
@@ -544,8 +534,8 @@ int usb_ep_in_data_avail(uint8_t ep_addr)
|
||||
int usb_ep_wait_in_data_avail(uint8_t ep_addr)
|
||||
{
|
||||
uint32_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < 3000; cnt++){
|
||||
|
||||
for (cnt = 0; cnt < 3000; cnt++) {
|
||||
if (usb_ep_in_data_avail(ep_addr))
|
||||
return cnt;
|
||||
}
|
||||
@@ -556,25 +546,24 @@ int usbd_read_packet(uint8_t ep_addr, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint16_t old_ep_idx, cnt;
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_addr);
|
||||
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
if (ep_idx == 0){
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_RXRDY)){
|
||||
if (ep_idx == 0) {
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_CSRL0_RXRDY)) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) & USB_RXCSRL1_RXRDY)){
|
||||
} else {
|
||||
if (!(HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) & USB_RXCSRL1_RXRDY)) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
cnt = usb_ep_out_data_avail(ep_idx);
|
||||
if (cnt){
|
||||
if (cnt) {
|
||||
musb_read_packet(ep_idx, buffer, cnt);
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~(USB_RXCSRL1_OVER | USB_RXCSRL1_ERROR | USB_RXCSRL1_STALL| USB_RXCSRL1_STALLED);
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~(USB_RXCSRL1_OVER | USB_RXCSRL1_ERROR | USB_RXCSRL1_STALL | USB_RXCSRL1_STALLED);
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~(USB_RXCSRL1_RXRDY);
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
}
|
||||
@@ -585,28 +574,28 @@ int usbd_write_packet(uint8_t ep_addr, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint16_t old_ep_idx, cnt;
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_addr);
|
||||
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_UNDRN){
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_UNDRN) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_UNDRN;
|
||||
}
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_TXRDY){
|
||||
if (HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) & USB_TXCSRL1_TXRDY) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!buffer && len){
|
||||
}
|
||||
|
||||
if (!buffer && len) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (!len){
|
||||
|
||||
if (!len) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) |= USB_TXCSRL1_TXRDY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
cnt = usb_ep_in_data_avail(ep_idx);
|
||||
if (cnt){
|
||||
if (cnt) {
|
||||
cnt = MIN(cnt, len);
|
||||
musb_write_packet(ep_idx, buffer, cnt);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) |= USB_TXCSRL1_TXRDY;
|
||||
@@ -649,6 +638,7 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_TXRDY | USB_CSRL0_DATAEND);
|
||||
} else {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
@@ -810,7 +800,7 @@ void USBD_IRQHandler(void)
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = USB_TXIE_EP0;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
|
||||
|
||||
for (uint8_t i = 1; i < USB_NUM_BIDIR_ENDPOINTS; i++) {
|
||||
for (uint8_t i = 1; i < CONFIG_USBDEV_EP_NUM; i++) {
|
||||
musb_set_active_ep(i);
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = 0;
|
||||
|
||||
@@ -14,19 +14,21 @@
|
||||
#define HWREGB(x) \
|
||||
(*((volatile uint8_t *)(x)))
|
||||
|
||||
#ifndef USBH_IRQHandler
|
||||
#error "please define USBH_IRQHandler in usb_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef USBH_BASE
|
||||
#error "please define USBH_BASE in usb_config.h"
|
||||
#endif
|
||||
|
||||
#define USB_BASE USBH_BASE
|
||||
|
||||
#if CONFIG_USBHOST_PIPE_NUM != 4
|
||||
#error musb host ip only supports 4 pipe num
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_SUNXI
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x01c13000)
|
||||
#endif
|
||||
|
||||
#ifndef USBH_IRQHandler
|
||||
#define USBH_IRQHandler USBH_IRQHandler //use actual usb irq name instead
|
||||
#endif
|
||||
|
||||
#define MUSB_FADDR_OFFSET 0x98
|
||||
#define MUSB_POWER_OFFSET 0x40
|
||||
#define MUSB_TXIS_OFFSET 0x44
|
||||
@@ -76,16 +78,8 @@
|
||||
#define USB_RXHUBPORT_BASE(ep_idx) (USB_BASE + MUSB_RXHUBPORTx_OFFSET)
|
||||
|
||||
#elif defined(CONFIG_USB_MUSB_CUSTOM)
|
||||
|
||||
#include "musb_custom.h"
|
||||
#else
|
||||
#ifndef USBH_IRQHandler
|
||||
#define USBH_IRQHandler USB_INT_Handler
|
||||
#endif
|
||||
|
||||
#ifndef USB_BASE
|
||||
#define USB_BASE (0x40086400UL)
|
||||
#endif
|
||||
|
||||
#define MUSB_FADDR_OFFSET 0x00
|
||||
#define MUSB_POWER_OFFSET 0x01
|
||||
#define MUSB_TXIS_OFFSET 0x02
|
||||
@@ -151,17 +145,10 @@ typedef enum {
|
||||
} ep0_state_t;
|
||||
|
||||
struct musb_pipe {
|
||||
uint8_t dev_addr;
|
||||
uint8_t ep_addr;
|
||||
uint8_t ep_type;
|
||||
uint8_t ep_interval;
|
||||
uint8_t speed;
|
||||
uint16_t ep_mps;
|
||||
uint8_t chidx;
|
||||
bool inuse;
|
||||
uint32_t xfrd;
|
||||
volatile bool waiter;
|
||||
usb_osal_sem_t waitsem;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_urb *urb;
|
||||
};
|
||||
|
||||
@@ -169,7 +156,7 @@ struct musb_hcd {
|
||||
volatile bool port_csc;
|
||||
volatile bool port_pec;
|
||||
volatile bool port_pe;
|
||||
struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM][2]; /* Support Bidirectional ep */
|
||||
struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM];
|
||||
} g_musb_hcd;
|
||||
|
||||
static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
@@ -265,91 +252,122 @@ static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
void musb_control_pipe_init(struct musb_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(0);
|
||||
musb_set_active_ep(chidx);
|
||||
|
||||
HWREGB(USB_TXADDR_BASE(0)) = pipe->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = pipe->speed;
|
||||
HWREGB(USB_TXHUBADDR_BASE(0)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(0)) = 0;
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TYPE0_SPEED_HIGH;
|
||||
} else if (urb->hport->speed == USB_SPEED_FULL) {
|
||||
speed = USB_TYPE0_SPEED_FULL;
|
||||
} else if (urb->hport->speed == USB_SPEED_LOW) {
|
||||
speed = USB_TYPE0_SPEED_LOW;
|
||||
}
|
||||
|
||||
musb_write_packet(0, (uint8_t *)setup, 8);
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = speed;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
|
||||
musb_write_packet(chidx, (uint8_t *)setup, 8);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP;
|
||||
musb_set_active_ep(old_ep_index);
|
||||
}
|
||||
|
||||
void musb_bulk_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_bulk_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
uint8_t ep_idx;
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
ep_idx = pipe->ep_addr & 0x7f;
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
musb_set_active_ep(chidx);
|
||||
|
||||
if (pipe->ep_addr & 0x80) {
|
||||
HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK;
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TXTYPE1_SPEED_HIGH;
|
||||
} else if (urb->hport->speed == USB_SPEED_FULL) {
|
||||
speed = USB_TXTYPE1_SPEED_FULL;
|
||||
} else if (urb->hport->speed == USB_SPEED_LOW) {
|
||||
speed = USB_TXTYPE1_SPEED_LOW;
|
||||
}
|
||||
|
||||
if (urb->ep->bEndpointAddress & 0x80) {
|
||||
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = 0;
|
||||
HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0;
|
||||
HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT;
|
||||
} else {
|
||||
HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
|
||||
HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0;
|
||||
|
||||
if (buflen > pipe->ep_mps) {
|
||||
buflen = pipe->ep_mps;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << chidx);
|
||||
} else {
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
|
||||
if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(ep_idx, buffer, buflen);
|
||||
musb_write_packet(chidx, buffer, buflen);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_index);
|
||||
}
|
||||
|
||||
void musb_intr_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen)
|
||||
void musb_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
uint8_t ep_idx;
|
||||
uint8_t old_ep_index;
|
||||
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
|
||||
|
||||
ep_idx = pipe->ep_addr & 0x7f;
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
musb_set_active_ep(chidx);
|
||||
|
||||
if (pipe->ep_addr & 0x80) {
|
||||
HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = pipe->ep_interval;
|
||||
HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0;
|
||||
if (urb->hport->speed == USB_SPEED_HIGH) {
|
||||
speed = USB_TXTYPE1_SPEED_HIGH;
|
||||
} else if (urb->hport->speed == USB_SPEED_FULL) {
|
||||
speed = USB_TXTYPE1_SPEED_FULL;
|
||||
} else if (urb->hport->speed == USB_SPEED_LOW) {
|
||||
speed = USB_TXTYPE1_SPEED_LOW;
|
||||
}
|
||||
|
||||
if (urb->ep->bEndpointAddress & 0x80) {
|
||||
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = urb->ep->bInterval;
|
||||
HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT;
|
||||
} else {
|
||||
HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = pipe->ep_interval;
|
||||
HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0;
|
||||
|
||||
if (buflen > pipe->ep_mps) {
|
||||
buflen = pipe->ep_mps;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << chidx);
|
||||
} else {
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = urb->ep->bInterval;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
|
||||
if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(ep_idx, buffer, buflen);
|
||||
musb_write_packet(chidx, buffer, buflen);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_index);
|
||||
}
|
||||
@@ -379,6 +397,29 @@ static uint8_t usbh_get_port_speed(const uint8_t port)
|
||||
return speed;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int musb_pipe_alloc(void)
|
||||
{
|
||||
int chidx;
|
||||
|
||||
for (chidx = 1; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
|
||||
if (!g_musb_hcd.pipe_pool[chidx].inuse) {
|
||||
g_musb_hcd.pipe_pool[chidx].inuse = true;
|
||||
return chidx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void musb_pipe_free(struct musb_pipe *pipe)
|
||||
{
|
||||
#if 0
|
||||
pipe->inuse = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
__WEAK void usb_hc_low_level_init(void)
|
||||
{
|
||||
}
|
||||
@@ -391,8 +432,7 @@ int usb_hc_init(void)
|
||||
memset(&g_musb_hcd, 0, sizeof(struct musb_hcd));
|
||||
|
||||
for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) {
|
||||
g_musb_hcd.pipe_pool[i][0].waitsem = usb_osal_sem_create(0);
|
||||
g_musb_hcd.pipe_pool[i][1].waitsem = usb_osal_sem_create(0);
|
||||
g_musb_hcd.pipe_pool[i].waitsem = usb_osal_sem_create(0);
|
||||
}
|
||||
|
||||
usb_hc_low_level_init();
|
||||
@@ -434,6 +474,22 @@ int usb_hc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_hc_deinit(void)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_IE_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
|
||||
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_HSENAB;
|
||||
HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) &= ~USB_DEVCTL_SESSION;
|
||||
|
||||
for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) {
|
||||
usb_osal_sem_delete(g_musb_hcd.pipe_pool[i].waitsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
{
|
||||
uint8_t nports;
|
||||
@@ -451,7 +507,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
@@ -461,7 +517,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_FEATURE_HUB_C_OVERCURRENT:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_DESCRIPTOR:
|
||||
@@ -476,7 +532,7 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
switch (setup->bRequest) {
|
||||
case HUB_REQUEST_CLEAR_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
@@ -498,12 +554,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
case HUB_PORT_FEATURE_C_RESET:
|
||||
break;
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_SET_FEATURE:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
switch (setup->wValue) {
|
||||
@@ -516,12 +572,12 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
case HUB_REQUEST_GET_STATUS:
|
||||
if (!port || port > nports) {
|
||||
return -EPIPE;
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
@@ -551,168 +607,79 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult)
|
||||
{
|
||||
struct musb_pipe *ppipe = (struct musb_pipe *)pipe;
|
||||
|
||||
ppipe->dev_addr = dev_addr;
|
||||
ppipe->ep_mps = ep_mps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
|
||||
{
|
||||
struct musb_pipe *ppipe;
|
||||
uint8_t old_ep_index;
|
||||
uint8_t ep_idx;
|
||||
usb_osal_sem_t waitsem;
|
||||
|
||||
ep_idx = ep_cfg->ep_addr & 0x7f;
|
||||
|
||||
if (ep_idx > CONIFG_USB_MUSB_PIPE_NUM) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
old_ep_index = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (ep_cfg->ep_addr & 0x80) {
|
||||
ppipe = &g_musb_hcd.pipe_pool[ep_idx][1];
|
||||
} else {
|
||||
ppipe = &g_musb_hcd.pipe_pool[ep_idx][0];
|
||||
}
|
||||
|
||||
/* store variables */
|
||||
waitsem = ppipe->waitsem;
|
||||
|
||||
memset(ppipe, 0, sizeof(struct musb_pipe));
|
||||
|
||||
ppipe->ep_addr = ep_cfg->ep_addr;
|
||||
ppipe->ep_type = ep_cfg->ep_type;
|
||||
ppipe->ep_mps = ep_cfg->ep_mps;
|
||||
ppipe->ep_interval = ep_cfg->ep_interval;
|
||||
ppipe->speed = ep_cfg->hport->speed;
|
||||
ppipe->dev_addr = ep_cfg->hport->dev_addr;
|
||||
ppipe->hport = ep_cfg->hport;
|
||||
|
||||
if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
if (ppipe->speed == USB_SPEED_HIGH) {
|
||||
ppipe->speed = USB_TYPE0_SPEED_HIGH;
|
||||
} else if (ppipe->speed == USB_SPEED_FULL) {
|
||||
ppipe->speed = USB_TYPE0_SPEED_FULL;
|
||||
} else if (ppipe->speed == USB_SPEED_LOW) {
|
||||
ppipe->speed = USB_TYPE0_SPEED_LOW;
|
||||
}
|
||||
} else {
|
||||
if (ppipe->speed == USB_SPEED_HIGH) {
|
||||
ppipe->speed = USB_TXTYPE1_SPEED_HIGH;
|
||||
} else if (ppipe->speed == USB_SPEED_FULL) {
|
||||
ppipe->speed = USB_TXTYPE1_SPEED_FULL;
|
||||
} else if (ppipe->speed == USB_SPEED_LOW) {
|
||||
ppipe->speed = USB_TXTYPE1_SPEED_LOW;
|
||||
}
|
||||
|
||||
if (ppipe->ep_addr & 0x80) {
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << ep_idx);
|
||||
} else {
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx);
|
||||
}
|
||||
}
|
||||
/* restore variable */
|
||||
ppipe->inuse = true;
|
||||
ppipe->waitsem = waitsem;
|
||||
|
||||
musb_set_active_ep(old_ep_index);
|
||||
*pipe = (usbh_pipe_t)ppipe;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_pipe_free(usbh_pipe_t pipe)
|
||||
{
|
||||
struct musb_pipe *ppipe;
|
||||
struct usbh_urb *urb;
|
||||
|
||||
ppipe = (struct musb_pipe *)pipe;
|
||||
|
||||
if (!ppipe) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
urb = ppipe->urb;
|
||||
|
||||
if (urb) {
|
||||
usbh_kill_urb(urb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_submit_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct musb_pipe *pipe;
|
||||
int chidx;
|
||||
size_t flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!urb) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hport || !urb->ep) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
if (!pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb->hport->connected) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (!pipe->hport->connected) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pipe->urb) {
|
||||
return -EBUSY;
|
||||
if (urb->errorcode == -USB_ERR_BUSY) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
pipe->waiter = false;
|
||||
pipe->xfrd = 0;
|
||||
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
|
||||
chidx = 0;
|
||||
} else {
|
||||
chidx = (urb->ep->bEndpointAddress & 0x0f);
|
||||
|
||||
if (chidx > (CONFIG_USBHOST_PIPE_NUM - 1)) {
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[chidx];
|
||||
pipe->chidx = chidx;
|
||||
pipe->urb = urb;
|
||||
urb->errorcode = -EBUSY;
|
||||
|
||||
urb->hcpriv = pipe;
|
||||
urb->errorcode = -USB_ERR_BUSY;
|
||||
urb->actual_length = 0;
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
pipe->waiter = true;
|
||||
}
|
||||
usb_osal_leave_critical_section(flags);
|
||||
usb_osal_sem_reset(pipe->waitsem);
|
||||
|
||||
switch (pipe->ep_type) {
|
||||
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
musb_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
musb_control_urb_init(0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
musb_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
musb_bulk_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
musb_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
musb_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
if (urb->timeout > 0) {
|
||||
/* wait until timeout or sem give */
|
||||
ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
|
||||
if (ret < 0) {
|
||||
goto errout_timeout;
|
||||
}
|
||||
|
||||
urb->timeout = 0;
|
||||
ret = urb->errorcode;
|
||||
/* we can free pipe when waitsem is done */
|
||||
musb_pipe_free(pipe);
|
||||
}
|
||||
return ret;
|
||||
errout_timeout:
|
||||
pipe->waiter = false;
|
||||
urb->timeout = 0;
|
||||
usbh_kill_urb(urb);
|
||||
return ret;
|
||||
}
|
||||
@@ -720,32 +687,43 @@ errout_timeout:
|
||||
int usbh_kill_urb(struct usbh_urb *urb)
|
||||
{
|
||||
struct musb_pipe *pipe;
|
||||
size_t flags;
|
||||
|
||||
pipe = urb->pipe;
|
||||
|
||||
if (!urb || !pipe) {
|
||||
return -EINVAL;
|
||||
if (!urb || !urb->hcpriv) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
urb->errorcode = -ESHUTDOWN;
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
pipe = (struct musb_pipe *)urb->hcpriv;
|
||||
urb->hcpriv = NULL;
|
||||
pipe->urb = NULL;
|
||||
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
urb->errorcode = -USB_ERR_SHUTDOWN;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
} else {
|
||||
musb_pipe_free(pipe);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void musb_pipe_waitup(struct musb_pipe *pipe)
|
||||
static void musb_urb_waitup(struct usbh_urb *urb)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
struct musb_pipe *pipe;
|
||||
|
||||
urb = pipe->urb;
|
||||
pipe = (struct musb_pipe *)urb->hcpriv;
|
||||
pipe->urb = NULL;
|
||||
urb->hcpriv = NULL;
|
||||
|
||||
if (pipe->waiter) {
|
||||
pipe->waiter = false;
|
||||
if (urb->timeout) {
|
||||
urb->timeout = 0;
|
||||
usb_osal_sem_give(pipe->waitsem);
|
||||
} else {
|
||||
musb_pipe_free(pipe);
|
||||
}
|
||||
|
||||
if (urb->complete) {
|
||||
@@ -764,7 +742,7 @@ void handle_ep0(void)
|
||||
struct usbh_urb *urb;
|
||||
uint32_t size;
|
||||
|
||||
pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0][0];
|
||||
pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0];
|
||||
urb = pipe->urb;
|
||||
if (urb == NULL) {
|
||||
return;
|
||||
@@ -775,23 +753,23 @@ void handle_ep0(void)
|
||||
if (ep0_status & USB_CSRL0_STALLED) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALLED;
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -EPERM;
|
||||
musb_pipe_waitup(pipe);
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
if (ep0_status & USB_CSRL0_ERROR) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_ERROR;
|
||||
musb_fifo_flush(0);
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -EIO;
|
||||
musb_pipe_waitup(pipe);
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
if (ep0_status & USB_CSRL0_STALL) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL;
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
urb->errorcode = -EPERM;
|
||||
musb_pipe_waitup(pipe);
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -805,8 +783,8 @@ void handle_ep0(void)
|
||||
} else {
|
||||
usb_ep0_state = USB_EP0_STATE_OUT_DATA;
|
||||
size = urb->transfer_buffer_length;
|
||||
if (size > pipe->ep_mps) {
|
||||
size = pipe->ep_mps;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(0, urb->transfer_buffer, size);
|
||||
@@ -824,8 +802,8 @@ void handle_ep0(void)
|
||||
case USB_EP0_STATE_IN_DATA:
|
||||
if (ep0_status & USB_CSRL0_RXRDY) {
|
||||
size = urb->transfer_buffer_length;
|
||||
if (size > pipe->ep_mps) {
|
||||
size = pipe->ep_mps;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
|
||||
@@ -835,7 +813,7 @@ void handle_ep0(void)
|
||||
urb->transfer_buffer_length -= size;
|
||||
urb->actual_length += size;
|
||||
|
||||
if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) {
|
||||
if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) {
|
||||
usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_TXRDY | USB_CSRL0_STATUS);
|
||||
} else {
|
||||
@@ -846,8 +824,8 @@ void handle_ep0(void)
|
||||
case USB_EP0_STATE_OUT_DATA:
|
||||
if (urb->transfer_buffer_length > 0) {
|
||||
size = urb->transfer_buffer_length;
|
||||
if (size > pipe->ep_mps) {
|
||||
size = pipe->ep_mps;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
musb_write_packet(0, urb->transfer_buffer, size);
|
||||
@@ -863,13 +841,13 @@ void handle_ep0(void)
|
||||
break;
|
||||
case USB_EP0_STATE_OUT_STATUS:
|
||||
urb->errorcode = 0;
|
||||
musb_pipe_waitup(pipe);
|
||||
musb_urb_waitup(urb);
|
||||
break;
|
||||
case USB_EP0_STATE_IN_STATUS:
|
||||
if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~(USB_CSRL0_RXRDY | USB_CSRL0_STATUS);
|
||||
urb->errorcode = 0;
|
||||
musb_pipe_waitup(pipe);
|
||||
musb_urb_waitup(urb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -939,7 +917,7 @@ void USBH_IRQHandler(void)
|
||||
if (txis & (1 << ep_idx)) {
|
||||
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx);
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx][0];
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx];
|
||||
urb = pipe->urb;
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
@@ -947,21 +925,21 @@ void USBH_IRQHandler(void)
|
||||
|
||||
if (ep_csrl_status & USB_TXCSRL1_ERROR) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_ERROR;
|
||||
urb->errorcode = -EIO;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
musb_urb_waitup(urb);
|
||||
} else if (ep_csrl_status & USB_TXCSRL1_NAKTO) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_NAKTO;
|
||||
urb->errorcode = -EBUSY;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
musb_urb_waitup(urb);
|
||||
} else if (ep_csrl_status & USB_TXCSRL1_STALL) {
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_STALL;
|
||||
urb->errorcode = -EPERM;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
} else {
|
||||
uint32_t size = urb->transfer_buffer_length;
|
||||
|
||||
if (size > pipe->ep_mps) {
|
||||
size = pipe->ep_mps;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
|
||||
urb->transfer_buffer += size;
|
||||
@@ -969,8 +947,9 @@ void USBH_IRQHandler(void)
|
||||
urb->actual_length += size;
|
||||
|
||||
if (urb->transfer_buffer_length == 0) {
|
||||
//HWREGH(USB_BASE + MUSB_TXIE_OFFSET) &= ~(1 << ep_idx);
|
||||
urb->errorcode = 0;
|
||||
goto pipe_wait;
|
||||
musb_urb_waitup(urb);
|
||||
} else {
|
||||
musb_write_packet(ep_idx, urb->transfer_buffer, size);
|
||||
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
|
||||
@@ -984,7 +963,7 @@ void USBH_IRQHandler(void)
|
||||
if (rxis & (1 << ep_idx)) {
|
||||
HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx); // clear isr flag
|
||||
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx][1];
|
||||
pipe = &g_musb_hcd.pipe_pool[ep_idx];
|
||||
urb = pipe->urb;
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
@@ -993,20 +972,20 @@ void USBH_IRQHandler(void)
|
||||
|
||||
if (ep_csrl_status & USB_RXCSRL1_ERROR) {
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_ERROR;
|
||||
urb->errorcode = -EIO;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_IO;
|
||||
musb_urb_waitup(urb);
|
||||
} else if (ep_csrl_status & USB_RXCSRL1_NAKTO) {
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_NAKTO;
|
||||
urb->errorcode = -EBUSY;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_NAK;
|
||||
musb_urb_waitup(urb);
|
||||
} else if (ep_csrl_status & USB_RXCSRL1_STALL) {
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_STALL;
|
||||
urb->errorcode = -EPERM;
|
||||
goto pipe_wait;
|
||||
urb->errorcode = -USB_ERR_STALL;
|
||||
musb_urb_waitup(urb);
|
||||
} else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {
|
||||
uint32_t size = urb->transfer_buffer_length;
|
||||
if (size > pipe->ep_mps) {
|
||||
size = pipe->ep_mps;
|
||||
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
}
|
||||
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
|
||||
|
||||
@@ -1018,9 +997,10 @@ void USBH_IRQHandler(void)
|
||||
urb->transfer_buffer_length -= size;
|
||||
urb->actual_length += size;
|
||||
|
||||
if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) {
|
||||
if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) {
|
||||
//HWREGH(USB_BASE + MUSB_RXIE_OFFSET) &= ~(1 << ep_idx);
|
||||
urb->errorcode = 0;
|
||||
goto pipe_wait;
|
||||
musb_urb_waitup(urb);
|
||||
} else {
|
||||
HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT;
|
||||
}
|
||||
@@ -1028,8 +1008,4 @@ void USBH_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return;
|
||||
pipe_wait:
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
musb_pipe_waitup(pipe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# Note
|
||||
|
||||
## Support Chip List
|
||||
|
||||
- NRF5x
|
||||
|
||||
## Before Use
|
||||
|
||||
- Your should implement `usb_dc_low_level_pre_init`,`usb_dc_low_level_post_init`,`usb_dc_low_level_deinit`.
|
||||
@@ -1,605 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#define __IM volatile const /*! Defines 'read only' structure member permissions */
|
||||
#define __OM volatile /*! Defines 'write only' structure member permissions */
|
||||
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
|
||||
|
||||
/**
|
||||
* @brief USBD_HALTED [HALTED] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IM uint32_t EPIN[8]; /*!< (@ 0x00000000) Description collection: IN endpoint halted status.
|
||||
Can be used as is as response to a GetStatus()
|
||||
request to endpoint. */
|
||||
__IM uint32_t RESERVED;
|
||||
__IM uint32_t EPOUT[8]; /*!< (@ 0x00000024) Description collection: OUT endpoint halted status.
|
||||
Can be used as is as response to a GetStatus()
|
||||
request to endpoint. */
|
||||
} USBD_HALTED_Type; /*!< Size = 68 (0x44) */
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_SIZE [SIZE] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IOM uint32_t EPOUT[8]; /*!< (@ 0x00000000) Description collection: Number of bytes received
|
||||
last in the data stage of this OUT endpoint */
|
||||
__IM uint32_t ISOOUT; /*!< (@ 0x00000020) Number of bytes received last on this ISO OUT
|
||||
data endpoint */
|
||||
} USBD_SIZE_Type; /*!< Size = 36 (0x24) */
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_EPIN [EPIN] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IOM uint32_t PTR; /*!< (@ 0x00000000) Description cluster: Data pointer */
|
||||
__IOM uint32_t MAXCNT; /*!< (@ 0x00000004) Description cluster: Maximum number of bytes
|
||||
to transfer */
|
||||
__IM uint32_t AMOUNT; /*!< (@ 0x00000008) Description cluster: Number of bytes transferred
|
||||
in the last transaction */
|
||||
__IM uint32_t RESERVED[2];
|
||||
} USBD_EPIN_Type; /*!< Size = 20 (0x14) */
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_ISOIN [ISOIN] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IOM uint32_t PTR; /*!< (@ 0x00000000) Data pointer */
|
||||
__IOM uint32_t MAXCNT; /*!< (@ 0x00000004) Maximum number of bytes to transfer */
|
||||
__IM uint32_t AMOUNT; /*!< (@ 0x00000008) Number of bytes transferred in the last transaction */
|
||||
} USBD_ISOIN_Type; /*!< Size = 12 (0xc) */
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_EPOUT [EPOUT] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IOM uint32_t PTR; /*!< (@ 0x00000000) Description cluster: Data pointer */
|
||||
__IOM uint32_t MAXCNT; /*!< (@ 0x00000004) Description cluster: Maximum number of bytes
|
||||
to transfer */
|
||||
__IM uint32_t AMOUNT; /*!< (@ 0x00000008) Description cluster: Number of bytes transferred
|
||||
in the last transaction */
|
||||
__IM uint32_t RESERVED[2];
|
||||
} USBD_EPOUT_Type; /*!< Size = 20 (0x14) */
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_ISOOUT [ISOOUT] (Unspecified)
|
||||
*/
|
||||
typedef struct {
|
||||
__IOM uint32_t PTR; /*!< (@ 0x00000000) Data pointer */
|
||||
__IOM uint32_t MAXCNT; /*!< (@ 0x00000004) Maximum number of bytes to transfer */
|
||||
__IM uint32_t AMOUNT; /*!< (@ 0x00000008) Number of bytes transferred in the last transaction */
|
||||
} USBD_ISOOUT_Type; /*!< Size = 12 (0xc) */
|
||||
|
||||
typedef struct { /*!< (@ 0x40027000) USBD Structure */
|
||||
__IM uint32_t RESERVED;
|
||||
__OM uint32_t TASKS_STARTEPIN[8]; /*!< (@ 0x00000004) Description collection: Captures the EPIN[n].PTR
|
||||
and EPIN[n].MAXCNT registers values, and
|
||||
enables endpoint IN n to respond to traffic
|
||||
from host */
|
||||
__OM uint32_t TASKS_STARTISOIN; /*!< (@ 0x00000024) Captures the ISOIN.PTR and ISOIN.MAXCNT registers
|
||||
values, and enables sending data on ISO
|
||||
endpoint */
|
||||
__OM uint32_t TASKS_STARTEPOUT[8]; /*!< (@ 0x00000028) Description collection: Captures the EPOUT[n].PTR
|
||||
and EPOUT[n].MAXCNT registers values, and
|
||||
enables endpoint n to respond to traffic
|
||||
from host */
|
||||
__OM uint32_t TASKS_STARTISOOUT; /*!< (@ 0x00000048) Captures the ISOOUT.PTR and ISOOUT.MAXCNT registers
|
||||
values, and enables receiving of data on
|
||||
ISO endpoint */
|
||||
__OM uint32_t TASKS_EP0RCVOUT; /*!< (@ 0x0000004C) Allows OUT data stage on control endpoint 0 */
|
||||
__OM uint32_t TASKS_EP0STATUS; /*!< (@ 0x00000050) Allows status stage on control endpoint 0 */
|
||||
__OM uint32_t TASKS_EP0STALL; /*!< (@ 0x00000054) Stalls data and status stage on control endpoint
|
||||
0 */
|
||||
__OM uint32_t TASKS_DPDMDRIVE; /*!< (@ 0x00000058) Forces D+ and D- lines into the state defined
|
||||
in the DPDMVALUE register */
|
||||
__OM uint32_t TASKS_DPDMNODRIVE; /*!< (@ 0x0000005C) Stops forcing D+ and D- lines into any state
|
||||
(USB engine takes control) */
|
||||
__IM uint32_t RESERVED1[40];
|
||||
__IOM uint32_t EVENTS_USBRESET; /*!< (@ 0x00000100) Signals that a USB reset condition has been detected
|
||||
on USB lines */
|
||||
__IOM uint32_t EVENTS_STARTED; /*!< (@ 0x00000104) Confirms that the EPIN[n].PTR and EPIN[n].MAXCNT,
|
||||
or EPOUT[n].PTR and EPOUT[n].MAXCNT registers
|
||||
have been captured on all endpoints reported
|
||||
in the EPSTATUS register */
|
||||
__IOM uint32_t EVENTS_ENDEPIN[8]; /*!< (@ 0x00000108) Description collection: The whole EPIN[n] buffer
|
||||
has been consumed. The RAM buffer can be
|
||||
accessed safely by software. */
|
||||
__IOM uint32_t EVENTS_EP0DATADONE; /*!< (@ 0x00000128) An acknowledged data transfer has taken place
|
||||
on the control endpoint */
|
||||
__IOM uint32_t EVENTS_ENDISOIN; /*!< (@ 0x0000012C) The whole ISOIN buffer has been consumed. The
|
||||
RAM buffer can be accessed safely by software. */
|
||||
__IOM uint32_t EVENTS_ENDEPOUT[8]; /*!< (@ 0x00000130) Description collection: The whole EPOUT[n] buffer
|
||||
has been consumed. The RAM buffer can be
|
||||
accessed safely by software. */
|
||||
__IOM uint32_t EVENTS_ENDISOOUT; /*!< (@ 0x00000150) The whole ISOOUT buffer has been consumed. The
|
||||
RAM buffer can be accessed safely by software. */
|
||||
__IOM uint32_t EVENTS_SOF; /*!< (@ 0x00000154) Signals that a SOF (start of frame) condition
|
||||
has been detected on USB lines */
|
||||
__IOM uint32_t EVENTS_USBEVENT; /*!< (@ 0x00000158) An event or an error not covered by specific
|
||||
events has occurred. Check EVENTCAUSE register
|
||||
to find the cause. */
|
||||
__IOM uint32_t EVENTS_EP0SETUP; /*!< (@ 0x0000015C) A valid SETUP token has been received (and acknowledged)
|
||||
on the control endpoint */
|
||||
__IOM uint32_t EVENTS_EPDATA; /*!< (@ 0x00000160) A data transfer has occurred on a data endpoint,
|
||||
indicated by the EPDATASTATUS register */
|
||||
__IM uint32_t RESERVED2[39];
|
||||
__IOM uint32_t SHORTS; /*!< (@ 0x00000200) Shortcuts between local events and tasks */
|
||||
__IM uint32_t RESERVED3[63];
|
||||
__IOM uint32_t INTEN; /*!< (@ 0x00000300) Enable or disable interrupt */
|
||||
__IOM uint32_t INTENSET; /*!< (@ 0x00000304) Enable interrupt */
|
||||
__IOM uint32_t INTENCLR; /*!< (@ 0x00000308) Disable interrupt */
|
||||
__IM uint32_t RESERVED4[61];
|
||||
__IOM uint32_t EVENTCAUSE; /*!< (@ 0x00000400) Details on what caused the USBEVENT event */
|
||||
__IM uint32_t RESERVED5[7];
|
||||
__IOM USBD_HALTED_Type HALTED; /*!< (@ 0x00000420) Unspecified */
|
||||
__IM uint32_t RESERVED6;
|
||||
__IOM uint32_t EPSTATUS; /*!< (@ 0x00000468) Provides information on which endpoint's EasyDMA
|
||||
registers have been captured */
|
||||
__IOM uint32_t EPDATASTATUS; /*!< (@ 0x0000046C) Provides information on which endpoint(s) an
|
||||
acknowledged data transfer has occurred
|
||||
(EPDATA event) */
|
||||
__IM uint32_t USBADDR; /*!< (@ 0x00000470) Device USB address */
|
||||
__IM uint32_t RESERVED7[3];
|
||||
__IM uint32_t BMREQUESTTYPE; /*!< (@ 0x00000480) SETUP data, byte 0, bmRequestType */
|
||||
__IM uint32_t BREQUEST; /*!< (@ 0x00000484) SETUP data, byte 1, bRequest */
|
||||
__IM uint32_t WVALUEL; /*!< (@ 0x00000488) SETUP data, byte 2, LSB of wValue */
|
||||
__IM uint32_t WVALUEH; /*!< (@ 0x0000048C) SETUP data, byte 3, MSB of wValue */
|
||||
__IM uint32_t WINDEXL; /*!< (@ 0x00000490) SETUP data, byte 4, LSB of wIndex */
|
||||
__IM uint32_t WINDEXH; /*!< (@ 0x00000494) SETUP data, byte 5, MSB of wIndex */
|
||||
__IM uint32_t WLENGTHL; /*!< (@ 0x00000498) SETUP data, byte 6, LSB of wLength */
|
||||
__IM uint32_t WLENGTHH; /*!< (@ 0x0000049C) SETUP data, byte 7, MSB of wLength */
|
||||
__IOM USBD_SIZE_Type SIZE; /*!< (@ 0x000004A0) Unspecified */
|
||||
__IM uint32_t RESERVED8[15];
|
||||
__IOM uint32_t ENABLE; /*!< (@ 0x00000500) Enable USB */
|
||||
__IOM uint32_t USBPULLUP; /*!< (@ 0x00000504) Control of the USB pull-up */
|
||||
__IOM uint32_t DPDMVALUE; /*!< (@ 0x00000508) State D+ and D- lines will be forced into by
|
||||
the DPDMDRIVE task. The DPDMNODRIVE task
|
||||
reverts the control of the lines to MAC
|
||||
IP (no forcing). */
|
||||
__IOM uint32_t DTOGGLE; /*!< (@ 0x0000050C) Data toggle control and status */
|
||||
__IOM uint32_t EPINEN; /*!< (@ 0x00000510) Endpoint IN enable */
|
||||
__IOM uint32_t EPOUTEN; /*!< (@ 0x00000514) Endpoint OUT enable */
|
||||
__OM uint32_t EPSTALL; /*!< (@ 0x00000518) STALL endpoints */
|
||||
__IOM uint32_t ISOSPLIT; /*!< (@ 0x0000051C) Controls the split of ISO buffers */
|
||||
__IM uint32_t FRAMECNTR; /*!< (@ 0x00000520) Returns the current value of the start of frame
|
||||
counter */
|
||||
__IM uint32_t RESERVED9[2];
|
||||
__IOM uint32_t LOWPOWER; /*!< (@ 0x0000052C) Controls USBD peripheral low power mode during
|
||||
USB suspend */
|
||||
__IOM uint32_t ISOINCONFIG; /*!< (@ 0x00000530) Controls the response of the ISO IN endpoint
|
||||
to an IN token when no data is ready to
|
||||
be sent */
|
||||
__IM uint32_t RESERVED10[51];
|
||||
__IOM USBD_EPIN_Type EPIN[8]; /*!< (@ 0x00000600) Unspecified */
|
||||
__IOM USBD_ISOIN_Type ISOIN; /*!< (@ 0x000006A0) Unspecified */
|
||||
__IM uint32_t RESERVED11[21];
|
||||
__IOM USBD_EPOUT_Type EPOUT[8]; /*!< (@ 0x00000700) Unspecified */
|
||||
__IOM USBD_ISOOUT_Type ISOOUT; /*!< (@ 0x000007A0) Unspecified */
|
||||
} NRF_USBD_Type; /*!< Size = 1964 (0x7ac) */
|
||||
|
||||
|
||||
/* Register: USBD_EPINEN */
|
||||
/* Description: Endpoint IN enable */
|
||||
|
||||
/* Bit 8 : Enable ISO IN endpoint */
|
||||
#define USBD_EPINEN_ISOIN_Pos (8UL) /*!< Position of ISOIN field. */
|
||||
#define USBD_EPINEN_ISOIN_Msk (0x1UL << USBD_EPINEN_ISOIN_Pos) /*!< Bit mask of ISOIN field. */
|
||||
#define USBD_EPINEN_ISOIN_Disable (0UL) /*!< Disable ISO IN endpoint 8 */
|
||||
#define USBD_EPINEN_ISOIN_Enable (1UL) /*!< Enable ISO IN endpoint 8 */
|
||||
|
||||
/* Bit 7 : Enable IN endpoint 7 */
|
||||
#define USBD_EPINEN_IN7_Pos (7UL) /*!< Position of IN7 field. */
|
||||
#define USBD_EPINEN_IN7_Msk (0x1UL << USBD_EPINEN_IN7_Pos) /*!< Bit mask of IN7 field. */
|
||||
#define USBD_EPINEN_IN7_Disable (0UL) /*!< Disable IN endpoint 7 */
|
||||
#define USBD_EPINEN_IN7_Enable (1UL) /*!< Enable IN endpoint 7 */
|
||||
|
||||
/* Bit 6 : Enable IN endpoint 6 */
|
||||
#define USBD_EPINEN_IN6_Pos (6UL) /*!< Position of IN6 field. */
|
||||
#define USBD_EPINEN_IN6_Msk (0x1UL << USBD_EPINEN_IN6_Pos) /*!< Bit mask of IN6 field. */
|
||||
#define USBD_EPINEN_IN6_Disable (0UL) /*!< Disable endpoint IN 6 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN6_Enable (1UL) /*!< Enable endpoint IN 6 (response to IN tokens) */
|
||||
|
||||
/* Bit 5 : Enable IN endpoint 5 */
|
||||
#define USBD_EPINEN_IN5_Pos (5UL) /*!< Position of IN5 field. */
|
||||
#define USBD_EPINEN_IN5_Msk (0x1UL << USBD_EPINEN_IN5_Pos) /*!< Bit mask of IN5 field. */
|
||||
#define USBD_EPINEN_IN5_Disable (0UL) /*!< Disable endpoint IN 5 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN5_Enable (1UL) /*!< Enable endpoint IN 5 (response to IN tokens) */
|
||||
|
||||
/* Bit 4 : Enable IN endpoint 4 */
|
||||
#define USBD_EPINEN_IN4_Pos (4UL) /*!< Position of IN4 field. */
|
||||
#define USBD_EPINEN_IN4_Msk (0x1UL << USBD_EPINEN_IN4_Pos) /*!< Bit mask of IN4 field. */
|
||||
#define USBD_EPINEN_IN4_Disable (0UL) /*!< Disable endpoint IN 4 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN4_Enable (1UL) /*!< Enable endpoint IN 4 (response to IN tokens) */
|
||||
|
||||
/* Bit 3 : Enable IN endpoint 3 */
|
||||
#define USBD_EPINEN_IN3_Pos (3UL) /*!< Position of IN3 field. */
|
||||
#define USBD_EPINEN_IN3_Msk (0x1UL << USBD_EPINEN_IN3_Pos) /*!< Bit mask of IN3 field. */
|
||||
#define USBD_EPINEN_IN3_Disable (0UL) /*!< Disable endpoint IN 3 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN3_Enable (1UL) /*!< Enable endpoint IN 3 (response to IN tokens) */
|
||||
|
||||
/* Bit 2 : Enable IN endpoint 2 */
|
||||
#define USBD_EPINEN_IN2_Pos (2UL) /*!< Position of IN2 field. */
|
||||
#define USBD_EPINEN_IN2_Msk (0x1UL << USBD_EPINEN_IN2_Pos) /*!< Bit mask of IN2 field. */
|
||||
#define USBD_EPINEN_IN2_Disable (0UL) /*!< Disable endpoint IN 2 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN2_Enable (1UL) /*!< Enable endpoint IN 2 (response to IN tokens) */
|
||||
|
||||
/* Bit 1 : Enable IN endpoint 1 */
|
||||
#define USBD_EPINEN_IN1_Pos (1UL) /*!< Position of IN1 field. */
|
||||
#define USBD_EPINEN_IN1_Msk (0x1UL << USBD_EPINEN_IN1_Pos) /*!< Bit mask of IN1 field. */
|
||||
#define USBD_EPINEN_IN1_Disable (0UL) /*!< Disable endpoint IN 1 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN1_Enable (1UL) /*!< Enable endpoint IN 1 (response to IN tokens) */
|
||||
|
||||
/* Bit 0 : Enable IN endpoint 0 */
|
||||
#define USBD_EPINEN_IN0_Pos (0UL) /*!< Position of IN0 field. */
|
||||
#define USBD_EPINEN_IN0_Msk (0x1UL << USBD_EPINEN_IN0_Pos) /*!< Bit mask of IN0 field. */
|
||||
#define USBD_EPINEN_IN0_Disable (0UL) /*!< Disable endpoint IN 0 (no response to IN tokens) */
|
||||
#define USBD_EPINEN_IN0_Enable (1UL) /*!< Enable endpoint IN 0 (response to IN tokens) */
|
||||
|
||||
/* Register: USBD_EPOUTEN */
|
||||
/* Description: Endpoint OUT enable */
|
||||
|
||||
/* Bit 8 : Enable ISO OUT endpoint 8 */
|
||||
#define USBD_EPOUTEN_ISOOUT_Pos (8UL) /*!< Position of ISOOUT field. */
|
||||
#define USBD_EPOUTEN_ISOOUT_Msk (0x1UL << USBD_EPOUTEN_ISOOUT_Pos) /*!< Bit mask of ISOOUT field. */
|
||||
#define USBD_EPOUTEN_ISOOUT_Disable (0UL) /*!< Disable ISO OUT endpoint 8 */
|
||||
#define USBD_EPOUTEN_ISOOUT_Enable (1UL) /*!< Enable ISO OUT endpoint 8 */
|
||||
|
||||
/* Bit 7 : Enable OUT endpoint 7 */
|
||||
#define USBD_EPOUTEN_OUT7_Pos (7UL) /*!< Position of OUT7 field. */
|
||||
#define USBD_EPOUTEN_OUT7_Msk (0x1UL << USBD_EPOUTEN_OUT7_Pos) /*!< Bit mask of OUT7 field. */
|
||||
#define USBD_EPOUTEN_OUT7_Disable (0UL) /*!< Disable endpoint OUT 7 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT7_Enable (1UL) /*!< Enable endpoint OUT 7 (response to OUT tokens) */
|
||||
|
||||
/* Bit 6 : Enable OUT endpoint 6 */
|
||||
#define USBD_EPOUTEN_OUT6_Pos (6UL) /*!< Position of OUT6 field. */
|
||||
#define USBD_EPOUTEN_OUT6_Msk (0x1UL << USBD_EPOUTEN_OUT6_Pos) /*!< Bit mask of OUT6 field. */
|
||||
#define USBD_EPOUTEN_OUT6_Disable (0UL) /*!< Disable endpoint OUT 6 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT6_Enable (1UL) /*!< Enable endpoint OUT 6 (response to OUT tokens) */
|
||||
|
||||
/* Bit 5 : Enable OUT endpoint 5 */
|
||||
#define USBD_EPOUTEN_OUT5_Pos (5UL) /*!< Position of OUT5 field. */
|
||||
#define USBD_EPOUTEN_OUT5_Msk (0x1UL << USBD_EPOUTEN_OUT5_Pos) /*!< Bit mask of OUT5 field. */
|
||||
#define USBD_EPOUTEN_OUT5_Disable (0UL) /*!< Disable endpoint OUT 5 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT5_Enable (1UL) /*!< Enable endpoint OUT 5 (response to OUT tokens) */
|
||||
|
||||
/* Bit 4 : Enable OUT endpoint 4 */
|
||||
#define USBD_EPOUTEN_OUT4_Pos (4UL) /*!< Position of OUT4 field. */
|
||||
#define USBD_EPOUTEN_OUT4_Msk (0x1UL << USBD_EPOUTEN_OUT4_Pos) /*!< Bit mask of OUT4 field. */
|
||||
#define USBD_EPOUTEN_OUT4_Disable (0UL) /*!< Disable endpoint OUT 4 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT4_Enable (1UL) /*!< Enable endpoint OUT 4 (response to OUT tokens) */
|
||||
|
||||
/* Bit 3 : Enable OUT endpoint 3 */
|
||||
#define USBD_EPOUTEN_OUT3_Pos (3UL) /*!< Position of OUT3 field. */
|
||||
#define USBD_EPOUTEN_OUT3_Msk (0x1UL << USBD_EPOUTEN_OUT3_Pos) /*!< Bit mask of OUT3 field. */
|
||||
#define USBD_EPOUTEN_OUT3_Disable (0UL) /*!< Disable endpoint OUT 3 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT3_Enable (1UL) /*!< Enable endpoint OUT 3 (response to OUT tokens) */
|
||||
|
||||
/* Bit 2 : Enable OUT endpoint 2 */
|
||||
#define USBD_EPOUTEN_OUT2_Pos (2UL) /*!< Position of OUT2 field. */
|
||||
#define USBD_EPOUTEN_OUT2_Msk (0x1UL << USBD_EPOUTEN_OUT2_Pos) /*!< Bit mask of OUT2 field. */
|
||||
#define USBD_EPOUTEN_OUT2_Disable (0UL) /*!< Disable endpoint OUT 2 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT2_Enable (1UL) /*!< Enable endpoint OUT 2 (response to OUT tokens) */
|
||||
|
||||
/* Bit 1 : Enable OUT endpoint 1 */
|
||||
#define USBD_EPOUTEN_OUT1_Pos (1UL) /*!< Position of OUT1 field. */
|
||||
#define USBD_EPOUTEN_OUT1_Msk (0x1UL << USBD_EPOUTEN_OUT1_Pos) /*!< Bit mask of OUT1 field. */
|
||||
#define USBD_EPOUTEN_OUT1_Disable (0UL) /*!< Disable endpoint OUT 1 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT1_Enable (1UL) /*!< Enable endpoint OUT 1 (response to OUT tokens) */
|
||||
|
||||
/* Bit 0 : Enable OUT endpoint 0 */
|
||||
#define USBD_EPOUTEN_OUT0_Pos (0UL) /*!< Position of OUT0 field. */
|
||||
#define USBD_EPOUTEN_OUT0_Msk (0x1UL << USBD_EPOUTEN_OUT0_Pos) /*!< Bit mask of OUT0 field. */
|
||||
#define USBD_EPOUTEN_OUT0_Disable (0UL) /*!< Disable endpoint OUT 0 (no response to OUT tokens) */
|
||||
#define USBD_EPOUTEN_OUT0_Enable (1UL) /*!< Enable endpoint OUT 0 (response to OUT tokens) */
|
||||
|
||||
/* Register: USBD_INTEN */
|
||||
/* Description: Enable or disable interrupt */
|
||||
|
||||
/* Bit 24 : Enable or disable interrupt for event EPDATA */
|
||||
#define USBD_INTEN_EPDATA_Pos (24UL) /*!< Position of EPDATA field. */
|
||||
#define USBD_INTEN_EPDATA_Msk (0x1UL << USBD_INTEN_EPDATA_Pos) /*!< Bit mask of EPDATA field. */
|
||||
#define USBD_INTEN_EPDATA_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_EPDATA_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 23 : Enable or disable interrupt for event EP0SETUP */
|
||||
#define USBD_INTEN_EP0SETUP_Pos (23UL) /*!< Position of EP0SETUP field. */
|
||||
#define USBD_INTEN_EP0SETUP_Msk (0x1UL << USBD_INTEN_EP0SETUP_Pos) /*!< Bit mask of EP0SETUP field. */
|
||||
#define USBD_INTEN_EP0SETUP_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_EP0SETUP_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 22 : Enable or disable interrupt for event USBEVENT */
|
||||
#define USBD_INTEN_USBEVENT_Pos (22UL) /*!< Position of USBEVENT field. */
|
||||
#define USBD_INTEN_USBEVENT_Msk (0x1UL << USBD_INTEN_USBEVENT_Pos) /*!< Bit mask of USBEVENT field. */
|
||||
#define USBD_INTEN_USBEVENT_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_USBEVENT_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 21 : Enable or disable interrupt for event SOF */
|
||||
#define USBD_INTEN_SOF_Pos (21UL) /*!< Position of SOF field. */
|
||||
#define USBD_INTEN_SOF_Msk (0x1UL << USBD_INTEN_SOF_Pos) /*!< Bit mask of SOF field. */
|
||||
#define USBD_INTEN_SOF_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_SOF_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 20 : Enable or disable interrupt for event ENDISOOUT */
|
||||
#define USBD_INTEN_ENDISOOUT_Pos (20UL) /*!< Position of ENDISOOUT field. */
|
||||
#define USBD_INTEN_ENDISOOUT_Msk (0x1UL << USBD_INTEN_ENDISOOUT_Pos) /*!< Bit mask of ENDISOOUT field. */
|
||||
#define USBD_INTEN_ENDISOOUT_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDISOOUT_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 19 : Enable or disable interrupt for event ENDEPOUT[7] */
|
||||
#define USBD_INTEN_ENDEPOUT7_Pos (19UL) /*!< Position of ENDEPOUT7 field. */
|
||||
#define USBD_INTEN_ENDEPOUT7_Msk (0x1UL << USBD_INTEN_ENDEPOUT7_Pos) /*!< Bit mask of ENDEPOUT7 field. */
|
||||
#define USBD_INTEN_ENDEPOUT7_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDEPOUT7_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 13 : Enable or disable interrupt for event ENDEPOUT[1] */
|
||||
#define USBD_INTEN_ENDEPOUT1_Pos (13UL) /*!< Position of ENDEPOUT1 field. */
|
||||
#define USBD_INTEN_ENDEPOUT1_Msk (0x1UL << USBD_INTEN_ENDEPOUT1_Pos) /*!< Bit mask of ENDEPOUT1 field. */
|
||||
#define USBD_INTEN_ENDEPOUT1_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDEPOUT1_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 12 : Enable or disable interrupt for event ENDEPOUT[0] */
|
||||
#define USBD_INTEN_ENDEPOUT0_Pos (12UL) /*!< Position of ENDEPOUT0 field. */
|
||||
#define USBD_INTEN_ENDEPOUT0_Msk (0x1UL << USBD_INTEN_ENDEPOUT0_Pos) /*!< Bit mask of ENDEPOUT0 field. */
|
||||
#define USBD_INTEN_ENDEPOUT0_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDEPOUT0_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 11 : Enable or disable interrupt for event ENDISOIN */
|
||||
#define USBD_INTEN_ENDISOIN_Pos (11UL) /*!< Position of ENDISOIN field. */
|
||||
#define USBD_INTEN_ENDISOIN_Msk (0x1UL << USBD_INTEN_ENDISOIN_Pos) /*!< Bit mask of ENDISOIN field. */
|
||||
#define USBD_INTEN_ENDISOIN_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDISOIN_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 10 : Enable or disable interrupt for event EP0DATADONE */
|
||||
#define USBD_INTEN_EP0DATADONE_Pos (10UL) /*!< Position of EP0DATADONE field. */
|
||||
#define USBD_INTEN_EP0DATADONE_Msk (0x1UL << USBD_INTEN_EP0DATADONE_Pos) /*!< Bit mask of EP0DATADONE field. */
|
||||
#define USBD_INTEN_EP0DATADONE_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_EP0DATADONE_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 3 : Enable or disable interrupt for event ENDEPIN[1] */
|
||||
#define USBD_INTEN_ENDEPIN1_Pos (3UL) /*!< Position of ENDEPIN1 field. */
|
||||
#define USBD_INTEN_ENDEPIN1_Msk (0x1UL << USBD_INTEN_ENDEPIN1_Pos) /*!< Bit mask of ENDEPIN1 field. */
|
||||
#define USBD_INTEN_ENDEPIN1_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDEPIN1_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 2 : Enable or disable interrupt for event ENDEPIN[0] */
|
||||
#define USBD_INTEN_ENDEPIN0_Pos (2UL) /*!< Position of ENDEPIN0 field. */
|
||||
#define USBD_INTEN_ENDEPIN0_Msk (0x1UL << USBD_INTEN_ENDEPIN0_Pos) /*!< Bit mask of ENDEPIN0 field. */
|
||||
#define USBD_INTEN_ENDEPIN0_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_ENDEPIN0_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 1 : Enable or disable interrupt for event STARTED */
|
||||
#define USBD_INTEN_STARTED_Pos (1UL) /*!< Position of STARTED field. */
|
||||
#define USBD_INTEN_STARTED_Msk (0x1UL << USBD_INTEN_STARTED_Pos) /*!< Bit mask of STARTED field. */
|
||||
#define USBD_INTEN_STARTED_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_STARTED_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 0 : Enable or disable interrupt for event USBRESET */
|
||||
#define USBD_INTEN_USBRESET_Pos (0UL) /*!< Position of USBRESET field. */
|
||||
#define USBD_INTEN_USBRESET_Msk (0x1UL << USBD_INTEN_USBRESET_Pos) /*!< Bit mask of USBRESET field. */
|
||||
#define USBD_INTEN_USBRESET_Disabled (0UL) /*!< Disable */
|
||||
#define USBD_INTEN_USBRESET_Enabled (1UL) /*!< Enable */
|
||||
|
||||
/* Register: USBD_INTENSET */
|
||||
/* Description: Enable interrupt */
|
||||
|
||||
/* Bit 21 : Write '1' to enable interrupt for event SOF */
|
||||
#define USBD_INTENSET_SOF_Pos (21UL) /*!< Position of SOF field. */
|
||||
#define USBD_INTENSET_SOF_Msk (0x1UL << USBD_INTENSET_SOF_Pos) /*!< Bit mask of SOF field. */
|
||||
#define USBD_INTENSET_SOF_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENSET_SOF_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENSET_SOF_Set (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 20 : Write '1' to enable interrupt for event ENDISOOUT */
|
||||
#define USBD_INTENSET_ENDISOOUT_Pos (20UL) /*!< Position of ENDISOOUT field. */
|
||||
#define USBD_INTENSET_ENDISOOUT_Msk (0x1UL << USBD_INTENSET_ENDISOOUT_Pos) /*!< Bit mask of ENDISOOUT field. */
|
||||
#define USBD_INTENSET_ENDISOOUT_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENSET_ENDISOOUT_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENSET_ENDISOOUT_Set (1UL) /*!< Enable */
|
||||
|
||||
/* Bit 11 : Write '1' to enable interrupt for event ENDISOIN */
|
||||
#define USBD_INTENSET_ENDISOIN_Pos (11UL) /*!< Position of ENDISOIN field. */
|
||||
#define USBD_INTENSET_ENDISOIN_Msk (0x1UL << USBD_INTENSET_ENDISOIN_Pos) /*!< Bit mask of ENDISOIN field. */
|
||||
#define USBD_INTENSET_ENDISOIN_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENSET_ENDISOIN_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENSET_ENDISOIN_Set (1UL) /*!< Enable */
|
||||
|
||||
/* Register: USBD_INTENCLR */
|
||||
/* Description: Disable interrupt */
|
||||
|
||||
/* Bit 21 : Write '1' to disable interrupt for event SOF */
|
||||
#define USBD_INTENCLR_SOF_Pos (21UL) /*!< Position of SOF field. */
|
||||
#define USBD_INTENCLR_SOF_Msk (0x1UL << USBD_INTENCLR_SOF_Pos) /*!< Bit mask of SOF field. */
|
||||
#define USBD_INTENCLR_SOF_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENCLR_SOF_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENCLR_SOF_Clear (1UL) /*!< Disable */
|
||||
|
||||
/* Bit 20 : Write '1' to disable interrupt for event ENDISOOUT */
|
||||
#define USBD_INTENCLR_ENDISOOUT_Pos (20UL) /*!< Position of ENDISOOUT field. */
|
||||
#define USBD_INTENCLR_ENDISOOUT_Msk (0x1UL << USBD_INTENCLR_ENDISOOUT_Pos) /*!< Bit mask of ENDISOOUT field. */
|
||||
#define USBD_INTENCLR_ENDISOOUT_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENCLR_ENDISOOUT_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENCLR_ENDISOOUT_Clear (1UL) /*!< Disable */
|
||||
|
||||
/* Bit 11 : Write '1' to disable interrupt for event ENDISOIN */
|
||||
#define USBD_INTENCLR_ENDISOIN_Pos (11UL) /*!< Position of ENDISOIN field. */
|
||||
#define USBD_INTENCLR_ENDISOIN_Msk (0x1UL << USBD_INTENCLR_ENDISOIN_Pos) /*!< Bit mask of ENDISOIN field. */
|
||||
#define USBD_INTENCLR_ENDISOIN_Disabled (0UL) /*!< Read: Disabled */
|
||||
#define USBD_INTENCLR_ENDISOIN_Enabled (1UL) /*!< Read: Enabled */
|
||||
#define USBD_INTENCLR_ENDISOIN_Clear (1UL) /*!< Disable */
|
||||
|
||||
/* Register: USBD_ISOSPLIT */
|
||||
/* Description: Controls the split of ISO buffers */
|
||||
|
||||
/* Bits 15..0 : Controls the split of ISO buffers */
|
||||
#define USBD_ISOSPLIT_SPLIT_Pos (0UL) /*!< Position of SPLIT field. */
|
||||
#define USBD_ISOSPLIT_SPLIT_Msk (0xFFFFUL << USBD_ISOSPLIT_SPLIT_Pos) /*!< Bit mask of SPLIT field. */
|
||||
#define USBD_ISOSPLIT_SPLIT_OneDir (0x0000UL) /*!< Full buffer dedicated to either iso IN or OUT */
|
||||
#define USBD_ISOSPLIT_SPLIT_HalfIN (0x0080UL) /*!< Lower half for IN, upper half for OUT */
|
||||
|
||||
/* Register: USBD_EPSTALL */
|
||||
/* Description: STALL endpoints */
|
||||
|
||||
/* Bit 8 : Stall selected endpoint */
|
||||
#define USBD_EPSTALL_STALL_Pos (8UL) /*!< Position of STALL field. */
|
||||
#define USBD_EPSTALL_STALL_Msk (0x1UL << USBD_EPSTALL_STALL_Pos) /*!< Bit mask of STALL field. */
|
||||
#define USBD_EPSTALL_STALL_UnStall (0UL) /*!< Don't stall selected endpoint */
|
||||
#define USBD_EPSTALL_STALL_Stall (1UL) /*!< Stall selected endpoint */
|
||||
|
||||
/* Register: USBD_DPDMVALUE */
|
||||
/* Description: State D+ and D- lines will be forced into by the DPDMDRIVE task. The DPDMNODRIVE task reverts the control of the lines to MAC IP (no forcing). */
|
||||
|
||||
/* Bits 4..0 : State D+ and D- lines will be forced into by the DPDMDRIVE task */
|
||||
#define USBD_DPDMVALUE_STATE_Pos (0UL) /*!< Position of STATE field. */
|
||||
#define USBD_DPDMVALUE_STATE_Msk (0x1FUL << USBD_DPDMVALUE_STATE_Pos) /*!< Bit mask of STATE field. */
|
||||
#define USBD_DPDMVALUE_STATE_Resume (1UL) /*!< D+ forced low, D- forced high (K state) for a timing preset in hardware (50 us or 5 ms, depending on bus state) */
|
||||
#define USBD_DPDMVALUE_STATE_J (2UL) /*!< D+ forced high, D- forced low (J state) */
|
||||
#define USBD_DPDMVALUE_STATE_K (4UL) /*!< D+ forced low, D- forced high (K state) */
|
||||
|
||||
/* Register: USBD_DTOGGLE */
|
||||
/* Description: Data toggle control and status */
|
||||
|
||||
/* Bits 9..8 : Data toggle value */
|
||||
#define USBD_DTOGGLE_VALUE_Pos (8UL) /*!< Position of VALUE field. */
|
||||
#define USBD_DTOGGLE_VALUE_Msk (0x3UL << USBD_DTOGGLE_VALUE_Pos) /*!< Bit mask of VALUE field. */
|
||||
#define USBD_DTOGGLE_VALUE_Nop (0UL) /*!< No action on data toggle when writing the register with this value */
|
||||
#define USBD_DTOGGLE_VALUE_Data0 (1UL) /*!< Data toggle is DATA0 on endpoint set by EP and IO */
|
||||
#define USBD_DTOGGLE_VALUE_Data1 (2UL) /*!< Data toggle is DATA1 on endpoint set by EP and IO */
|
||||
|
||||
/* Register: USBD_EVENTCAUSE */
|
||||
/* Description: Details on what caused the USBEVENT event */
|
||||
|
||||
/* Bit 10 : USB MAC has been woken up and operational. Write '1' to clear. */
|
||||
#define USBD_EVENTCAUSE_USBWUALLOWED_Pos (10UL) /*!< Position of USBWUALLOWED field. */
|
||||
#define USBD_EVENTCAUSE_USBWUALLOWED_Msk (0x1UL << USBD_EVENTCAUSE_USBWUALLOWED_Pos) /*!< Bit mask of USBWUALLOWED field. */
|
||||
#define USBD_EVENTCAUSE_USBWUALLOWED_NotAllowed (0UL) /*!< Wake up not allowed */
|
||||
#define USBD_EVENTCAUSE_USBWUALLOWED_Allowed (1UL) /*!< Wake up allowed */
|
||||
|
||||
/* Bit 9 : Signals that a RESUME condition (K state or activity restart) has been detected on USB lines. Write '1' to clear. */
|
||||
#define USBD_EVENTCAUSE_RESUME_Pos (9UL) /*!< Position of RESUME field. */
|
||||
#define USBD_EVENTCAUSE_RESUME_Msk (0x1UL << USBD_EVENTCAUSE_RESUME_Pos) /*!< Bit mask of RESUME field. */
|
||||
#define USBD_EVENTCAUSE_RESUME_NotDetected (0UL) /*!< Resume not detected */
|
||||
#define USBD_EVENTCAUSE_RESUME_Detected (1UL) /*!< Resume detected */
|
||||
|
||||
/* Bit 8 : Signals that USB lines have been idle long enough for the device to enter suspend. Write '1' to clear. */
|
||||
#define USBD_EVENTCAUSE_SUSPEND_Pos (8UL) /*!< Position of SUSPEND field. */
|
||||
#define USBD_EVENTCAUSE_SUSPEND_Msk (0x1UL << USBD_EVENTCAUSE_SUSPEND_Pos) /*!< Bit mask of SUSPEND field. */
|
||||
#define USBD_EVENTCAUSE_SUSPEND_NotDetected (0UL) /*!< Suspend not detected */
|
||||
#define USBD_EVENTCAUSE_SUSPEND_Detected (1UL) /*!< Suspend detected */
|
||||
|
||||
/* Register: USBD_SIZE_ISOOUT */
|
||||
/* Description: Number of bytes received last on this ISO OUT data endpoint */
|
||||
|
||||
/* Bit 16 : Zero-length data packet received */
|
||||
#define USBD_SIZE_ISOOUT_ZERO_Pos (16UL) /*!< Position of ZERO field. */
|
||||
#define USBD_SIZE_ISOOUT_ZERO_Msk (0x1UL << USBD_SIZE_ISOOUT_ZERO_Pos) /*!< Bit mask of ZERO field. */
|
||||
#define USBD_SIZE_ISOOUT_ZERO_Normal (0UL) /*!< No zero-length data received, use value in SIZE */
|
||||
#define USBD_SIZE_ISOOUT_ZERO_ZeroData (1UL) /*!< Zero-length data received, ignore value in SIZE */
|
||||
|
||||
/* Register: USBD_EVENTCAUSE */
|
||||
/* Description: Details on what caused the USBEVENT event */
|
||||
|
||||
/* Bit 11 : USB device is ready for normal operation. Write '1' to clear. */
|
||||
#define USBD_EVENTCAUSE_READY_Pos (11UL) /*!< Position of READY field. */
|
||||
#define USBD_EVENTCAUSE_READY_Msk (0x1UL << USBD_EVENTCAUSE_READY_Pos) /*!< Bit mask of READY field. */
|
||||
#define USBD_EVENTCAUSE_READY_NotDetected (0UL) /*!< USBEVENT was not issued due to USBD peripheral ready */
|
||||
#define USBD_EVENTCAUSE_READY_Ready (1UL) /*!< USBD peripheral is ready */
|
||||
|
||||
/* Register: USBD_ISOINCONFIG */
|
||||
/* Description: Controls the response of the ISO IN endpoint to an IN token when no data is ready to be sent */
|
||||
|
||||
/* Bit 0 : Controls the response of the ISO IN endpoint to an IN token when no data is ready to be sent */
|
||||
#define USBD_ISOINCONFIG_RESPONSE_Pos (0UL) /*!< Position of RESPONSE field. */
|
||||
#define USBD_ISOINCONFIG_RESPONSE_Msk (0x1UL << USBD_ISOINCONFIG_RESPONSE_Pos) /*!< Bit mask of RESPONSE field. */
|
||||
#define USBD_ISOINCONFIG_RESPONSE_NoResp (0UL) /*!< Endpoint does not respond in that case */
|
||||
#define USBD_ISOINCONFIG_RESPONSE_ZeroData (1UL) /*!< Endpoint responds with a zero-length data packet in that case */
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clock control (CLOCK)
|
||||
*/
|
||||
|
||||
typedef struct { /*!< (@ 0x40000000) CLOCK Structure */
|
||||
__OM uint32_t TASKS_HFCLKSTART; /*!< (@ 0x00000000) Start HFXO crystal oscillator */
|
||||
__OM uint32_t TASKS_HFCLKSTOP; /*!< (@ 0x00000004) Stop HFXO crystal oscillator */
|
||||
__OM uint32_t TASKS_LFCLKSTART; /*!< (@ 0x00000008) Start LFCLK */
|
||||
__OM uint32_t TASKS_LFCLKSTOP; /*!< (@ 0x0000000C) Stop LFCLK */
|
||||
__OM uint32_t TASKS_CAL; /*!< (@ 0x00000010) Start calibration of LFRC */
|
||||
__OM uint32_t TASKS_CTSTART; /*!< (@ 0x00000014) Start calibration timer */
|
||||
__OM uint32_t TASKS_CTSTOP; /*!< (@ 0x00000018) Stop calibration timer */
|
||||
__IM uint32_t RESERVED[57];
|
||||
__IOM uint32_t EVENTS_HFCLKSTARTED; /*!< (@ 0x00000100) HFXO crystal oscillator started */
|
||||
__IOM uint32_t EVENTS_LFCLKSTARTED; /*!< (@ 0x00000104) LFCLK started */
|
||||
__IM uint32_t RESERVED1;
|
||||
__IOM uint32_t EVENTS_DONE; /*!< (@ 0x0000010C) Calibration of LFRC completed */
|
||||
__IOM uint32_t EVENTS_CTTO; /*!< (@ 0x00000110) Calibration timer timeout */
|
||||
__IM uint32_t RESERVED2[5];
|
||||
__IOM uint32_t EVENTS_CTSTARTED; /*!< (@ 0x00000128) Calibration timer has been started and is ready
|
||||
to process new tasks */
|
||||
__IOM uint32_t EVENTS_CTSTOPPED; /*!< (@ 0x0000012C) Calibration timer has been stopped and is ready
|
||||
to process new tasks */
|
||||
__IM uint32_t RESERVED3[117];
|
||||
__IOM uint32_t INTENSET; /*!< (@ 0x00000304) Enable interrupt */
|
||||
__IOM uint32_t INTENCLR; /*!< (@ 0x00000308) Disable interrupt */
|
||||
__IM uint32_t RESERVED4[63];
|
||||
__IM uint32_t HFCLKRUN; /*!< (@ 0x00000408) Status indicating that HFCLKSTART task has been
|
||||
triggered */
|
||||
__IM uint32_t HFCLKSTAT; /*!< (@ 0x0000040C) HFCLK status */
|
||||
__IM uint32_t RESERVED5;
|
||||
__IM uint32_t LFCLKRUN; /*!< (@ 0x00000414) Status indicating that LFCLKSTART task has been
|
||||
triggered */
|
||||
__IM uint32_t LFCLKSTAT; /*!< (@ 0x00000418) LFCLK status */
|
||||
__IM uint32_t LFCLKSRCCOPY; /*!< (@ 0x0000041C) Copy of LFCLKSRC register, set when LFCLKSTART
|
||||
task was triggered */
|
||||
__IM uint32_t RESERVED6[62];
|
||||
__IOM uint32_t LFCLKSRC; /*!< (@ 0x00000518) Clock source for the LFCLK */
|
||||
__IM uint32_t RESERVED7[3];
|
||||
__IOM uint32_t HFXODEBOUNCE; /*!< (@ 0x00000528) HFXO debounce time. The HFXO is started by triggering
|
||||
the TASKS_HFCLKSTART task. */
|
||||
__IM uint32_t RESERVED8[3];
|
||||
__IOM uint32_t CTIV; /*!< (@ 0x00000538) Calibration timer interval */
|
||||
__IM uint32_t RESERVED9[8];
|
||||
__IOM uint32_t TRACECONFIG; /*!< (@ 0x0000055C) Clocking options for the trace port debug interface */
|
||||
__IM uint32_t RESERVED10[21];
|
||||
__IOM uint32_t LFRCMODE; /*!< (@ 0x000005B4) LFRC mode configuration */
|
||||
} NRF_CLOCK_Type; /*!< Size = 1464 (0x5b8) */
|
||||
|
||||
|
||||
#define CLOCK_HFCLKSTAT_STATE_Pos (16UL) /*!< Position of STATE field. */
|
||||
#define CLOCK_HFCLKSTAT_STATE_Msk (0x1UL << CLOCK_HFCLKSTAT_STATE_Pos) /*!< Bit mask of STATE field. */
|
||||
#define CLOCK_HFCLKSTAT_STATE_NotRunning (0UL) /*!< HFCLK not running */
|
||||
#define CLOCK_HFCLKSTAT_STATE_Running (1UL) /*!< HFCLK running */
|
||||
|
||||
|
||||
/* Bit 0 : Source of HFCLK */
|
||||
#define CLOCK_HFCLKSTAT_SRC_Pos (0UL) /*!< Position of SRC field. */
|
||||
#define CLOCK_HFCLKSTAT_SRC_Msk (0x1UL << CLOCK_HFCLKSTAT_SRC_Pos) /*!< Bit mask of SRC field. */
|
||||
#define CLOCK_HFCLKSTAT_SRC_RC (0UL) /*!< 64 MHz internal oscillator (HFINT) */
|
||||
#define CLOCK_HFCLKSTAT_SRC_Xtal (1UL) /*!< 64 MHz crystal oscillator (HFXO) */
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[24U];
|
||||
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RESERVED1[24U];
|
||||
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[24U];
|
||||
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[24U];
|
||||
__IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
|
||||
uint32_t RESERVED4[56U];
|
||||
__IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
|
||||
uint32_t RESERVED5[644U];
|
||||
__OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
|
||||
} NVIC_Type;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -174,15 +174,15 @@ uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_IN(ep_cfg->ep_addr)) {
|
||||
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
|
||||
uint8_t epnum = USBD_EPNUM_FROM_IN_EPIDX(ep_idx);
|
||||
|
||||
g_nuvoton_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_nuvoton_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_nuvoton_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_nuvoton_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_nuvoton_udc.in_ep[ep_idx].ep_enable = true;
|
||||
if (ep_idx == 0) {
|
||||
/* EP0 ==> control IN endpoint, address 0 */
|
||||
@@ -194,8 +194,8 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
} else {
|
||||
uint8_t epnum = USBD_EPNUM_FROM_OUT_EPIDX(ep_idx);
|
||||
|
||||
g_nuvoton_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_nuvoton_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_nuvoton_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_nuvoton_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_nuvoton_udc.out_ep[ep_idx].ep_enable = true;
|
||||
if (ep_idx == 0) {
|
||||
/* EP1 ==> control OUT endpoint, address 0 */
|
||||
|
||||
@@ -236,45 +236,45 @@ int usbd_set_address(const uint8_t addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_endpoint_descriptor *usbd_get_ep0_desc(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
static struct usb_endpoint_descriptor *usbd_get_ep0_desc(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
static struct usb_endpoint_descriptor ep0_desc;
|
||||
|
||||
/* Config EP0 mps from speed */
|
||||
ep0_desc.bEndpointAddress = ep_cfg->ep_addr;
|
||||
ep0_desc.bEndpointAddress = ep->bEndpointAddress;
|
||||
ep0_desc.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
|
||||
ep0_desc.bmAttributes = ep_cfg->ep_type;
|
||||
ep0_desc.wMaxPacketSize = ep_cfg->ep_mps;
|
||||
ep0_desc.bmAttributes = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
ep0_desc.wMaxPacketSize = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
ep0_desc.bInterval = 0;
|
||||
ep0_desc.bLength = 7;
|
||||
|
||||
return &ep0_desc;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
int usbd_ep_open(const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
struct pusb2_dc_ep_state *ep_state;
|
||||
uint32_t error;
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
ep_state = &g_pusb2_udc.out_ep[ep_idx];
|
||||
} else {
|
||||
ep_state = &g_pusb2_udc.in_ep[ep_idx];
|
||||
}
|
||||
|
||||
ep_state->ep_mps = ep_cfg->ep_mps;
|
||||
ep_state->ep_type = ep_cfg->ep_type;
|
||||
ep_state->desc = usbd_get_ep0_desc(ep_cfg);
|
||||
ep_state->ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
ep_state->ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
ep_state->desc = usbd_get_ep0_desc(ep);
|
||||
|
||||
USB_ASSERT(ep_state->priv_ep != NULL);
|
||||
USB_LOG_DBG("try to enable ep@0x%x 0x%x:0x%x\n", ep_cfg->ep_addr,
|
||||
USB_LOG_DBG("try to enable ep@0x%x 0x%x:0x%x\n", ep->bEndpointAddress,
|
||||
ep_state->priv_ep, ep_state->desc );
|
||||
error = FPUsb2DcEpEnable(&g_pusb2_udc.pusb2.device_ctrl,
|
||||
ep_state->priv_ep,
|
||||
(const FUsbEndpointDescriptor *)ep_state->desc);
|
||||
if (FPUSB2_SUCCESS != error){
|
||||
USB_LOG_ERR("enable ep-%d failed, error = 0x%x\n", ep_cfg->ep_addr, error);
|
||||
USB_LOG_ERR("enable ep-%d failed, error = 0x%x\n", ep->bEndpointAddress, error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,605 +0,0 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usb_rp2040_reg.h"
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler isr_irq5
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 16
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_VBUS_DETECT
|
||||
#define FORCE_VBUS_DETECT 1
|
||||
#endif
|
||||
|
||||
/* Endpoint state */
|
||||
struct usb_dc_ep_state {
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint8_t ep_stalled; /* Endpoint stall flag */
|
||||
uint8_t ep_enable; /* Endpoint enable */
|
||||
uint8_t ep_addr; /* Endpoint address */
|
||||
uint8_t *xfer_buf;
|
||||
uint32_t xfer_len;
|
||||
uint32_t actual_xfer_len;
|
||||
/**
|
||||
* For rp2040
|
||||
*/
|
||||
volatile uint32_t *endpoint_control; /*!< Endpoint control register */
|
||||
volatile uint32_t *buffer_control; /*!< Buffer control register */
|
||||
uint8_t *dpram_data_buf; /*!< Buffer pointer in usb dpram */
|
||||
uint8_t next_pid; /*!< Toggle after each packet (unless replying to a SETUP) */
|
||||
};
|
||||
|
||||
/* Driver state */
|
||||
struct rp2040_udc {
|
||||
volatile uint8_t dev_addr;
|
||||
struct usb_dc_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct usb_dc_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
struct usb_setup_packet setup; /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
|
||||
} g_rp2040_udc;
|
||||
|
||||
static uint8_t *next_buffer_ptr;
|
||||
|
||||
/**
|
||||
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
|
||||
*
|
||||
* @param buf
|
||||
* @return uint32_t
|
||||
*/
|
||||
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
|
||||
{
|
||||
return (uint32_t)buf ^ (uint32_t)usb_dpram;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Alloc the endpoint dpram and set up ep (if applicable. Not valid for EP0).
|
||||
*
|
||||
* @param ep
|
||||
*/
|
||||
static int8_t rp2040_usb_config_ep(struct usb_dc_ep_state *ep)
|
||||
{
|
||||
if (!ep->endpoint_control) {
|
||||
USB_LOG_WRN("Not valid for EP0 \r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!< size must be multiple of 64 */
|
||||
uint16_t size = ((ep->ep_mps + 64 - 1) / 64) * 64;
|
||||
/*!< Get current buffer ptr */
|
||||
ep->dpram_data_buf = next_buffer_ptr;
|
||||
/*!< Update the next buffer ptr */
|
||||
next_buffer_ptr += size;
|
||||
if (((uint32_t)next_buffer_ptr & 0b111111u) != 0) {
|
||||
USB_LOG_ERR("DPRAM Not 64 byte aligned \r\n");
|
||||
return -1;
|
||||
}
|
||||
uint32_t dpram_offset = usb_buffer_offset(ep->dpram_data_buf);
|
||||
if (dpram_offset > USB_DPRAM_MAX) {
|
||||
USB_LOG_ERR("DPRAM overflow \r\n");
|
||||
return -2;
|
||||
}
|
||||
USB_LOG_INFO("Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->dpram_data_buf);
|
||||
/*!< Enable ep and perbuffer trigger interrupt */
|
||||
volatile uint32_t reg = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER | ((ep->ep_type) << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
|
||||
*ep->endpoint_control = reg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rp2040_usb_init(void)
|
||||
{
|
||||
/*!< Reset usb controller */
|
||||
reset_block(RESETS_RESET_USBCTRL_BITS);
|
||||
unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
|
||||
|
||||
/*!< Clear any previous state just in case */
|
||||
memset(usb_hw, 0, sizeof(*usb_hw));
|
||||
memset(usb_dpram, 0, sizeof(*usb_dpram));
|
||||
|
||||
/*!< Mux the controller to the onboard usb phy */
|
||||
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
|
||||
}
|
||||
|
||||
int usb_dc_init(void)
|
||||
{
|
||||
memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
|
||||
rp2040_usb_init();
|
||||
#if FORCE_VBUS_DETECT
|
||||
/*!< Force VBUS detect so the device thinks it is plugged into a host */
|
||||
usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initializes the USB peripheral for device mode and enables it.
|
||||
* Don't need to enable the pull up here. Force VBUS
|
||||
*/
|
||||
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
|
||||
|
||||
/**
|
||||
* Enable individual controller IRQS here. Processor interrupt enable will be used
|
||||
* for the global interrupt enable...
|
||||
* Note: Force VBUS detect cause disconnection not detectable
|
||||
*/
|
||||
usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
|
||||
usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
|
||||
USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
|
||||
(FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
|
||||
|
||||
/**
|
||||
* Enable interrupt
|
||||
* Clear pending before enable
|
||||
* (if IRQ is actually asserted, it will immediately re-pend)
|
||||
*/
|
||||
*((io_rw_32 *)(PPB_BASE + M0PLUS_NVIC_ICPR_OFFSET)) = 1 << 5;
|
||||
*((io_rw_32 *)(PPB_BASE + M0PLUS_NVIC_ISER_OFFSET)) = 1 << 5;
|
||||
|
||||
usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a transfer on a given endpoint.
|
||||
*
|
||||
* @param ep, the endpoint configuration.
|
||||
* @param buf, the data buffer to send. Only applicable if the endpoint is TX
|
||||
* @param len, the length of the data in buf (this example limits max len to one packet - 64 bytes)
|
||||
*/
|
||||
static void usb_start_transfer(struct usb_dc_ep_state *ep, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
/*!< Prepare buffer control register value */
|
||||
uint32_t val = len | USB_BUF_CTRL_AVAIL;
|
||||
if (len < ep->ep_mps) {
|
||||
val |= USB_BUF_CTRL_LAST;
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_IN(ep->ep_addr)) {
|
||||
/*!< Need to copy the data from the user buffer to the usb memory */
|
||||
if (buf != NULL) {
|
||||
memcpy((void *)ep->dpram_data_buf, (void *)buf, len);
|
||||
}
|
||||
/*!< Mark as full */
|
||||
val |= USB_BUF_CTRL_FULL;
|
||||
} else {
|
||||
}
|
||||
|
||||
/*!< Set pid and flip for next transfer */
|
||||
val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
|
||||
ep->next_pid ^= 1u;
|
||||
/**
|
||||
* !Need delay some cycles
|
||||
* nop for some clk_sys cycles to ensure that at least one clk_usb cycle has passed. For example if clk_sys was running
|
||||
* at 125MHz and clk_usb was running at 48MHz then 125/48 rounded up would be 3 nop instructions
|
||||
*/
|
||||
*ep->buffer_control = val & ~USB_BUF_CTRL_AVAIL;
|
||||
__asm volatile(
|
||||
"b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1: b 1f\n"
|
||||
"1:\n"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
*ep->buffer_control = val;
|
||||
}
|
||||
|
||||
int usb_dc_deinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_address(const uint8_t addr)
|
||||
{
|
||||
if (addr != 0) {
|
||||
g_rp2040_udc.dev_addr = addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(const uint8_t port)
|
||||
{
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
|
||||
|
||||
if (ep_idx == 0) {
|
||||
/**
|
||||
* A device must support Endpoint 0 so that it can reply to SETUP packets and be enumerated. As a result, there is no
|
||||
* endpoint control register for EP0. Its buffers begin at 0x100. All other endpoints can have either single or dual buffers
|
||||
* and are mapped at the base address programmed. As EP0 has no endpoint control register, the interrupt enable
|
||||
* controls for EP0 come from SIE_CTRL.
|
||||
*/
|
||||
g_rp2040_udc.out_ep[ep_idx].endpoint_control = NULL;
|
||||
g_rp2040_udc.out_ep[ep_idx].dpram_data_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0];
|
||||
g_rp2040_udc.in_ep[ep_idx].endpoint_control = NULL;
|
||||
g_rp2040_udc.in_ep[ep_idx].dpram_data_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0];
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
|
||||
g_rp2040_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_rp2040_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_rp2040_udc.out_ep[ep_idx].ep_addr = ep_cfg->ep_addr;
|
||||
g_rp2040_udc.out_ep[ep_idx].ep_enable = true;
|
||||
/*!< Get control reg */
|
||||
g_rp2040_udc.out_ep[ep_idx].buffer_control = &usb_dpram->ep_buf_ctrl[ep_idx].out;
|
||||
/*!< Clear control reg */
|
||||
*(g_rp2040_udc.out_ep[ep_idx].buffer_control) = 0;
|
||||
|
||||
if (ep_idx != 0) {
|
||||
g_rp2040_udc.out_ep[ep_idx].endpoint_control = &usb_dpram->ep_ctrl[ep_idx - 1].out;
|
||||
/**
|
||||
* Allocate a buffer on DPRAM for the endpoint
|
||||
*/
|
||||
return rp2040_usb_config_ep(&g_rp2040_udc.out_ep[ep_idx]);
|
||||
}
|
||||
|
||||
} else {
|
||||
g_rp2040_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
|
||||
g_rp2040_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
|
||||
g_rp2040_udc.in_ep[ep_idx].ep_addr = ep_cfg->ep_addr;
|
||||
g_rp2040_udc.in_ep[ep_idx].ep_enable = true;
|
||||
/*!< Get control reg */
|
||||
g_rp2040_udc.in_ep[ep_idx].buffer_control = &usb_dpram->ep_buf_ctrl[ep_idx].in;
|
||||
/*!< Clear control reg */
|
||||
*(g_rp2040_udc.in_ep[ep_idx].buffer_control) = 0;
|
||||
|
||||
if (ep_idx != 0) {
|
||||
g_rp2040_udc.in_ep[ep_idx].endpoint_control = &usb_dpram->ep_ctrl[ep_idx - 1].in;
|
||||
/**
|
||||
* Allocate a buffer on DPRAM for the endpoint
|
||||
*/
|
||||
return rp2040_usb_config_ep(&g_rp2040_udc.in_ep[ep_idx]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_close(const uint8_t ep)
|
||||
{
|
||||
/*!< Ep id */
|
||||
uint16_t size = 0;
|
||||
|
||||
uint8_t epid = USB_EP_GET_IDX(ep);
|
||||
if (USB_EP_DIR_IS_IN(ep)) {
|
||||
/*!< In */
|
||||
size = ((g_rp2040_udc.in_ep[epid].ep_mps + 64 - 1) / 64) * 64;
|
||||
memset(g_rp2040_udc.in_ep[epid].dpram_data_buf, 0, size);
|
||||
next_buffer_ptr -= size;
|
||||
g_rp2040_udc.in_ep[epid].ep_enable = false;
|
||||
} else if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
/*!< Out */
|
||||
size = ((g_rp2040_udc.out_ep[epid].ep_mps + 64 - 1) / 64) * 64;
|
||||
memset(g_rp2040_udc.out_ep[epid].dpram_data_buf, 0, size);
|
||||
next_buffer_ptr -= size;
|
||||
g_rp2040_udc.out_ep[epid].ep_enable = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_set_stall(const uint8_t ep)
|
||||
{
|
||||
if (USB_EP_GET_IDX(ep) == 0) {
|
||||
/**
|
||||
* A stall on EP0 has to be armed so it can be cleared on the next setup packet
|
||||
*/
|
||||
usb_hw_set->ep_stall_arm = (USB_EP_DIR_IS_IN(ep)) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
|
||||
} else {
|
||||
*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_clear_stall(const uint8_t ep)
|
||||
{
|
||||
volatile uint32_t value = 0;
|
||||
if (USB_EP_GET_IDX(ep)) {
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
|
||||
value = *(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) & (~USB_BUF_CTRL_STALL);
|
||||
*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = value;
|
||||
} else {
|
||||
g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
|
||||
value = *(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) & (~USB_BUF_CTRL_STALL);
|
||||
*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_rp2040_udc.in_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
g_rp2040_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_rp2040_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_rp2040_udc.in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (data_len == 0) {
|
||||
usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], NULL, 0);
|
||||
return 0;
|
||||
} else {
|
||||
/*!< Not zlp */
|
||||
data_len = MIN(data_len, g_rp2040_udc.in_ep[ep_idx].ep_mps);
|
||||
usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], g_rp2040_udc.in_ep[ep_idx].xfer_buf, data_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_rp2040_udc.out_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
g_rp2040_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_rp2040_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_rp2040_udc.out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (data_len == 0) {
|
||||
usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], NULL, 0);
|
||||
return 0;
|
||||
} else {
|
||||
/*!< Not zlp */
|
||||
data_len = MIN(data_len, g_rp2040_udc.out_ep[ep_idx].ep_mps);
|
||||
usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], g_rp2040_udc.out_ep[ep_idx].xfer_buf, data_len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify an endpoint that a transfer has completed.
|
||||
*
|
||||
* @param ep, the endpoint to notify.
|
||||
*/
|
||||
static void usb_handle_ep_buff_done(struct usb_dc_ep_state *ep)
|
||||
{
|
||||
uint32_t buffer_control = *ep->buffer_control;
|
||||
/*!< Get the transfer length for this endpoint */
|
||||
uint16_t read_count = buffer_control & USB_BUF_CTRL_LEN_MASK;
|
||||
/*!< Call that endpoints buffer done handler */
|
||||
if (ep->ep_addr == 0x80) {
|
||||
/*!< EP0 In */
|
||||
/**
|
||||
* Determine the current setup direction
|
||||
*/
|
||||
switch (g_rp2040_udc.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
|
||||
case 1:
|
||||
/*!< Get */
|
||||
if (g_rp2040_udc.in_ep[0].xfer_len > g_rp2040_udc.in_ep[0].ep_mps) {
|
||||
g_rp2040_udc.in_ep[0].xfer_len -= g_rp2040_udc.in_ep[0].ep_mps;
|
||||
g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].ep_mps;
|
||||
usbd_event_ep_in_complete_handler(0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
|
||||
} else {
|
||||
g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].xfer_len;
|
||||
g_rp2040_udc.in_ep[0].xfer_len = 0;
|
||||
/**
|
||||
* EP0 In complete and host will send a out token to get 0 length packet
|
||||
* In the next usbd_event_ep_in_complete_handler, stack will start read 0 length packet
|
||||
* and host must send data1 packet.We resest the ep0 next_pid = 1 in setup interrupt head.
|
||||
*/
|
||||
usbd_event_ep_in_complete_handler(0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
/*!< Set */
|
||||
if (g_rp2040_udc.dev_addr > 0) {
|
||||
usb_hw->dev_addr_ctrl = g_rp2040_udc.dev_addr;
|
||||
g_rp2040_udc.dev_addr = 0;
|
||||
} else {
|
||||
/*!< Normal status stage // Setup out...out in */
|
||||
/**
|
||||
* Perpar for next setup
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (ep->ep_addr == 0x00) {
|
||||
/*!< EP0 Out */
|
||||
memcpy(g_rp2040_udc.out_ep[0].xfer_buf, g_rp2040_udc.out_ep[0].dpram_data_buf, read_count);
|
||||
if (read_count == 0) {
|
||||
/*!< Normal status stage // Setup in...in out */
|
||||
/**
|
||||
* Perpar for next setup
|
||||
*/
|
||||
}
|
||||
|
||||
g_rp2040_udc.out_ep[0].actual_xfer_len += read_count;
|
||||
g_rp2040_udc.out_ep[0].xfer_len -= read_count;
|
||||
|
||||
usbd_event_ep_out_complete_handler(0x00, g_rp2040_udc.out_ep[0].actual_xfer_len);
|
||||
} else {
|
||||
/*!< Others ep */
|
||||
uint16_t data_len = 0;
|
||||
if (USB_EP_DIR_IS_OUT(ep->ep_addr)) {
|
||||
/*!< flip the pid */
|
||||
memcpy(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].dpram_data_buf, read_count);
|
||||
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf += read_count;
|
||||
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += read_count;
|
||||
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len -= read_count;
|
||||
|
||||
if (read_count < g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps || g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len == 0) {
|
||||
/*!< Out complete */
|
||||
usbd_event_ep_out_complete_handler(ep->ep_addr, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
|
||||
} else {
|
||||
/*!< Need read again */
|
||||
data_len = MIN(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps);
|
||||
usb_start_transfer(&g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f], NULL, data_len);
|
||||
}
|
||||
} else {
|
||||
if (g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len > g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps) {
|
||||
/*!< Need tx again */
|
||||
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len -= g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
|
||||
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
|
||||
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
|
||||
data_len = MIN(g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps);
|
||||
usb_start_transfer(&g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f], g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf, data_len);
|
||||
} else {
|
||||
/*!< In complete */
|
||||
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len;
|
||||
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(ep->ep_addr, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the endpoint configuration for a specified endpoint number and
|
||||
* direction and notify it that a transfer has completed.
|
||||
*
|
||||
* @param ep_num
|
||||
* @param in
|
||||
*/
|
||||
static void usb_handle_buff_done(uint8_t ep_num, bool in)
|
||||
{
|
||||
uint8_t ep_addr = ep_num | (in ? USB_EP_DIR_IN : 0);
|
||||
if (USB_EP_DIR_IS_OUT(ep_addr)) {
|
||||
usb_handle_ep_buff_done(&g_rp2040_udc.out_ep[ep_num]);
|
||||
} else {
|
||||
usb_handle_ep_buff_done(&g_rp2040_udc.in_ep[ep_num]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle a "buffer status" irq. This means that one or more
|
||||
* buffers have been sent / received. Notify each endpoint where this
|
||||
* is the case.
|
||||
*/
|
||||
static void usb_handle_buff_status()
|
||||
{
|
||||
uint32_t buffers = usb_hw->buf_status;
|
||||
uint32_t remaining_buffers = buffers;
|
||||
|
||||
uint32_t bit = 1u;
|
||||
for (uint8_t i = 0; remaining_buffers && i < USB_NUM_ENDPOINTS * 2; i++) {
|
||||
if (remaining_buffers & bit) {
|
||||
/*!< clear this in advance */
|
||||
usb_hw_clear->buf_status = bit;
|
||||
/*!< IN transfer for even i, OUT transfer for odd i */
|
||||
usb_handle_buff_done(i >> 1u, !(i & 1u));
|
||||
remaining_buffers &= ~bit;
|
||||
}
|
||||
bit <<= 1u;
|
||||
}
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(void)
|
||||
{
|
||||
uint32_t const status = usb_hw->ints;
|
||||
uint32_t handled = 0;
|
||||
|
||||
if (status & USB_INTS_BUFF_STATUS_BITS) {
|
||||
handled |= USB_INTS_BUFF_STATUS_BITS;
|
||||
usb_handle_buff_status();
|
||||
}
|
||||
|
||||
if (status & USB_INTS_SETUP_REQ_BITS) {
|
||||
handled |= USB_INTS_SETUP_REQ_BITS;
|
||||
memcpy((uint8_t *)&g_rp2040_udc.setup, (uint8_t const *)&usb_dpram->setup_packet, 8);
|
||||
/**
|
||||
* reset pid to both 1 (data and ack)
|
||||
*/
|
||||
g_rp2040_udc.in_ep[0].next_pid = 1;
|
||||
g_rp2040_udc.out_ep[0].next_pid = 1;
|
||||
usbd_event_ep0_setup_complete_handler((uint8_t *)&g_rp2040_udc.setup);
|
||||
usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
|
||||
}
|
||||
|
||||
#if FORCE_VBUS_DETECT == 0
|
||||
/**
|
||||
* Since we force VBUS detect On, device will always think it is connected and
|
||||
* couldn't distinguish between disconnect and suspend
|
||||
*/
|
||||
if (status & USB_INTS_DEV_CONN_DIS_BITS) {
|
||||
handled |= USB_INTS_DEV_CONN_DIS_BITS;
|
||||
if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) {
|
||||
/*!< Connected: nothing to do */
|
||||
} else {
|
||||
/*!< Disconnected */
|
||||
}
|
||||
usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SE0 for 2.5 us or more (will last at least 10ms)
|
||||
*/
|
||||
if (status & USB_INTS_BUS_RESET_BITS) {
|
||||
handled |= USB_INTS_BUS_RESET_BITS;
|
||||
usb_hw->dev_addr_ctrl = 0;
|
||||
|
||||
for (uint8_t i = 0; i < USB_NUM_BIDIR_ENDPOINTS - 1; i++) {
|
||||
/*!< Start at ep1 */
|
||||
usb_dpram->ep_ctrl[i].in = 0;
|
||||
usb_dpram->ep_ctrl[i].out = 0;
|
||||
}
|
||||
/*!< reclaim buffer space */
|
||||
next_buffer_ptr = &usb_dpram->epx_data[0];
|
||||
|
||||
usbd_event_reset_handler();
|
||||
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
|
||||
|
||||
#if CHERRYUSB_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
|
||||
/**
|
||||
* Only run enumeration walk-around if pull up is enabled
|
||||
*/
|
||||
if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS)
|
||||
rp2040_usb_device_enumeration_fix();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Note from pico datasheet 4.1.2.6.4 (v1.2)
|
||||
* If you enable the suspend interrupt, it is likely you will see a suspend interrupt when
|
||||
* the device is first connected but the bus is idle. The bus can be idle for a few ms before
|
||||
* the host begins sending start of frame packets. You will also see a suspend interrupt
|
||||
* when the device is disconnected if you do not have a VBUS detect circuit connected. This is
|
||||
* because without VBUS detection, it is impossible to tell the difference between
|
||||
* being disconnected and suspended.
|
||||
*/
|
||||
if (status & USB_INTS_DEV_SUSPEND_BITS) {
|
||||
handled |= USB_INTS_DEV_SUSPEND_BITS;
|
||||
/*!< Suspend */
|
||||
usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
|
||||
}
|
||||
|
||||
if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) {
|
||||
handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
|
||||
/*!< Resume */
|
||||
usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
|
||||
}
|
||||
|
||||
if (status ^ handled) {
|
||||
USB_LOG_INFO("Unhandled IRQ 0x%x\n", (uint32_t)(status ^ handled));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user