65 Commits

Author SHA1 Message Date
sakumisu
7df43ba6a2 release v1.0.0 2023-12-30 15:42:23 +08:00
sakumisu
e58a78c070 add aic & intel ehci glue, add rtems osal 2023-12-30 15:01:20 +08:00
sakumisu
1492b8cca9 remove ch32 host, nrf5x, rp2040 port 2023-12-30 14:44:52 +08:00
sakumisu
67a3bbe02e fix hctsiz macro name 2023-12-30 14:39:34 +08:00
sakumisu
65b2de960b update gccfg for stm32h7/f7 2023-12-30 14:39:26 +08:00
sakumisu
019c9cff6e fix dwc2 out chan actual len 2023-12-28 20:57:50 +08:00
sakumisu
2662a3497d add \t for hub info log 2023-12-27 20:21:10 +08:00
sakumisu
7f7add7cec update memory usage 2023-12-27 20:20:25 +08:00
sakumisu
fa2900d4cd fix rst grammar 2023-12-26 23:04:54 +08:00
sakumisu
d30d08ca3a musb do not use alloc pipe 2023-12-26 22:52:32 +08:00
sakumisu
02685793aa update demo version 2023-12-26 20:37:23 +08:00
sakumisu
8cd31e6be0 add check for dwc2 ramsize and ep num 2023-12-26 20:11:23 +08:00
sakumisu
56c2b34131 update stm32 demo rst 2023-12-25 22:06:35 +08:00
sakumisu
f68a86ea89 add usbh_deinitialize api 2023-12-24 23:37:47 +08:00
sakumisu
8a831cdaa5 user must define some configs in usb_config.h when use fsdev/musb/dwc2 2023-12-21 21:58:08 +08:00
sakumisu
44e9c1cf4f register desc with callback when enable CONFIG_USBDEV_ADVANCE_DESC 2023-12-20 20:24:47 +08:00
sakumisu
e201439722 create lwip rx thread by user 2023-12-19 21:38:55 +08:00
sakumisu
01f9025b6b init demo thread in xxx_run api, and delete by itself 2023-12-18 20:52:26 +08:00
sakumisu
bb709437aa fix musb submit_urb by 5bbe2a97 2023-12-18 20:52:07 +08:00
sakumisu
7b936db889 remove vendor host class because its version is too old 2023-12-16 23:22:41 +08:00
sakumisu
6db1ef3a40 update demo version 2023-12-16 23:19:57 +08:00
sakumisu
8f991699cb remove mtp & printer class 2023-12-16 17:20:52 +08:00
sakumisu
29d45ef5c7 replace struct usbd_endpoint_cfg with struct usb_endpoint_descriptor in usbh_ep_open api 2023-12-10 22:34:01 +08:00
FanHuaCloud
a1ed27523c AT32 gccfg adds the vbusig flag by default 2023-12-09 14:45:14 +08:00
sakumisu
ce2a438c99 fix uninitialized warning 2023-12-05 21:39:36 +08:00
sakumisu
297852ce16 update host api rst 2023-12-05 21:35:00 +08:00
sakumisu
b1e95f0ca3 update hc template 2023-12-05 21:34:51 +08:00
sakumisu
14f1f597f1 add usb errno, do not use system errno 2023-12-05 21:34:32 +08:00
sakumisu
48730e20be add usb_osal_sem_reset api 2023-12-05 20:49:26 +08:00
sakumisu
11e389f922 Revert "reset sem before taking"
This reverts commit b5f0c043e7.
2023-12-05 20:45:21 +08:00
sakumisu
82cd79989c check token only with qtd, not use token in qh 2023-12-05 20:44:30 +08:00
sakumisu
fe18d36fe0 implement rtt eth_device control and eth_tx api 2023-12-01 20:44:24 +08:00
sakumisu
d414fd21d8 add config for rndis & ecm thread 2023-12-01 20:43:13 +08:00
sakumisu
c8a11be013 add two dhcp timer 2023-11-30 21:34:18 +08:00
sakumisu
fb6a463cc1 implement rt_hw_cpu_dcache_ops api 2023-11-30 21:33:22 +08:00
sakumisu
7e3795c191 auto enable lwip demo with __has_include 2023-11-29 21:04:50 +08:00
sakumisu
22d60b4300 add align check for rtt disk port 2023-11-29 21:03:19 +08:00
sakumisu
85e73197f9 update rtt dfs port 2023-11-28 20:41:58 +08:00
sakumisu
c90f273e24 port and add comment for gccfg with gd/at/st 2023-11-27 20:30:15 +08:00
sakumisu
b14976dd56 fix usbh_set_interface api, correct wValue for altsetting 2023-11-27 20:29:24 +08:00
sakumisu
9cd88c0ca3 update dwc2 rst 2023-11-26 23:06:09 +08:00
sakumisu
3440e0cc1d move out dwc2 ggcfg register and config by user 2023-11-26 22:59:41 +08:00
ovo
849ea98853 bugfix: send zlp won't trigger ep tx interrupt 2023-11-26 18:48:11 +08:00
sakumisu
b5f0c043e7 reset sem before taking 2023-11-24 21:11:25 +08:00
sakumisu
84299ce80b delete lwip rx thread in self 2023-11-24 21:11:05 +08:00
sakumisu
8e0c5b4e7e find roothub port to check if device is connecting 2023-11-24 21:09:45 +08:00
sakumisu
8ae4453ca4 fix en colon 2023-11-23 22:50:07 +08:00
Zhihong Chen
86c7e435a3 hpmicro: update port files
- update port files

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-11-23 15:21:11 +08:00
sakumisu
074f30a7b4 disable device not find log 2023-11-22 21:45:13 +08:00
sakumisu
50e1cd3471 add mutex for ep0 urb to avoid multithreading 2023-11-22 21:44:51 +08:00
sakumisu
b7d02b7125 reset rx length when pbuf allocs failed 2023-11-22 21:43:57 +08:00
sakumisu
5b32482c3e free pipe after sem giving 2023-11-22 21:42:56 +08:00
sakumisu
18eed18413 add some delay to avoid too much error log when device is disconnected 2023-11-22 19:28:30 +08:00
sakumisu
98c6ac25ec update readme 2023-11-22 19:28:30 +08:00
sakumisu
af1484882d support ehci suspend & resume 2023-11-22 19:28:30 +08:00
sakumisu
e3c9fdbb86 reduce qtd num 2023-11-22 19:28:30 +08:00
sakumisu
03db11f4af add ecm and rndis thread delete for dynamic netif 2023-11-22 19:28:30 +08:00
sakumisu
d6bd89f274 set CONFIG_USBHOST_PSC_PRIO to zero to making usb prio highest 2023-11-22 19:28:30 +08:00
sakumisu
9ea2121c7c make hub_set_feature and hub_clear_feature api public 2023-11-20 22:15:43 +08:00
sakumisu
bbcb433564 support host demo with timer for rtthread 2023-11-20 22:15:33 +08:00
sakumisu
7989708bfe add dhcp timer for getting ip addr 2023-11-20 16:59:18 +08:00
sakumisu
07fa211f40 remove rndis code in third party because it is implemented internally 2023-11-17 23:37:15 +08:00
sakumisu
73eb69bfa2 remove usb_mem.h 2023-11-17 21:05:31 +08:00
sakumisu
a08097c90e use static urb for ep0 2023-11-17 21:05:07 +08:00
sakumisu
5bbe2a97f2 refactor urb, add ep & hport in urb to make hardware pipe more reusable 2023-11-16 19:56:52 +08:00
110 changed files with 3367 additions and 19982 deletions

View File

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

View File

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

View File

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

@@ -0,0 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 0
PATCHLEVEL = 99
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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` 结构体信息如下:

View File

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

View File

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

View File

@@ -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使用 fsdevF4/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 无cacheH7 有 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 引脚一般使用 50000000ULSTM32F7/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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@
## AT32
- AT32F415xx
- AT32F402xx、AT32F405xx、AT32F415xx、AT32F423xx、AT32F425xx、AT32F435xx、AT32F437xx
## GD32

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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