update(cherryusb): update to v1.4.0
This commit is contained in:
parent
cbf6b641c2
commit
669a6822e7
|
@ -48,6 +48,10 @@ if RT_USING_CHERRYUSB
|
|||
bool "musb_bk"
|
||||
config RT_CHERRYUSB_DEVICE_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX
|
||||
bool "chipidea_mcx"
|
||||
config RT_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
|
||||
bool "chipidea_custom"
|
||||
config RT_CHERRYUSB_DEVICE_BL
|
||||
bool "bouffalo"
|
||||
config RT_CHERRYUSB_DEVICE_CH32
|
||||
|
@ -162,10 +166,12 @@ if RT_USING_CHERRYUSB
|
|||
bool "ehci_hpm"
|
||||
config RT_CHERRYUSB_HOST_EHCI_AIC
|
||||
bool "ehci_aic"
|
||||
config RT_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980
|
||||
bool "ehci_nuvoton_nuc980"
|
||||
config RT_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0
|
||||
bool "ehci_nuvoton_ma35d0"
|
||||
config RT_CHERRYUSB_HOST_EHCI_MCX
|
||||
bool "ehci_mcx"
|
||||
config RT_CHERRYUSB_HOST_EHCI_NUC980
|
||||
bool "ehci_nuc980"
|
||||
config RT_CHERRYUSB_HOST_EHCI_MA35D0
|
||||
bool "ehci_ma35d0"
|
||||
config RT_CHERRYUSB_HOST_EHCI_CUSTOM
|
||||
bool "ehci_custom"
|
||||
config RT_CHERRYUSB_HOST_DWC2_ST
|
||||
|
@ -294,7 +300,7 @@ if RT_USING_CHERRYUSB
|
|||
config CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
bool
|
||||
|
||||
config CHERRYUSB_HOST_TEMPLATE
|
||||
config RT_CHERRYUSB_HOST_TEMPLATE
|
||||
bool
|
||||
prompt "Use usb host template"
|
||||
default n
|
||||
|
|
|
@ -34,7 +34,7 @@ Taking into account USB performance issues and trying to achieve the theoretical
|
|||
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
|
||||
- Subcontracting function is handled in interrupt
|
||||
|
||||
## Directoy Structure
|
||||
## Directory Structure
|
||||
|
||||
| Directory | Description |
|
||||
|:-------------:|:---------------------------:|
|
||||
|
@ -65,15 +65,17 @@ CherryUSB Device Stack has the following functions:
|
|||
- Support Device Firmware Upgrade CLASS (DFU)
|
||||
- Support USB MIDI CLASS (MIDI)
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support WINUSB1.0、WINUSB2.0(with BOS)
|
||||
- Support WINUSB1.0、WINUSB2.0、WEBUSB、BOS
|
||||
- Support Vendor class
|
||||
- Support UF2
|
||||
- Support Android Debug Bridge (Only support shell)
|
||||
- Support multi device with the same USB IP
|
||||
|
||||
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_core.c | 3516 | 512(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|
@ -87,6 +89,7 @@ The CherryUSB Host Stack has a standard enumeration implementation for devices m
|
|||
|
||||
CherryUSB Host Stack has the following functions:
|
||||
|
||||
- Support low speed, full speed, high speed and super speed devices
|
||||
- Automatic loading of supported Class drivers
|
||||
- Support blocking transfers and asynchronous transfers
|
||||
- Support Composite Device
|
||||
|
@ -98,7 +101,7 @@ CherryUSB Host Stack has the following functions:
|
|||
- Support USB Audio CLASS (UAC1.0)
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
|
||||
- Support Vendor class
|
||||
- Support Vendor class (serial, net, wifi)
|
||||
- Support USB modeswitch
|
||||
- Support multi host with the same USB IP
|
||||
|
||||
|
@ -108,7 +111,7 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
|||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|
||||
|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 |
|
||||
|
@ -152,6 +155,7 @@ Only standard and commercial USB IP are listed.
|
|||
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||
|
@ -175,17 +179,26 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|
|||
|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 |
|
||||
|HPMicro | HPM6000/HPM5000 | 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 |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## Package Support
|
||||
|
||||
CherryUSB package is available as follows:
|
||||
|
||||
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
|
||||
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
|
||||
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
|
||||
|
||||
## Commercial Support
|
||||
|
||||
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
|
||||
|
|
|
@ -65,15 +65,17 @@ CherryUSB Device 协议栈当前实现以下功能:
|
|||
- 支持 Device Firmware Upgrade CLASS (DFU)
|
||||
- 支持 USB MIDI CLASS (MIDI)
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
||||
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 UF2
|
||||
- 支持 Android Debug Bridge (Only support shell)
|
||||
- 支持相同 USB IP 的多从机
|
||||
|
||||
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_core.c | 3516 | 512(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|
@ -87,6 +89,7 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了
|
|||
|
||||
CherryUSB Host 协议栈当前实现以下功能:
|
||||
|
||||
- 支持 low speed, full speed, high speed 和 super speed 设备
|
||||
- 自动加载支持的Class 驱动
|
||||
- 支持阻塞式传输和异步传输
|
||||
- 支持复合设备
|
||||
|
@ -98,7 +101,7 @@ CherryUSB Host 协议栈当前实现以下功能:
|
|||
- Support USB Audio CLASS (UAC1.0)
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 Vendor 类 class (serial, net, wifi)
|
||||
- 支持 USB modeswitch
|
||||
- 支持相同 USB IP 的多主机
|
||||
|
||||
|
@ -108,7 +111,7 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
|||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|
||||
|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 |
|
||||
|
@ -152,6 +155,7 @@ x 受以下宏影响:
|
|||
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||
|
@ -176,20 +180,29 @@ CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和
|
|||
|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 |
|
||||
|HPMicro | HPM6000/HPM5000 | 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 |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|
||||
## 软件包支持
|
||||
|
||||
CherryUSB 软件包可以通过以下方式获取:
|
||||
|
||||
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
|
||||
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
|
||||
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
|
||||
|
||||
## 商业支持
|
||||
|
||||
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html。
|
||||
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html 。
|
||||
|
||||
## 联系
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ path += [cwd + '/class/vendor/net']
|
|||
path += [cwd + '/class/vendor/serial']
|
||||
src = []
|
||||
|
||||
LIBS = []
|
||||
LIBPATH = []
|
||||
CPPDEFINES = []
|
||||
|
||||
# USB DEVICE
|
||||
|
@ -56,6 +58,9 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
|
|||
src += Glob('port/musb/usb_glue_bk.c')
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
|
||||
src += Glob('port/chipidea/usb_dc_chipidea.c')
|
||||
src += Glob('port/chipidea/usb_glue_mcx.c')
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_BL']):
|
||||
src += Glob('port/bouffalolab/usb_dc_bl.c')
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_HPM']):
|
||||
|
@ -68,6 +73,15 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
|
|||
src += Glob('port/ch32/usb_dc_usbhs.c')
|
||||
else:
|
||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_PUSB2']):
|
||||
path += [cwd + '/port/xhci/rt-thread']
|
||||
src += Glob('port/pusb2/rt-thread/usb_dc_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_dc_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_dc_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_ACM']):
|
||||
src += Glob('class/cdc/usbd_cdc.c')
|
||||
|
@ -140,10 +154,14 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
|
|||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_aic.c')
|
||||
src += Glob('port/ohci/usb_hc_ohci.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980']):
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_MCX']):
|
||||
path += [cwd + '/port/chipidea']
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_mcx.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUC980']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_nuc980.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_MA35D0']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_ma35d0.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_EHCI_CUSTOM']):
|
||||
|
@ -169,6 +187,26 @@ if GetDepend(['RT_CHERRYUSB_HOST']):
|
|||
src += Glob('port/musb/usb_glue_bk.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_MUSB_CUSTOM']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/rt-thread']
|
||||
src += Glob('port/pusb2/rt-thread/usb_hc_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_hc_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_hc_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_XHCI']):
|
||||
path += [cwd + '/port/xhci/phytium/rt-thread']
|
||||
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium_plat.c')
|
||||
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/xhci/phytium']
|
||||
LIBS = ['libxhci_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/xhci/phytium']
|
||||
LIBS = ['libxhci_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['RT_CHERRYUSB_HOST_CDC_ACM']):
|
||||
src += Glob('class/cdc/usbh_cdc_acm.c')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 3
|
||||
PATCHLEVEL = 1
|
||||
VERSION_MINOR = 4
|
||||
PATCHLEVEL = 0
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
|
|
|
@ -36,14 +36,16 @@ ${CMAKE_CURRENT_LIST_DIR}/class/audio
|
|||
${CMAKE_CURRENT_LIST_DIR}/class/video
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/wireless
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/midi
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/adb
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
|
||||
)
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC_ACM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_acm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
|
||||
|
@ -69,6 +71,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
|
|||
if(CONFIG_CHERRYUSB_DEVICE_DFU)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_ADB)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/adb/usbd_adb.c)
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
|
||||
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
|
||||
|
@ -97,6 +102,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
|
|||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_bk")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
|
||||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "chipidea_mcx")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_dc_chipidea.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_glue_mcx.c)
|
||||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
|
||||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
|
||||
|
@ -121,6 +129,9 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
|
||||
endif()
|
||||
|
@ -142,18 +153,10 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/chry_pool.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/usbh_uvc_queue.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
|
||||
|
||||
|
@ -209,6 +212,9 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||
if(CONFIG_CHERRYUSB_HOST_PL2303)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_BL616)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
|
||||
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
|
||||
|
@ -226,6 +232,12 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_mcx")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_mcx.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
|
||||
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_nuvoton")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
|
@ -260,5 +272,21 @@ if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
|||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_yoc.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "idf")
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/osal/idf)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/idf/usb_osal_idf.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "threadx")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_threadx.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYRB)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYMP)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/usbh_uvc_queue.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
|
||||
endif()
|
|
@ -6,16 +6,10 @@
|
|||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x010301
|
||||
#define CHERRYUSB_VERSION_STR "v1.3.1"
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
|
||||
#define usb_malloc(size) malloc(size)
|
||||
#define usb_free(ptr) free(ptr)
|
||||
|
||||
#ifndef CONFIG_USB_DBG_LEVEL
|
||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
||||
#endif
|
||||
|
@ -72,6 +66,10 @@
|
|||
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
||||
#endif
|
||||
|
||||
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
|
||||
// #define CONFIG_USBDEV_MSC_POLLING
|
||||
|
||||
/* move msc read & write from isr to thread */
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
|
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
|
||||
#define ADB_OUT_EP_IDX 0
|
||||
#define ADB_IN_EP_IDX 1
|
||||
|
||||
#define ADB_STATE_READ_MSG 0
|
||||
#define ADB_STATE_READ_DATA 1
|
||||
#define ADB_STATE_WRITE_MSG 2
|
||||
#define ADB_STATE_WRITE_DATA 3
|
||||
#define ADB_STATE_AWRITE_MSG 4
|
||||
#define ADB_STATE_AWRITE_DATA 5
|
||||
|
||||
#define MAX_PAYLOAD_V1 (4 * 1024)
|
||||
#define MAX_PAYLOAD_V2 (256 * 1024)
|
||||
#define MAX_PAYLOAD MAX_PAYLOAD_V1
|
||||
#define A_VERSION 0x01000000
|
||||
|
||||
#define A_SYNC 0x434e5953
|
||||
#define A_CNXN 0x4e584e43
|
||||
#define A_OPEN 0x4e45504f
|
||||
#define A_OKAY 0x59414b4f
|
||||
#define A_CLSE 0x45534c43
|
||||
#define A_WRTE 0x45545257
|
||||
#define A_AUTH 0x48545541
|
||||
|
||||
struct adb_msg {
|
||||
uint32_t command; /* command identifier constant (A_CNXN, ...) */
|
||||
uint32_t arg0; /* first argument */
|
||||
uint32_t arg1; /* second argument */
|
||||
uint32_t data_length; /* length of payload (0 is allowed) */
|
||||
uint32_t data_crc32; /* crc32 of data payload */
|
||||
uint32_t magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
struct adb_packet {
|
||||
struct adb_msg msg;
|
||||
uint8_t payload[MAX_PAYLOAD];
|
||||
};
|
||||
|
||||
struct usbd_adb {
|
||||
uint8_t state;
|
||||
uint8_t common_state;
|
||||
uint8_t write_state;
|
||||
bool writable;
|
||||
uint32_t localid;
|
||||
uint32_t shell_remoteid;
|
||||
uint32_t file_remoteid;
|
||||
} adb_client;
|
||||
|
||||
static struct usbd_endpoint adb_ep_data[2];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct adb_packet tx_packet;
|
||||
USB_NOCACHE_RAM_SECTION struct adb_packet rx_packet;
|
||||
|
||||
static inline uint32_t adb_packet_checksum(struct adb_packet *packet)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < packet->msg.data_length; ++i) {
|
||||
sum += (uint32_t)(packet->payload[i]);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t usbd_adb_get_remoteid(uint32_t localid)
|
||||
{
|
||||
if (localid == ADB_SHELL_LOALID) {
|
||||
return adb_client.shell_remoteid;
|
||||
} else {
|
||||
return adb_client.file_remoteid;
|
||||
}
|
||||
}
|
||||
|
||||
static void adb_send_msg(struct adb_packet *packet)
|
||||
{
|
||||
adb_client.common_state = ADB_STATE_WRITE_MSG;
|
||||
|
||||
packet->msg.data_crc32 = adb_packet_checksum(packet);
|
||||
packet->msg.magic = packet->msg.command ^ 0xffffffff;
|
||||
|
||||
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
|
||||
}
|
||||
|
||||
static void adb_send_okay(struct adb_packet *packet, uint32_t localid)
|
||||
{
|
||||
packet->msg.command = A_OKAY;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
|
||||
packet->msg.data_length = 0;
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
}
|
||||
|
||||
static void adb_send_close(struct adb_packet *packet, uint32_t localid, uint32_t remoteid)
|
||||
{
|
||||
packet->msg.command = A_CLSE;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = remoteid;
|
||||
packet->msg.data_length = 0;
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
}
|
||||
|
||||
void usbd_adb_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
if (adb_client.common_state == ADB_STATE_READ_MSG) {
|
||||
if (nbytes != sizeof(struct adb_msg)) {
|
||||
USB_LOG_ERR("invalid adb msg size:%d\r\n", nbytes);
|
||||
return;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
|
||||
rx_packet.msg.command,
|
||||
rx_packet.msg.arg0,
|
||||
rx_packet.msg.arg1,
|
||||
rx_packet.msg.data_length);
|
||||
|
||||
if (rx_packet.msg.data_length) {
|
||||
/* setup next out ep read transfer */
|
||||
adb_client.common_state = ADB_STATE_READ_DATA;
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, rx_packet.payload, rx_packet.msg.data_length);
|
||||
} else {
|
||||
if (rx_packet.msg.command == A_CLSE) {
|
||||
adb_client.writable = false;
|
||||
usbd_adb_notify_write_done();
|
||||
USB_LOG_INFO("Close remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
}
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
}
|
||||
} else if (adb_client.common_state == ADB_STATE_READ_DATA) {
|
||||
switch (rx_packet.msg.command) {
|
||||
case A_SYNC:
|
||||
|
||||
break;
|
||||
case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
|
||||
char *support_feature = "device::"
|
||||
"ro.product.name=cherryadb;"
|
||||
"ro.product.model=cherrysh;"
|
||||
"ro.product.device=cherryadb;"
|
||||
"features=cmd,shell_v1";
|
||||
|
||||
tx_packet.msg.command = A_CNXN;
|
||||
tx_packet.msg.arg0 = A_VERSION;
|
||||
tx_packet.msg.arg1 = MAX_PAYLOAD;
|
||||
tx_packet.msg.data_length = strlen(support_feature);
|
||||
memcpy(tx_packet.payload, support_feature, strlen(support_feature));
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
|
||||
adb_client.writable = false;
|
||||
break;
|
||||
case A_OPEN: /* OPEN(local-id, 0, "destination") */
|
||||
rx_packet.payload[rx_packet.msg.data_length] = '\0';
|
||||
|
||||
if (strncmp((const char *)rx_packet.payload, "shell:", 6) == 0) {
|
||||
adb_client.localid = ADB_SHELL_LOALID;
|
||||
adb_client.shell_remoteid = rx_packet.msg.arg0;
|
||||
adb_send_okay(&tx_packet, ADB_SHELL_LOALID);
|
||||
|
||||
USB_LOG_INFO("Open shell service, remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
} else if (strncmp((const char *)rx_packet.payload, "sync:", 5) == 0) {
|
||||
adb_client.localid = ADB_FILE_LOALID;
|
||||
adb_client.file_remoteid = rx_packet.msg.arg0;
|
||||
adb_send_okay(&tx_packet, ADB_FILE_LOALID);
|
||||
USB_LOG_INFO("Open file service, remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
}
|
||||
break;
|
||||
case A_OKAY:
|
||||
|
||||
break;
|
||||
case A_CLSE:
|
||||
|
||||
break;
|
||||
case A_WRTE: /* WRITE(local-id, remote-id, "data") */
|
||||
if ((rx_packet.msg.arg0 == adb_client.shell_remoteid) && (rx_packet.msg.arg1 == ADB_SHELL_LOALID)) {
|
||||
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
|
||||
} else if ((rx_packet.msg.arg0 == adb_client.file_remoteid) && (rx_packet.msg.arg1 == ADB_FILE_LOALID)) {
|
||||
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
|
||||
} else {
|
||||
adb_send_close(&tx_packet, 0, rx_packet.msg.arg0);
|
||||
}
|
||||
break;
|
||||
case A_AUTH:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_adb_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
if (adb_client.common_state == ADB_STATE_WRITE_MSG) {
|
||||
if (tx_packet.msg.data_length) {
|
||||
adb_client.common_state = ADB_STATE_WRITE_DATA;
|
||||
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
|
||||
} else {
|
||||
if (rx_packet.msg.command == A_WRTE) {
|
||||
adb_client.writable = true;
|
||||
if (adb_client.localid == ADB_SHELL_LOALID) {
|
||||
usbd_adb_notify_shell_read(rx_packet.payload, rx_packet.msg.data_length);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
}
|
||||
} else if (adb_client.common_state == ADB_STATE_WRITE_DATA) {
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
} else if (adb_client.write_state == ADB_STATE_AWRITE_MSG) {
|
||||
if (tx_packet.msg.data_length) {
|
||||
adb_client.write_state = ADB_STATE_AWRITE_DATA;
|
||||
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
|
||||
} else {
|
||||
}
|
||||
} else if (adb_client.write_state == ADB_STATE_AWRITE_DATA) {
|
||||
usbd_adb_notify_write_done();
|
||||
}
|
||||
}
|
||||
|
||||
void adb_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_INIT:
|
||||
break;
|
||||
case USBD_EVENT_DEINIT:
|
||||
break;
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = NULL;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = adb_notify_handler;
|
||||
|
||||
adb_ep_data[ADB_OUT_EP_IDX].ep_addr = out_ep;
|
||||
adb_ep_data[ADB_OUT_EP_IDX].ep_cb = usbd_adb_bulk_out;
|
||||
adb_ep_data[ADB_IN_EP_IDX].ep_addr = in_ep;
|
||||
adb_ep_data[ADB_IN_EP_IDX].ep_cb = usbd_adb_bulk_in;
|
||||
|
||||
usbd_add_endpoint(busid, &adb_ep_data[ADB_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(busid, &adb_ep_data[ADB_IN_EP_IDX]);
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
bool usbd_adb_can_write(void)
|
||||
{
|
||||
return adb_client.writable;
|
||||
}
|
||||
|
||||
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len)
|
||||
{
|
||||
struct adb_packet *packet;
|
||||
|
||||
packet = &tx_packet;
|
||||
packet->msg.command = A_WRTE;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
|
||||
packet->msg.data_length = len;
|
||||
memcpy(packet->payload, data, len);
|
||||
|
||||
packet->msg.data_crc32 = adb_packet_checksum(packet);
|
||||
packet->msg.magic = packet->msg.command ^ 0xffffffff;
|
||||
|
||||
adb_client.write_state = ADB_STATE_AWRITE_MSG;
|
||||
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbd_adb_close(uint32_t localid)
|
||||
{
|
||||
adb_send_close(&tx_packet, 0, usbd_adb_get_remoteid(localid));
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_ADB_H
|
||||
#define USBD_ADB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ADB_SHELL_LOALID 0x01
|
||||
#define ADB_FILE_LOALID 0x02
|
||||
|
||||
// clang-format off
|
||||
#define ADB_DESCRIPTOR_INIT(bFirstInterface, in_ep, out_ep, wMaxPacketSize) \
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(bFirstInterface, 0x00, 0x02, 0xff, 0x42, 0x01, 0x02), \
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(in_ep, 0x02, wMaxPacketSize, 0x00), \
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(out_ep, 0x02, wMaxPacketSize, 0x00)
|
||||
// clang-format on
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep);
|
||||
|
||||
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len);
|
||||
void usbd_adb_notify_file_read(uint8_t *data, uint32_t len);
|
||||
void usbd_adb_notify_write_done(void);
|
||||
bool usbd_adb_can_write(void);
|
||||
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len);
|
||||
void usbd_adb_close(uint32_t localid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_ADB_H */
|
|
@ -62,7 +62,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
|
|||
setup->bRequest);
|
||||
|
||||
uint8_t entity_id;
|
||||
uint8_t ep;
|
||||
uint8_t ep = 0;
|
||||
uint8_t subtype = 0x01;
|
||||
uint8_t control_selector;
|
||||
uint8_t ch;
|
||||
|
@ -314,31 +314,56 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
|||
|
||||
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
(void)mute;
|
||||
}
|
||||
|
||||
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)sampling_freq;
|
||||
}
|
||||
|
||||
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)sampling_freq_table;
|
||||
}
|
||||
|
|
|
@ -456,20 +456,26 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||
|
||||
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
|
||||
{
|
||||
(void)audio_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
{
|
||||
(void)audio_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver audio_ctrl_class_driver = {
|
||||
|
|
|
@ -1,29 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_CDC_H
|
||||
#define USBD_CDC_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
// legacy for old version
|
||||
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init cdc acm interface driver */
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_CDC_H */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
const char *stop_name[] = { "1", "1.5", "2" };
|
||||
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
||||
|
@ -85,6 +85,8 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
|
|||
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
|
@ -95,10 +97,16 @@ struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interfa
|
|||
|
||||
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)line_coding;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
|
||||
line_coding->dwDTERate = 2000000;
|
||||
line_coding->bDataBits = 8;
|
||||
line_coding->bParityType = 0;
|
||||
|
@ -107,12 +115,20 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc
|
|||
|
||||
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)dtr;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)rts;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_CDC_ACM_H
|
||||
#define USBD_CDC_ACM_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init cdc acm interface driver */
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_CDC_ACM_H */
|
|
@ -79,6 +79,10 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
|
|||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
(void)busid;
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
g_cmd_intf = LO_BYTE(setup->wIndex);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
|
@ -105,6 +109,9 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
|
|||
|
||||
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)busid;
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_current_net_status = 0;
|
||||
|
@ -123,19 +130,23 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
|||
|
||||
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
g_cdc_ecm_rx_data_length += nbytes;
|
||||
|
||||
if (nbytes < usbd_get_ep_mps(busid, ep)) {
|
||||
if (nbytes < usbd_get_ep_mps(0, ep)) {
|
||||
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
|
||||
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||
} else {
|
||||
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, ep));
|
||||
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep));
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
|
||||
(void)busid;
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(0, ep, NULL, 0);
|
||||
} else {
|
||||
|
@ -145,6 +156,10 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
|
||||
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
if (g_current_net_status == 1) {
|
||||
g_current_net_status = 2;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
|
||||
|
@ -242,4 +257,6 @@ void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
|
|||
|
||||
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
(void)buf;
|
||||
(void)len;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define DEV_FORMAT "/dev/ttyACM%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
@ -57,9 +57,9 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
|||
setup->wIndex = cdc_acm_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
|
||||
memcpy(g_cdc_acm_buf[cdc_acm_class->minor], line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
|
@ -78,11 +78,11 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
|||
setup->wIndex = cdc_acm_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
|
||||
memcpy(line_coding, g_cdc_acm_buf[cdc_acm_class->minor], sizeof(struct cdc_line_coding));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -231,20 +231,26 @@ int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *
|
|||
|
||||
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
(void)cdc_acm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
(void)cdc_acm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_acm_class_driver = {
|
||||
|
|
|
@ -236,6 +236,7 @@ void usbh_cdc_ecm_rx_thread(void *argument)
|
|||
uint32_t g_cdc_ecm_rx_length;
|
||||
int ret;
|
||||
|
||||
(void)argument;
|
||||
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
|
@ -306,10 +307,12 @@ int usbh_cdc_ecm_eth_output(uint32_t buflen)
|
|||
|
||||
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
(void)cdc_ecm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
(void)cdc_ecm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_ecm_class_driver = {
|
||||
|
|
|
@ -259,6 +259,7 @@ void usbh_cdc_ncm_rx_thread(void *argument)
|
|||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)argument;
|
||||
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
|
@ -330,7 +331,7 @@ find_class:
|
|||
#else
|
||||
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
@ -386,10 +387,12 @@ int usbh_cdc_ncm_eth_output(uint32_t buflen)
|
|||
|
||||
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||
{
|
||||
(void)cdc_ncm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||
{
|
||||
(void)cdc_ncm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_ncm_class_driver = {
|
||||
|
|
|
@ -558,26 +558,24 @@ struct usb_hid_kbd_report
|
|||
};
|
||||
|
||||
/* Keyboard output report (1 byte) (HID B.1),
|
||||
* see USBHID_KBDOUT_* definitions
|
||||
* see HID_KBD_OUTPUT_* definitions
|
||||
*/
|
||||
|
||||
/* Mouse input report (HID B.2) */
|
||||
struct usb_hid_mouse_report
|
||||
{
|
||||
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
|
||||
uint8_t xdisp; /* X displacement */
|
||||
uint8_t ydisp; /* y displacement */
|
||||
int8_t xdisp; /* X displacement */
|
||||
int8_t ydisp; /* y displacement */
|
||||
/* Device specific additional bytes may follow */
|
||||
#ifdef CONFIG_INPUT_MOUSE_WHEEL
|
||||
uint8_t wdisp; /* Wheel displacement */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Joystick input report (1 bytes) (HID D.1) */
|
||||
struct usb_hid_js_report
|
||||
{
|
||||
uint8_t xpos; /* X position */
|
||||
uint8_t ypos; /* X position */
|
||||
int8_t xpos; /* X position */
|
||||
int8_t ypos; /* X position */
|
||||
uint8_t buttons; /* See USBHID_JSIN_* definitions */
|
||||
uint8_t throttle; /* Throttle */
|
||||
};
|
||||
|
|
|
@ -50,6 +50,8 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
|
|||
|
||||
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = hid_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
|
@ -60,30 +62,65 @@ struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *
|
|||
return intf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Appendix G: HID Request Support Requirements
|
||||
*
|
||||
* The following table enumerates the requests that need to be supported by various types of HID class devices.
|
||||
* Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
|
||||
* ------------------------------------------------------------------------------------------
|
||||
* Boot Mouse Required Optional Optional Optional Required Required
|
||||
* Non-Boot Mouse Required Optional Optional Optional Optional Optional
|
||||
* Boot Keyboard Required Optional Required Required Required Required
|
||||
* Non-Boot Keybrd Required Optional Required Required Optional Optional
|
||||
* Other Device Required Optional Optional Optional Optional Optional
|
||||
*/
|
||||
|
||||
__WEAK void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)report_type;
|
||||
(*data[0]) = 0;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)report_type;
|
||||
(void)report;
|
||||
(void)report_len;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)duration;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)protocol;
|
||||
}
|
|
@ -12,7 +12,15 @@
|
|||
|
||||
#define DEV_FORMAT "/dev/input%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
|
||||
/* interface descriptor field offsets */
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[CONFIG_USBHOST_MAX_HID_CLASS][USB_ALIGN_UP(256, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
@ -56,13 +64,13 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b
|
|||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 128;
|
||||
setup->wLength = hid_class->report_size;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf, ret - 8);
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -100,11 +108,11 @@ 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, setup, g_hid_buf);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf, 1);
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -147,6 +155,7 @@ int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
|
|||
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
|
@ -159,13 +168,21 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
|
|||
setup->wIndex = 0;
|
||||
setup->wLength = buflen;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport, setup, buffer);
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t *p;
|
||||
bool found = false;
|
||||
|
||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||
if (hid_class == NULL) {
|
||||
|
@ -178,6 +195,47 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||
|
||||
hport->config.intf[intf].priv = hid_class;
|
||||
|
||||
p = hport->raw_config_desc;
|
||||
while (p[DESC_bLength]) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||
if (cur_iface == intf) {
|
||||
hid_class->protocol = p[7];
|
||||
struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9);
|
||||
|
||||
if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) {
|
||||
USB_LOG_ERR("HID descriptor not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) {
|
||||
USB_LOG_ERR("HID report descriptor not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
hid_class->report_size = desc->subdesc[0].wDescriptorLength;
|
||||
|
||||
if (hid_class->report_size > sizeof(g_hid_buf[hid_class->minor])) {
|
||||
USB_LOG_ERR("HID report descriptor too large\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
found = true;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
USB_LOG_ERR("HID interface not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
found:
|
||||
// /* 0x0 = boot protocol, 0x1 = report protocol */
|
||||
// ret = usbh_hid_set_protocol(hid_class, 0x1);
|
||||
// if (ret < 0) {
|
||||
|
@ -239,10 +297,12 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||
|
||||
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
(void)hid_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
(void)hid_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver hid_class_driver = {
|
||||
|
|
|
@ -16,6 +16,9 @@ struct usbh_hid {
|
|||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||
|
||||
uint8_t report_desc[256];
|
||||
uint16_t report_size;
|
||||
|
||||
uint8_t protocol;
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
|
||||
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
|
||||
|
||||
#define HUB_MAX_DEPTH 5
|
||||
|
||||
#define HUB_SUBCLASS 0x00
|
||||
#define HUB_PROTOCOL_STT 0x01
|
||||
#define HUB_PROTOCOL_MTT 0x02
|
||||
|
||||
/* Hub class requests */
|
||||
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
|
||||
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
|
||||
|
@ -32,18 +38,26 @@
|
|||
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
||||
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
||||
#define HUB_PORT_FEATURE_RESET (0x04)
|
||||
#define HUB_PORT_FEATURE_L1 (0x05)
|
||||
#define HUB_PORT_FEATURE_POWER (0x08)
|
||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
|
||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
|
||||
#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
|
||||
|
||||
#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_POWER_SS (0x09) /* USB 3.0 only */
|
||||
/* This is a bit tricky because HUB_PORT_FEATURE_POWER_SS and
|
||||
HUB_PORT_FEATURE_LOWSPEED share the same bit. */
|
||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_TEST (0x0b) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_INDICATOR (0x0c) /* USB 2.0 only */
|
||||
|
||||
/* Port status change (wPortChange) */
|
||||
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
|
||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
|
||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
|
||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
|
||||
#define HUB_PORT_FEATURE_C_RESET (0x14)
|
||||
#define HUB_PORT_FEATURE_TEST (0x15)
|
||||
#define HUB_PORT_FEATURE_INDICATOR (0x16)
|
||||
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
|
||||
#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
|
||||
#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
|
||||
#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
|
||||
|
||||
/* Hub status */
|
||||
#define HUB_STATUS_LOCALPOWER (1 << 0)
|
||||
|
@ -56,23 +70,42 @@
|
|||
/* Hub port status */
|
||||
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_SUSPEND (1 << 2) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_L1 (1 << 5)
|
||||
#define HUB_PORT_STATUS_L1 (1 << 5) /* USB 2.0 only */
|
||||
|
||||
/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U2 (0x02 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U3 (0x03 << 5)
|
||||
#define HUB_PORT_STATUS_LS_SS_DISABLED (0x04 << 5)
|
||||
#define HUB_PORT_STATUS_LS_RX_DETECT (0x05 << 5)
|
||||
#define HUB_PORT_STATUS_LS_SS_INACTIVE (0x06 << 5)
|
||||
#define HUB_PORT_STATUS_LS_POLLING (0x07 << 5)
|
||||
#define HUB_PORT_STATUS_LS_RECOVERY (0x08 << 5)
|
||||
#define HUB_PORT_STATUS_LS_HOT_RESET (0x09 << 5)
|
||||
#define HUB_PORT_STATUS_LS_COMP_MOD (0x0a << 5)
|
||||
#define HUB_PORT_STATUS_LS_LOOPBACK (0x0b << 5)
|
||||
|
||||
#define HUB_PORT_STATUS_POWER (1 << 8)
|
||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
|
||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
|
||||
#define HUB_PORT_STATUS_TEST (1 << 11)
|
||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
|
||||
#define HUB_PORT_STATUS_POWER_SS (1 << 9) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_TEST (1 << 11) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12) /* USB 2.0 only */
|
||||
|
||||
/* Hub port status change */
|
||||
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_C_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_C_L1 (1 << 5)
|
||||
#define HUB_PORT_STATUS_C_L1 (1 << 5) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_BH_RESET (1 << 5) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_C_PORTLINK (1 << 6) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_C_CONFIGERR (1 << 7) /* USB 3.0 only */
|
||||
|
||||
/* Hub characteristics */
|
||||
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
|
||||
|
@ -106,6 +139,21 @@ struct usb_hub_descriptor {
|
|||
|
||||
#define USB_SIZEOF_HUB_DESC 9
|
||||
|
||||
/* Super speed Hub descriptor */
|
||||
struct usb_hub_ss_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bNbrPorts;
|
||||
uint16_t wHubCharacteristics;
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
uint8_t bHubHdrDecLat;
|
||||
uint16_t wHubDelay;
|
||||
uint8_t DeviceRemovable;
|
||||
} __PACKED;
|
||||
|
||||
#define USB_SIZEOF_HUB_SS_DESC 11
|
||||
|
||||
/* Hub status */
|
||||
struct hub_status {
|
||||
uint16_t wPortStatus;
|
||||
|
|
|
@ -55,9 +55,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
|
|||
}
|
||||
memset(hub_class, 0, sizeof(struct usbh_hub));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
@ -67,15 +65,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
|||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
|
||||
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
|
||||
and we havn't handle the difference here */
|
||||
if ((hub->parent->speed == USB_SPEED_SUPER) ||
|
||||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||
} else {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
|
||||
}
|
||||
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||
|
@ -87,8 +77,8 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
|||
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
|
||||
static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
@ -96,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
|||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
||||
setup->wValue = 0;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
setup->wLength = USB_SIZEOF_HUB_SS_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hub_buf[hub->bus->busid], 2);
|
||||
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
|
@ -180,6 +170,8 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
|||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
|
||||
{
|
||||
(void)length;
|
||||
|
||||
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -1;
|
||||
|
@ -199,6 +191,29 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
|
||||
{
|
||||
(void)length;
|
||||
|
||||
if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -1;
|
||||
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
|
||||
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -2;
|
||||
} else {
|
||||
USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
|
||||
USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
|
||||
USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
|
||||
USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
|
||||
USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
|
||||
USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
|
@ -311,22 +326,65 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||
hub->hub_addr = hport->dev_addr;
|
||||
hub->parent = hport;
|
||||
hub->bus = hport->bus;
|
||||
hub->speed = hport->speed;
|
||||
|
||||
hport->self = hub;
|
||||
hport->config.intf[intf].priv = hub;
|
||||
|
||||
if (hport->depth > HUB_MAX_DEPTH) {
|
||||
USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Super-Speed hubs need to know their depth to be able to
|
||||
* parse the bits of the route-string that correspond to
|
||||
* their downstream port number.
|
||||
*
|
||||
*/
|
||||
if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
|
||||
ret = usbh_hub_set_depth(hub, hport->depth - 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Unable to set hub depth \r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get hub descriptor. */
|
||||
if (hport->speed == USB_SPEED_SUPER) {
|
||||
ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
|
||||
hub->nports = hub->hub_ss_desc.bNbrPorts;
|
||||
hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
|
||||
hub->tt_think = 0U;
|
||||
} else {
|
||||
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
|
||||
hub->nports = hub->hub_desc.bNbrPorts;
|
||||
hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
|
||||
hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hub->child[port].port = port + 1;
|
||||
hub->child[port].parent = hub;
|
||||
hub->child[port].bus = hport->bus;
|
||||
}
|
||||
|
||||
if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
|
||||
hub->ismtt = 1;
|
||||
} else {
|
||||
hub->ismtt = 0;
|
||||
}
|
||||
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(hub->intin, ep_desc);
|
||||
|
@ -334,28 +392,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (hport->speed == USB_SPEED_SUPER) {
|
||||
uint16_t depth = 0;
|
||||
struct usbh_hubport *parent = hport->parent->parent;
|
||||
while (parent) {
|
||||
depth++;
|
||||
parent = parent->parent->parent;
|
||||
}
|
||||
|
||||
ret = usbh_hub_set_depth(hub, depth);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
usb_osal_msleep(hub->powerdelay);
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
|
||||
if (ret < 0) {
|
||||
|
@ -395,7 +441,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||
usb_osal_timer_delete(hub->int_timer);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
child = &hub->child[port];
|
||||
usbh_hubport_release(child);
|
||||
child->parent = NULL;
|
||||
|
@ -415,7 +461,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||
{
|
||||
struct usbh_hubport *child;
|
||||
struct hub_port_status port_status;
|
||||
uint8_t portchange_index;
|
||||
uint16_t portchange_index;
|
||||
uint16_t portstatus;
|
||||
uint16_t portchange;
|
||||
uint16_t mask;
|
||||
|
@ -429,11 +475,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
portchange_index = hub->int_buffer[0];
|
||||
hub->int_buffer[0] &= ~portchange_index;
|
||||
memcpy(&portchange_index, hub->int_buffer, 2);
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
||||
|
||||
if (!(portchange_index & (1 << (port + 1)))) {
|
||||
|
@ -539,6 +584,11 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out device speed. This is a bit tricky because
|
||||
* HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
|
||||
*/
|
||||
if (portstatus & HUB_PORT_STATUS_POWER) {
|
||||
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||
speed = USB_SPEED_HIGH;
|
||||
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
||||
|
@ -546,6 +596,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||
} else {
|
||||
speed = USB_SPEED_FULL;
|
||||
}
|
||||
} else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
|
||||
speed = USB_SPEED_SUPER;
|
||||
} else {
|
||||
USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
child = &hub->child[port];
|
||||
/** release child sources first */
|
||||
|
@ -553,6 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||
|
||||
memset(child, 0, sizeof(struct usbh_hubport));
|
||||
child->parent = hub;
|
||||
child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
|
||||
child->connected = true;
|
||||
child->port = port + 1;
|
||||
child->speed = speed;
|
||||
|
@ -624,7 +681,7 @@ int usbh_hub_initialize(struct usbh_bus *bus)
|
|||
hub->is_roothub = true;
|
||||
hub->parent = NULL;
|
||||
hub->hub_addr = 1;
|
||||
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
hub->int_buffer = bus->hcd.roothub_intbuf;
|
||||
hub->bus = bus;
|
||||
|
||||
|
@ -652,7 +709,7 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
|
|||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
hub = &bus->hcd.roothub;
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
|
||||
usbh_hubport_release(hport);
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
struct usbh_hub;
|
||||
|
||||
#define USBH_HUB_MAX_PORTS 4
|
||||
/* Maximum size of an interrupt IN transfer */
|
||||
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "usb_scsi.h"
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
#include "usb_osal.h"
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
#include "chry_ringbuffer.h"
|
||||
#endif
|
||||
|
||||
#define MSD_OUT_EP_IDX 0
|
||||
|
@ -50,6 +52,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
|
|||
usb_osal_mq_t usbd_msc_mq;
|
||||
usb_osal_thread_t usbd_msc_thread;
|
||||
uint32_t nbytes;
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
chry_ringbuffer_t msc_rb;
|
||||
uint8_t msc_rb_pool[2];
|
||||
uint32_t nbytes;
|
||||
#endif
|
||||
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
|
||||
|
||||
|
@ -94,9 +100,11 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
|
|||
|
||||
void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_INIT:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
|
||||
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
|
||||
|
@ -105,10 +113,12 @@ void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
|||
if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
|
||||
}
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
chry_ringbuffer_init(&g_usbd_msc[busid].msc_rb, g_usbd_msc[busid].msc_rb_pool, sizeof(g_usbd_msc[busid].msc_rb_pool));
|
||||
#endif
|
||||
break;
|
||||
case USBD_EVENT_DEINIT:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
if (g_usbd_msc[busid].usbd_msc_mq) {
|
||||
usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
|
||||
}
|
||||
|
@ -500,6 +510,9 @@ static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
|
||||
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
|
@ -522,8 +535,10 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
return false;
|
||||
}
|
||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead(busid);
|
||||
|
@ -532,6 +547,9 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
|
||||
static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
|
@ -554,8 +572,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
return false;
|
||||
}
|
||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead(busid);
|
||||
|
@ -565,6 +585,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
|
@ -594,6 +618,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
|
@ -803,6 +831,8 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
|
|||
|
||||
void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
switch (g_usbd_msc[busid].stage) {
|
||||
case MSC_READ_CBW:
|
||||
if (SCSI_CBWDecode(busid, nbytes) == false) {
|
||||
|
@ -815,9 +845,12 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||
case SCSI_CMD_WRITE10:
|
||||
case SCSI_CMD_WRITE12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
g_usbd_msc[busid].nbytes = nbytes;
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].nbytes = nbytes;
|
||||
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_OUT);
|
||||
#else
|
||||
if (SCSI_processWrite(busid, nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
|
@ -835,13 +868,18 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
|
||||
void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
switch (g_usbd_msc[busid].stage) {
|
||||
case MSC_DATA_IN:
|
||||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||
case SCSI_CMD_READ10:
|
||||
case SCSI_CMD_READ12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
|
||||
#else
|
||||
if (SCSI_processRead(busid) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
|
@ -870,7 +908,7 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
static void usbdev_msc_thread(void *argument)
|
||||
{
|
||||
uintptr_t event;
|
||||
|
@ -882,7 +920,26 @@ static void usbdev_msc_thread(void *argument)
|
|||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
USB_LOG_DBG("%d\r\n", event);
|
||||
USB_LOG_DBG("event:%d\r\n", event);
|
||||
if (event == MSC_DATA_OUT) {
|
||||
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else if (event == MSC_DATA_IN) {
|
||||
if (SCSI_processRead(busid) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
void usbd_msc_polling(uint8_t busid)
|
||||
{
|
||||
uint8_t event;
|
||||
|
||||
if (chry_ringbuffer_read_byte(&g_usbd_msc[busid].msc_rb, &event)) {
|
||||
USB_LOG_DBG("event:%d\r\n", event);
|
||||
if (event == MSC_DATA_OUT) {
|
||||
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
|
@ -932,7 +989,7 @@ void usbd_msc_set_readonly(uint8_t busid, bool readonly)
|
|||
g_usbd_msc[busid].readonly = readonly;
|
||||
}
|
||||
|
||||
bool usbd_msc_set_popup(uint8_t busid)
|
||||
bool usbd_msc_get_popup(uint8_t busid)
|
||||
{
|
||||
return g_usbd_msc[busid].popup;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *b
|
|||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
|
||||
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
|
||||
bool usbd_msc_set_popup(uint8_t busid);
|
||||
bool usbd_msc_get_popup(uint8_t busid);
|
||||
|
||||
void usbd_msc_polling(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#define MSC_INQUIRY_TIMEOUT 500
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
@ -87,6 +87,8 @@ static void usbh_msc_cbw_dump(struct CBW *cbw)
|
|||
|
||||
static void usbh_msc_csw_dump(struct CSW *csw)
|
||||
{
|
||||
(void)csw;
|
||||
|
||||
USB_LOG_DBG("CSW:\r\n");
|
||||
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
|
||||
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
|
||||
|
@ -182,14 +184,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
|
||||
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL, MSC_INQUIRY_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
||||
|
@ -197,7 +199,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
|
@ -207,7 +209,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
|||
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
|
||||
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
||||
|
@ -215,7 +217,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
|
@ -225,7 +227,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
|||
cbw->CB[0] = SCSI_CMD_INQUIRY;
|
||||
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
|
@ -233,7 +235,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
|
@ -242,7 +244,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
|||
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
|
||||
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf, MSC_INQUIRY_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
|
||||
|
@ -250,11 +252,11 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
|
||||
memcpy(g_msc_buf, message, 31);
|
||||
memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
|
||||
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL, MSC_INQUIRY_TIMEOUT);
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
|
||||
}
|
||||
|
||||
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
@ -274,12 +276,12 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
|||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][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;
|
||||
|
@ -376,7 +378,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
|
@ -387,7 +389,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
|
|||
SET_BE32(&cbw->CB[2], start_sector);
|
||||
SET_BE16(&cbw->CB[7], nsectors);
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
|
||||
|
@ -395,7 +397,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
|
|||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
|
@ -407,7 +409,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
|
|||
SET_BE32(&cbw->CB[2], start_sector);
|
||||
SET_BE16(&cbw->CB[7], nsectors);
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
|
@ -421,10 +423,12 @@ void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
|||
|
||||
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
(void)msc_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
(void)msc_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver msc_class_driver = {
|
||||
|
|
|
@ -680,6 +680,7 @@ void usbh_asix_rx_thread(void *argument)
|
|||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)argument;
|
||||
USB_LOG_INFO("Create asix rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
|
@ -742,7 +743,7 @@ find_class:
|
|||
#else
|
||||
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
@ -791,10 +792,12 @@ int usbh_asix_eth_output(uint32_t buflen)
|
|||
|
||||
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
|
||||
{
|
||||
(void)asix_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
|
||||
{
|
||||
(void)asix_class;
|
||||
}
|
||||
|
||||
static const uint16_t asix_id_table[][2] = {
|
||||
|
|
|
@ -2140,6 +2140,7 @@ void usbh_rtl8152_rx_thread(void *argument)
|
|||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)argument;
|
||||
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
|
@ -2210,7 +2211,7 @@ find_class:
|
|||
#else
|
||||
if ((g_rtl8152_rx_length + (16 * 1024)) > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE\r\n");
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
@ -2248,10 +2249,12 @@ int usbh_rtl8152_eth_output(uint32_t buflen)
|
|||
|
||||
__WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
|
||||
{
|
||||
(void)rtl8152_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
|
||||
{
|
||||
(void)rtl8152_class;
|
||||
}
|
||||
|
||||
static const uint16_t rtl_id_table[][2] = {
|
||||
|
|
|
@ -349,10 +349,12 @@ int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer
|
|||
|
||||
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
(void)ch34x_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
(void)ch34x_class;
|
||||
}
|
||||
|
||||
static const uint16_t ch34x_id_table[][2] = {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
|
||||
|
||||
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
@ -298,10 +298,12 @@ int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buf
|
|||
|
||||
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
(void)cp210x_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
(void)cp210x_class;
|
||||
}
|
||||
|
||||
static const uint16_t cp210x_id_table[][2] = {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_FTDI_CLASS 1
|
||||
|
||||
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
@ -57,7 +57,7 @@ static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_
|
|||
}
|
||||
int divisor = FTDI_USB_CLK / baudrate;
|
||||
int frac_bits = 0;
|
||||
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
|
||||
for (uint8_t i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
|
||||
if ((divisor & 0xF) == frac[i]) {
|
||||
frac_bits = i;
|
||||
break;
|
||||
|
@ -370,10 +370,12 @@ int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, u
|
|||
|
||||
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
(void)ftdi_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
(void)ftdi_class;
|
||||
}
|
||||
|
||||
static const uint16_t ftdi_id_table[][2] = {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[64];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_PL2303_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_PL2303_CLASS 1
|
||||
|
||||
#define UT_WRITE_VENDOR_DEVICE (USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
|
||||
#define UT_READ_VENDOR_DEVICE (USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
|
||||
|
@ -413,10 +413,12 @@ int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buf
|
|||
|
||||
__WEAK void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
(void)pl2303_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
(void)pl2303_class;
|
||||
}
|
||||
|
||||
static const uint16_t pl2303_id_table[][2] = {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# BL616 USB WIFI
|
||||
|
||||
Usbwifi firmware please contact bouffalolab. You can purchase a module in the following ways:
|
||||
|
||||
- https://iot.mi.com/moduleBrowser.html
|
||||
- https://docs.ai-thinker.com/ai_m61
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_bl616.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_bl616"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/wifi/bl616"
|
||||
|
||||
#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
#define ARR_ELE_6(e) (e)[0], (e)[1], (e)[2], (e)[3], (e)[4], (e)[5]
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_tx_buffer[2048 + 512];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_rx_buffer[2048 + 512];
|
||||
|
||||
static struct usbh_bl616 g_bl616_class;
|
||||
|
||||
static const char *auth_to_str(uint8_t auth)
|
||||
{
|
||||
const char *table[RNM_WIFI_AUTH_MAX] = {
|
||||
[RNM_WIFI_AUTH_UNKNOWN] = "UNKNOWN",
|
||||
[RNM_WIFI_AUTH_OPEN] = "OPEN",
|
||||
[RNM_WIFI_AUTH_WEP] = "WEP",
|
||||
[RNM_WIFI_AUTH_WPA_PSK] = "WPA-PSK",
|
||||
[RNM_WIFI_AUTH_WPA2_PSK] = "WPA2-PSK",
|
||||
[RNM_WIFI_AUTH_WPA_WPA2_PSK] = "WPA2-PSK/WPA-PSK",
|
||||
[RNM_WIFI_AUTH_WPA_ENTERPRISE] = "WPA-ENT",
|
||||
[RNM_WIFI_AUTH_WPA3_SAE] = "WPA3-SAE",
|
||||
[RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE] = "WPA2-PSK/WPA3-SAE",
|
||||
};
|
||||
if (auth < RNM_WIFI_AUTH_MAX)
|
||||
return table[auth];
|
||||
else
|
||||
return table[RNM_WIFI_AUTH_UNKNOWN];
|
||||
}
|
||||
|
||||
static const char *cipher_to_str(uint8_t cipher)
|
||||
{
|
||||
const char *table[RNM_WIFI_CIPHER_MAX] = {
|
||||
[RNM_WIFI_CIPHER_UNKNOWN] = "UNKNOWN",
|
||||
[RNM_WIFI_CIPHER_NONE] = "NONE",
|
||||
[RNM_WIFI_CIPHER_WEP] = "WEP",
|
||||
[RNM_WIFI_CIPHER_AES] = "AES",
|
||||
[RNM_WIFI_CIPHER_TKIP] = "TKIP",
|
||||
[RNM_WIFI_CIPHER_TKIP_AES] = "TKIP/AES",
|
||||
};
|
||||
if (cipher < RNM_WIFI_CIPHER_MAX)
|
||||
return table[cipher];
|
||||
else
|
||||
return table[RNM_WIFI_CIPHER_UNKNOWN];
|
||||
}
|
||||
|
||||
static int parse_get_mac_rsp_msg(struct usbh_bl616 *bl616_class, void *buf, int buf_len)
|
||||
{
|
||||
usb_data_t *usb_hdr = buf;
|
||||
rnm_mac_addr_ind_msg_t *rsp = buf + sizeof(usb_data_t);
|
||||
|
||||
if (buf_len != sizeof(usb_data_t) + sizeof(rnm_mac_addr_ind_msg_t)) {
|
||||
return -1;
|
||||
}
|
||||
if (usb_hdr->type != USBWIFI_DATA_TYPE_CMD || usb_hdr->length != sizeof(rnm_mac_addr_ind_msg_t)) {
|
||||
return -1;
|
||||
}
|
||||
if (rsp->hdr.cmd != BFLB_CMD_GET_MAC_ADDR || !(rsp->hdr.flags & RNM_MSG_FLAG_ACK)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(bl616_class->sta_mac, rsp->sta_mac, 6);
|
||||
memcpy(bl616_class->ap_mac, rsp->ap_mac, 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_bl616_bulk_in_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &bl616_class->bulkin_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_bulk_out_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &bl616_class->bulkout_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_get_wifi_mac(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
int ret;
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *rnm_msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(rnm_msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
rnm_msg->cmd = BFLB_CMD_GET_MAC_ADDR;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
ret = usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_bl616_bulk_in_transfer(bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = parse_get_mac_rsp_msg(bl616_class, g_bl616_rx_buffer, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_wifi_open(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_HELLO;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
static int usbh_bl616_wifi_close(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_UNLOAD_DRV;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_sta_connect(const char *ssid,
|
||||
const int ssid_len,
|
||||
const char *password,
|
||||
const int pwd_len)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_sta_connect_msg_t *msg = (rnm_sta_connect_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_sta_connect_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_sta_connect_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->hdr.cmd = BFLB_CMD_STA_CONNECT;
|
||||
msg->hdr.msg_id = 0x0001;
|
||||
msg->hdr.session_id = 0x0002;
|
||||
msg->ssid_len = ssid_len;
|
||||
memcpy(msg->ssid, ssid, ssid_len);
|
||||
if (password) {
|
||||
memcpy(msg->password, password, pwd_len);
|
||||
}
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_sta_connect_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_sta_disconnect(void)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_STA_DISCONNECT;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_get_wifi_scan_result(void)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_SCAN_RESULTS;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_scan(void)
|
||||
{
|
||||
int ret;
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_SCAN;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
ret = usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
usb_osal_msleep(500);
|
||||
return usbh_bl616_get_wifi_scan_result();
|
||||
}
|
||||
|
||||
static int usbh_bl616_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bl616 *bl616_class = &g_bl616_class;
|
||||
|
||||
memset(bl616_class, 0, sizeof(struct usbh_bl616));
|
||||
|
||||
bl616_class->hport = hport;
|
||||
bl616_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = bl616_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(bl616_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(bl616_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
usbh_bl616_get_wifi_mac(bl616_class);
|
||||
usbh_bl616_wifi_close(bl616_class);
|
||||
usbh_bl616_wifi_open(bl616_class);
|
||||
|
||||
USB_LOG_INFO("BL616 WIFI STA MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
bl616_class->sta_mac[0],
|
||||
bl616_class->sta_mac[1],
|
||||
bl616_class->sta_mac[2],
|
||||
bl616_class->sta_mac[3],
|
||||
bl616_class->sta_mac[4],
|
||||
bl616_class->sta_mac[5]);
|
||||
|
||||
USB_LOG_INFO("BL616 WIFI AP MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
bl616_class->ap_mac[0],
|
||||
bl616_class->ap_mac[1],
|
||||
bl616_class->ap_mac[2],
|
||||
bl616_class->ap_mac[3],
|
||||
bl616_class->ap_mac[4],
|
||||
bl616_class->ap_mac[5]);
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_bl616_run(bl616_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bl616 *bl616_class = (struct usbh_bl616 *)hport->config.intf[intf].priv;
|
||||
|
||||
if (bl616_class) {
|
||||
if (bl616_class->bulkin) {
|
||||
usbh_kill_urb(&bl616_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (bl616_class->bulkout) {
|
||||
usbh_kill_urb(&bl616_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_bl616_stop(bl616_class);
|
||||
}
|
||||
|
||||
memset(bl616_class, 0, sizeof(struct usbh_bl616));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bl616_rx_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
usb_data_t *usb_hdr;
|
||||
rnm_base_msg_t *msg;
|
||||
rnm_sta_ip_update_ind_msg_t *ipmsg;
|
||||
rnm_scan_ind_msg_t *scanmsg;
|
||||
uint8_t *data;
|
||||
|
||||
(void)argument;
|
||||
USB_LOG_INFO("Create bl616 wifi rx thread\r\n");
|
||||
|
||||
while (1) {
|
||||
ret = usbh_bl616_bulk_in_transfer(&g_bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), USB_OSAL_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
usb_hdr = (usb_data_t *)g_bl616_rx_buffer;
|
||||
|
||||
if (usb_hdr->type == USBWIFI_DATA_TYPE_CMD) {
|
||||
msg = (rnm_base_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
|
||||
switch (msg->cmd) {
|
||||
case BFLB_CMD_STA_CONNECTED_IND:
|
||||
USB_LOG_INFO("AP connected\n");
|
||||
g_bl616_class.connect_status = true;
|
||||
usbh_bl616_sta_connect_callback();
|
||||
|
||||
break;
|
||||
case BFLB_CMD_STA_DISCONNECTED_IND:
|
||||
if (g_bl616_class.connect_status == true) {
|
||||
g_bl616_class.connect_status = false;
|
||||
USB_LOG_INFO("AP disconnected\n");
|
||||
usbh_bl616_sta_disconnect_callback();
|
||||
}
|
||||
break;
|
||||
case BFLB_CMD_STA_IP_UPDATE_IND:
|
||||
ipmsg = (rnm_sta_ip_update_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
|
||||
USB_LOG_INFO("WIFI IP update\r\n");
|
||||
USB_LOG_INFO("WIFI IPv4 Address : %d:%d:%d:%d\r\n",
|
||||
ipmsg->ip4_addr[0],
|
||||
ipmsg->ip4_addr[1],
|
||||
ipmsg->ip4_addr[2],
|
||||
ipmsg->ip4_addr[3]);
|
||||
USB_LOG_INFO("WIFI IPv4 Mask : %d:%d:%d:%d\r\n",
|
||||
ipmsg->ip4_mask[0],
|
||||
ipmsg->ip4_mask[1],
|
||||
ipmsg->ip4_mask[2],
|
||||
ipmsg->ip4_mask[3]);
|
||||
USB_LOG_INFO("WIFI IPv4 Gateway : %d:%d:%d:%d\r\n\r\n",
|
||||
ipmsg->ip4_gw[0],
|
||||
ipmsg->ip4_gw[1],
|
||||
ipmsg->ip4_gw[2],
|
||||
ipmsg->ip4_gw[3]);
|
||||
|
||||
g_bl616_class.mode = BL_MODE_STA;
|
||||
usbh_bl616_sta_update_ip(ipmsg->ip4_addr, ipmsg->ip4_mask, ipmsg->ip4_gw);
|
||||
break;
|
||||
case BFLB_CMD_SCAN_RESULTS:
|
||||
scanmsg = (rnm_scan_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
USB_LOG_INFO("WIFI scan result:\r\n");
|
||||
for (uint32_t i = 0; i < scanmsg->num; ++i) {
|
||||
struct bf1b_wifi_scan_record *r = &scanmsg->records[i];
|
||||
USB_LOG_INFO("BSSID " MAC_FMT ", channel %u, rssi %d, auth %s, cipher %s, SSID %s\r\n",
|
||||
ARR_ELE_6(r->bssid), r->channel, r->rssi,
|
||||
auth_to_str(r->auth_mode), cipher_to_str(r->cipher), r->ssid);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (usb_hdr->type == USBWIFI_DATA_TYPE_PKT) {
|
||||
data = (uint8_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
usbh_bl616_eth_input(data, usb_hdr->length);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Delete bl616 wifi rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
}
|
||||
|
||||
uint8_t *usbh_bl616_get_eth_txbuf(void)
|
||||
{
|
||||
return (g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
}
|
||||
|
||||
int usbh_bl616_eth_output(uint32_t buflen)
|
||||
{
|
||||
usb_data_t *usb_hdr;
|
||||
uint32_t txlen;
|
||||
|
||||
if (g_bl616_class.connect_status == false) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_PKT;
|
||||
usb_hdr->length = buflen;
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
txlen = buflen + sizeof(usb_data_t);
|
||||
if (!(txlen % USB_GET_MAXPACKETSIZE(g_bl616_class.bulkout->wMaxPacketSize))) {
|
||||
txlen += 1;
|
||||
}
|
||||
USB_LOG_DBG("txlen:%d\r\n", txlen);
|
||||
|
||||
usbh_bulk_urb_fill(&g_bl616_class.bulkout_urb, g_bl616_class.hport, g_bl616_class.bulkout, g_bl616_tx_buffer, txlen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_bl616_class.bulkout_urb);
|
||||
}
|
||||
|
||||
int wifi_sta_connect(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
USB_LOG_ERR("Usage: %s <ssid> <password>\r\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
usbh_bl616_wifi_sta_connect(argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_scan(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
usbh_bl616_wifi_scan();
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bl616_run(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
(void)bl616_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bl616_stop(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
(void)bl616_class;
|
||||
}
|
||||
|
||||
static const uint16_t bl616_id_table[][2] = {
|
||||
{ 0x349b, 0x616f },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct usbh_class_driver bl616_class_driver = {
|
||||
.driver_name = "bl616_wifi",
|
||||
.connect = usbh_bl616_connect,
|
||||
.disconnect = usbh_bl616_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.id_table = bl616_id_table,
|
||||
.class_driver = &bl616_class_driver
|
||||
};
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_BL616_H
|
||||
#define USBH_BL616_H
|
||||
|
||||
#define USBWIFI_DATA_TYPE_CMD 0xA55A
|
||||
#define USBWIFI_DATA_TYPE_PKT 0x6996
|
||||
|
||||
#define USB_DATA_FLAG_AP_PKT (1u << 0)
|
||||
|
||||
typedef enum {
|
||||
BFLB_CMD_REBOOT = 0,
|
||||
BFLB_CMD_RESET,
|
||||
BFLB_CMD_HELLO,
|
||||
BFLB_CMD_PING,
|
||||
|
||||
BFLB_CMD_GET_MAC_ADDR,
|
||||
|
||||
// Scan
|
||||
BFLB_CMD_SCAN,
|
||||
BFLB_CMD_SCAN_RESULTS,
|
||||
|
||||
// STA
|
||||
BFLB_CMD_STA_CONNECT,
|
||||
BFLB_CMD_STA_DISCONNECT,
|
||||
BFLB_CMD_STA_CONNECTED_IND,
|
||||
BFLB_CMD_STA_DISCONNECTED_IND,
|
||||
BFLB_CMD_STA_IP_UPDATE_IND,
|
||||
BFLB_CMD_STA_SET_AUTO_RECONNECT,
|
||||
BFLB_CMD_STA_GET_LINK_STATUS,
|
||||
|
||||
// AP
|
||||
BFLB_CMD_AP_START,
|
||||
BFLB_CMD_AP_STOP,
|
||||
BFLB_CMD_AP_STARTED_IND,
|
||||
BFLB_CMD_AP_STOPPED_IND,
|
||||
BFLB_CMD_AP_GET_STA_LIST,
|
||||
|
||||
// Monitor
|
||||
BFLB_CMD_MONITOR_START,
|
||||
BFLB_CMD_MONITOR_STOP,
|
||||
BFLB_CMD_MONITOR_SET_CHANNEL,
|
||||
BFLB_CMD_MONITOR_GET_CHANNEL,
|
||||
|
||||
BFLB_CMD_SET_LPM_MODE,
|
||||
|
||||
// OTA
|
||||
BFLB_CMD_GET_DEV_VERSION,
|
||||
BFLB_CMD_OTA,
|
||||
|
||||
BFLB_CMD_EXT,
|
||||
|
||||
BFLB_CMD_USER_EXT,
|
||||
BFLB_CMD_UNLOAD_DRV,
|
||||
|
||||
BFLB_CMD_MAX,
|
||||
} bflb_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
STATUS_OK,
|
||||
STATUS_NOMEM = 128,
|
||||
STATUS_INVALID_INPUT,
|
||||
STATUS_INVALID_MODE,
|
||||
STATUS_ERR_UNSPECIFIED,
|
||||
STATUS_NOT_IMPLEMENTED,
|
||||
} cmd_status_t;
|
||||
|
||||
typedef enum {
|
||||
RNM_WIFI_AUTH_UNKNOWN = 0,
|
||||
RNM_WIFI_AUTH_OPEN,
|
||||
RNM_WIFI_AUTH_WEP,
|
||||
RNM_WIFI_AUTH_WPA_PSK,
|
||||
RNM_WIFI_AUTH_WPA2_PSK,
|
||||
RNM_WIFI_AUTH_WPA_WPA2_PSK,
|
||||
RNM_WIFI_AUTH_WPA_ENTERPRISE,
|
||||
RNM_WIFI_AUTH_WPA3_SAE,
|
||||
RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE,
|
||||
RNM_WIFI_AUTH_MAX,
|
||||
} rnm_wifi_auth_mode_t;
|
||||
|
||||
typedef enum {
|
||||
RNM_WIFI_CIPHER_UNKNOWN = 0,
|
||||
RNM_WIFI_CIPHER_NONE,
|
||||
RNM_WIFI_CIPHER_WEP,
|
||||
RNM_WIFI_CIPHER_AES,
|
||||
RNM_WIFI_CIPHER_TKIP,
|
||||
RNM_WIFI_CIPHER_TKIP_AES,
|
||||
RNM_WIFI_CIPHER_MAX,
|
||||
} rnm_wifi_cipher_t;
|
||||
|
||||
/* common header */
|
||||
typedef struct {
|
||||
uint16_t cmd;
|
||||
// flag ACK is used by server to indicate a response to client
|
||||
#define RNM_MSG_FLAG_ACK (1 << 0)
|
||||
// flag TRANSPARENT is never transfered to peer but used locally
|
||||
#define RNM_MSG_FLAG_TRANSPARENT (1 << 1)
|
||||
// flag ASYNC is used by server to notify client events such as STA_CONNECTED
|
||||
#define RNM_MSG_FLAG_ASYNC (1 << 2)
|
||||
uint16_t flags;
|
||||
uint16_t status;
|
||||
uint16_t msg_id;
|
||||
uint16_t session_id;
|
||||
uint16_t msg_id_replying;
|
||||
} rnm_base_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
} rnm_ack_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint8_t sta_mac[6];
|
||||
uint8_t ap_mac[6];
|
||||
} rnm_mac_addr_ind_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint16_t ssid_len;
|
||||
uint8_t ssid[32];
|
||||
uint8_t password[64];
|
||||
} rnm_sta_connect_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint8_t ip4_addr[4];
|
||||
uint8_t ip4_mask[4];
|
||||
uint8_t ip4_gw[4];
|
||||
uint8_t ip4_dns1[4];
|
||||
uint8_t ip4_dns2[4];
|
||||
uint8_t gw_mac[6];
|
||||
} rnm_sta_ip_update_ind_msg_t;
|
||||
|
||||
struct bf1b_wifi_scan_record {
|
||||
uint8_t bssid[6];
|
||||
// TODO use compressed SSID encoding to save room
|
||||
uint8_t ssid[32 + 1];
|
||||
uint16_t channel;
|
||||
int8_t rssi;
|
||||
uint8_t auth_mode;
|
||||
uint8_t cipher;
|
||||
} __PACKED;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint16_t num;
|
||||
struct bf1b_wifi_scan_record records[];
|
||||
} rnm_scan_ind_msg_t;
|
||||
|
||||
typedef enum {
|
||||
BL_MODE_NONE,
|
||||
BL_MODE_STA, // card is STA
|
||||
BL_MODE_AP, // card is AP
|
||||
BL_MODE_STA_AP, // card is STA&AP
|
||||
BL_MODE_SNIFFER, // card is sniffer
|
||||
BL_MODE_MAX,
|
||||
} bl_wifi_mode_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint16_t flags;
|
||||
uint16_t payload_offset;
|
||||
uint32_t rsvd[8];
|
||||
uint8_t payload[];
|
||||
} __attribute__((aligned(4))) usb_data_t;
|
||||
|
||||
struct usbh_bl616 {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
|
||||
uint8_t intf;
|
||||
|
||||
uint8_t sta_mac[6];
|
||||
uint8_t ap_mac[6];
|
||||
uint8_t mode;
|
||||
bool connect_status;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_bl616_wifi_sta_connect(const char *ssid,
|
||||
const int ssid_len,
|
||||
const char *password,
|
||||
const int pwd_len);
|
||||
|
||||
int usbh_bl616_wifi_sta_disconnect(void);
|
||||
int usbh_bl616_wifi_scan(void);
|
||||
|
||||
void usbh_bl616_sta_connect_callback(void);
|
||||
void usbh_bl616_sta_disconnect_callback(void);
|
||||
void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t ip4_gw[4]);
|
||||
|
||||
uint8_t *usbh_bl616_get_eth_txbuf(void);
|
||||
int usbh_bl616_eth_output(uint32_t buflen);
|
||||
void usbh_bl616_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_bl616_rx_thread(void *argument);
|
||||
|
||||
void usbh_bl616_run(struct usbh_bl616 *bl616_class);
|
||||
void usbh_bl616_stop(struct usbh_bl616 *bl616_class);
|
||||
|
||||
int wifi_sta_connect(int argc, char **argv);
|
||||
int wifi_scan(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_BL616_H */
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Till Harbaum
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_xbox.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/xbox%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_xbox_buf[128];
|
||||
|
||||
static struct usbh_xbox g_xbox_class[CONFIG_USBHOST_MAX_XBOX_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_xbox *usbh_xbox_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
memset(&g_xbox_class[devno], 0, sizeof(struct usbh_xbox));
|
||||
g_xbox_class[devno].minor = devno;
|
||||
return &g_xbox_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_xbox_class_free(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
int devno = xbox_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
memset(xbox_class, 0, sizeof(struct usbh_xbox));
|
||||
}
|
||||
|
||||
int usbh_xbox_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
|
||||
struct usbh_xbox *xbox_class = usbh_xbox_class_alloc();
|
||||
if (xbox_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc xbox_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
xbox_class->hport = hport;
|
||||
xbox_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = xbox_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(xbox_class->intin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(xbox_class->intout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, xbox_class->minor);
|
||||
|
||||
USB_LOG_INFO("Register XBOX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_xbox_run(xbox_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_xbox_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_xbox *xbox_class = (struct usbh_xbox *)hport->config.intf[intf].priv;
|
||||
|
||||
if (xbox_class) {
|
||||
if (xbox_class->intin) {
|
||||
usbh_kill_urb(&xbox_class->intin_urb);
|
||||
}
|
||||
|
||||
if (xbox_class->intout) {
|
||||
usbh_kill_urb(&xbox_class->intout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister XBOX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_xbox_stop(xbox_class);
|
||||
}
|
||||
|
||||
usbh_xbox_class_free(xbox_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_xbox_run(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_xbox_stop(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver xbox_class_driver = {
|
||||
.driver_name = "xbox",
|
||||
.connect = usbh_xbox_connect,
|
||||
.disconnect = usbh_xbox_disconnect
|
||||
};
|
||||
|
||||
static const uint16_t xbox_id_table[][2] = {
|
||||
{ 0x0079, 0x18d4 }, // GPD Win 2 X-Box Controller
|
||||
{ 0x03eb, 0xff01 }, // Wooting One (Legacy)
|
||||
{ 0x03eb, 0xff02 }, // Wooting Two (Legacy)
|
||||
{ 0x044f, 0xb326 }, // Thrustmaster Gamepad GP XID
|
||||
{ 0x045e, 0x028e }, // Microsoft X-Box 360 pad
|
||||
{ 0x045e, 0x028f }, // Microsoft X-Box 360 pad v2
|
||||
{ 0x046d, 0xc21d }, // Logitech Gamepad F310
|
||||
{ 0x046d, 0xc21e }, // Logitech Gamepad F510
|
||||
{ 0x046d, 0xc21f }, // Logitech Gamepad F710
|
||||
{ 0x046d, 0xc242 }, // Logitech Chillstream Controller
|
||||
{ 0x046d, 0xcaa3 }, // Logitech DriveFx Racing Wheel
|
||||
{ 0x056e, 0x2004 }, // Elecom JC-U3613M
|
||||
{ 0x06a3, 0xf51a }, // Saitek P3600
|
||||
{ 0x0738, 0x4716 }, // Mad Catz Wired Xbox 360 Controller
|
||||
{ 0x0738, 0x4718 }, // Mad Catz Street Fighter IV FightStick SE
|
||||
{ 0x0738, 0x4726 }, // Mad Catz Xbox 360 Controller
|
||||
{ 0x0738, 0x4736 }, // Mad Catz MicroCon Gamepad
|
||||
{ 0x0738, 0x4740 }, // Mad Catz Beat Pad
|
||||
{ 0x0738, 0x9871 }, // Mad Catz Portable Drum
|
||||
{ 0x0738, 0xb726 }, // Mad Catz Xbox controller - MW2
|
||||
{ 0x0738, 0xbeef }, // Mad Catz JOYTECH NEO SE Advanced GamePad
|
||||
{ 0x0738, 0xcb02 }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
|
||||
{ 0x0738, 0xcb03 }, // Saitek P3200 Rumble Pad - PC/Xbox 360
|
||||
{ 0x0738, 0xcb29 }, // Saitek Aviator Stick AV8R02
|
||||
{ 0x0738, 0xf738 }, // Super SFIV FightStick TE S
|
||||
{ 0x07ff, 0xffff }, // Mad Catz GamePad
|
||||
{ 0x0e6f, 0x0113 }, // Afterglow AX.1 Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x011f }, // Rock Candy Gamepad Wired Controller
|
||||
{ 0x0e6f, 0x0131 }, // PDP EA Sports Controller
|
||||
{ 0x0e6f, 0x0133 }, // Xbox 360 Wired Controller
|
||||
{ 0x0e6f, 0x0201 }, // Pelican PL-3601 'TSZ' Wired Xbox 360 Controller
|
||||
{ 0x0e6f, 0x0213 }, // Afterglow Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x021f }, // Rock Candy Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x0301 }, // Logic3 Controller
|
||||
{ 0x0e6f, 0x0401 }, // Logic3 Controller
|
||||
{ 0x0e6f, 0x0413 }, // Afterglow AX.1 Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x0501 }, // PDP Xbox 360 Controller
|
||||
{ 0x0e6f, 0xf900 }, // PDP Afterglow AX.1
|
||||
{ 0x0f0d, 0x000a }, // Hori Co. DOA4 FightStick
|
||||
{ 0x0f0d, 0x000c }, // Hori PadEX Turbo
|
||||
{ 0x1038, 0x1430 }, // SteelSeries Stratus Duo
|
||||
{ 0x1038, 0x1431 }, // SteelSeries Stratus Duo
|
||||
{ 0x11c9, 0x55f0 }, // Nacon GC-100XF
|
||||
{ 0x1209, 0x2882 }, // Ardwiino Controller
|
||||
{ 0x12ab, 0x0301 }, // PDP AFTERGLOW AX.1
|
||||
{ 0x1430, 0x4748 }, // RedOctane Guitar Hero X-plorer
|
||||
{ 0x1430, 0xf801 }, // RedOctane Controller
|
||||
{ 0x146b, 0x0601 }, // BigBen Interactive XBOX 360 Controller
|
||||
{ 0x1532, 0x0037 }, // Razer Sabertooth
|
||||
{ 0x15e4, 0x3f00 }, // Power A Mini Pro Elite
|
||||
{ 0x15e4, 0x3f0a }, // Xbox Airflo wired controller
|
||||
{ 0x15e4, 0x3f10 }, // Batarang Xbox 360 controller
|
||||
{ 0x162e, 0xbeef }, // Joytech Neo-Se Take2
|
||||
{ 0x1689, 0xfd00 }, // Razer Onza Tournament Edition
|
||||
{ 0x1689, 0xfd01 }, // Razer Onza Classic Edition
|
||||
{ 0x1689, 0xfe00 }, // Razer Sabertooth
|
||||
{ 0x1949, 0x041a }, // Amazon Game Controller
|
||||
{ 0x1bad, 0x0002 }, // Harmonix Rock Band Guitar
|
||||
{ 0x1bad, 0xf016 }, // Mad Catz Xbox 360 Controller
|
||||
{ 0x1bad, 0xf021 }, // Mad Cats Ghost Recon FS GamePad
|
||||
{ 0x1bad, 0xf023 }, // MLG Pro Circuit Controller (Xbox)
|
||||
{ 0x1bad, 0xf025 }, // Mad Catz Call Of Duty
|
||||
{ 0x1bad, 0xf027 }, // Mad Catz FPS Pro
|
||||
{ 0x1bad, 0xf028 }, // Street Fighter IV FightPad
|
||||
{ 0x1bad, 0xf030 }, // Mad Catz Xbox 360 MC2 MicroCon Racing Wheel
|
||||
{ 0x1bad, 0xf036 }, // Mad Catz MicroCon GamePad Pro
|
||||
{ 0x1bad, 0xf038 }, // Street Fighter IV FightStick TE
|
||||
{ 0x1bad, 0xf501 }, // HoriPad EX2 Turbo
|
||||
{ 0x1bad, 0xf506 }, // Hori Real Arcade Pro.EX Premium VLX
|
||||
{ 0x1bad, 0xf900 }, // Harmonix Xbox 360 Controller
|
||||
{ 0x1bad, 0xf901 }, // Gamestop Xbox 360 Controller
|
||||
{ 0x1bad, 0xf903 }, // Tron Xbox 360 controller
|
||||
{ 0x1bad, 0xf904 }, // PDP Versus Fighting Pad
|
||||
{ 0x1bad, 0xfa01 }, // MadCatz GamePad
|
||||
{ 0x1bad, 0xfd00 }, // Razer Onza TE
|
||||
{ 0x1bad, 0xfd01 }, // Razer Onza
|
||||
{ 0x20d6, 0x2001 }, // BDA Xbox Series X Wired Controller
|
||||
{ 0x20d6, 0x281f }, // PowerA Wired Controller For Xbox 360
|
||||
{ 0x24c6, 0x5300 }, // PowerA MINI PROEX Controller
|
||||
{ 0x24c6, 0x5303 }, // Xbox Airflo wired controller
|
||||
{ 0x24c6, 0x530a }, // Xbox 360 Pro EX Controller
|
||||
{ 0x24c6, 0x531a }, // PowerA Pro Ex
|
||||
{ 0x24c6, 0x5397 }, // FUS1ON Tournament Controller
|
||||
{ 0x24c6, 0x5500 }, // Hori XBOX 360 EX 2 with Turbo
|
||||
{ 0x24c6, 0x5501 }, // Hori Real Arcade Pro VX-SA
|
||||
{ 0x24c6, 0x5506 }, // Hori SOULCALIBUR V Stick
|
||||
{ 0x24c6, 0x550d }, // Hori GEM Xbox controller
|
||||
{ 0x24c6, 0x5b00 }, // ThrustMaster Ferrari 458 Racing Wheel
|
||||
{ 0x24c6, 0x5b02 }, // Thrustmaster, Inc. GPX Controller
|
||||
{ 0x24c6, 0x5b03 }, // Thrustmaster Ferrari 458 Racing Wheel
|
||||
{ 0x24c6, 0x5d04 }, // Razer Sabertooth
|
||||
{ 0x24c6, 0xfafe }, // Rock Candy Gamepad for Xbox 360
|
||||
{ 0x2563, 0x058d }, // OneXPlayer Gamepad
|
||||
{ 0x2dc8, 0x3106 }, // 8BitDo Ultimate Wireless / Pro 2 Wired Controller
|
||||
{ 0x2dc8, 0x3109 }, // 8BitDo Ultimate Wireless Bluetooth
|
||||
{ 0x31e3, 0x1100 }, // Wooting One
|
||||
{ 0x31e3, 0x1200 }, // Wooting Two
|
||||
{ 0x31e3, 0x1210 }, // Wooting Lekker
|
||||
{ 0x31e3, 0x1220 }, // Wooting Two HE
|
||||
{ 0x31e3, 0x1230 }, // Wooting Two HE (ARM)
|
||||
{ 0x31e3, 0x1300 }, // Wooting 60HE (AVR)
|
||||
{ 0x31e3, 0x1310 }, // Wooting 60HE (ARM)
|
||||
{ 0x3285, 0x0607 }, // Nacon GC-100
|
||||
{ 0x413d, 0x2104 }, // Black Shark Green Ghost Gamepad
|
||||
{ 0x0000, 0x0000 } // end of list
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VEND_SPECIFIC,
|
||||
.subclass = 0x5d,
|
||||
.protocol = 0x01,
|
||||
.id_table = xbox_id_table,
|
||||
.class_driver = &xbox_class_driver
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Till Harbaum
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_XBOX_H
|
||||
#define USBH_XBOX_H
|
||||
|
||||
struct usbh_xbox {
|
||||
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 intf; /* interface number */
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_xbox_run(struct usbh_xbox *xbox_class);
|
||||
void usbh_xbox_stop(struct usbh_xbox *xbox_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_XBOX_H */
|
|
@ -24,6 +24,8 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
|
|||
{
|
||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||
|
||||
(void)busid;
|
||||
|
||||
switch (control_selector) {
|
||||
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
|
|
|
@ -495,20 +495,26 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|||
|
||||
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
|
|
|
@ -102,6 +102,8 @@ static void rndis_notify_rsp(void)
|
|||
|
||||
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||||
rndis_encapsulated_cmd_handler(*data, setup->wLength);
|
||||
|
@ -152,6 +154,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
|||
rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
|
@ -177,6 +181,9 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
|
|||
{
|
||||
rndis_halt_msg_t *resp;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageLength = 0;
|
||||
|
||||
|
@ -192,6 +199,8 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
|||
uint8_t *infomation_buffer;
|
||||
uint32_t infomation_len = 0;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
resp->RequestId = cmd->RequestId;
|
||||
|
@ -338,6 +347,8 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
|||
rndis_set_cmplt_t *resp;
|
||||
rndis_config_parameter_t *param;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
|
@ -394,6 +405,9 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
|||
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
rndis_reset_cmplt_t *resp;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
|
||||
|
@ -412,6 +426,8 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
|||
rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
|
@ -425,6 +441,9 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
|||
|
||||
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)busid;
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
|
@ -445,6 +464,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
{
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
||||
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
|
||||
|
@ -461,7 +483,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
|
||||
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
|
||||
(void)busid;
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(0, ep, NULL, 0);
|
||||
} else {
|
||||
|
@ -471,6 +495,10 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||
|
||||
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
//USB_LOG_DBG("len:%d\r\n", nbytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -365,14 +365,18 @@ delete :
|
|||
|
||||
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
(void)bluetooth_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
(void)bluetooth_class;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver bluetooth_class_driver = {
|
||||
|
|
|
@ -26,6 +26,7 @@ static struct usbh_rndis g_rndis_class;
|
|||
|
||||
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
// int ret;
|
||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
||||
|
||||
|
@ -460,6 +461,8 @@ void usbh_rndis_rx_thread(void *argument)
|
|||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)argument;
|
||||
|
||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
|
@ -531,7 +534,7 @@ find_class:
|
|||
#else
|
||||
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
@ -581,10 +584,12 @@ int usbh_rndis_eth_output(uint32_t buflen)
|
|||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver rndis_class_driver = {
|
||||
|
|
|
@ -33,6 +33,13 @@ int usb_dc_deinit(uint8_t busid);
|
|||
*/
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr);
|
||||
|
||||
/**
|
||||
* @brief Set remote wakeup feature
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbd_set_remote_wakeup(uint8_t busid);
|
||||
|
||||
/**
|
||||
* @brief Get USB device speed
|
||||
*
|
||||
|
|
|
@ -614,7 +614,7 @@ struct usb_webusb_url_descriptor {
|
|||
char URL[];
|
||||
} __PACKED;
|
||||
|
||||
struct usb_webusb_url_ex_descriptor {
|
||||
struct usb_webusb_descriptor {
|
||||
uint8_t vendor_code;
|
||||
const uint8_t *string;
|
||||
uint32_t string_len;
|
||||
|
|
|
@ -82,4 +82,31 @@ void usb_assert(const char *filename, int linenum);
|
|||
usb_assert(__FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ptr;
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0; i < buflen; i += 16) {
|
||||
CONFIG_USB_PRINTF("%08X:", i);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen) {
|
||||
if ((j % 8) == 0) {
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
}
|
||||
|
||||
CONFIG_USB_PRINTF("%02X ", buf[i + j]);
|
||||
} else
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen)
|
||||
CONFIG_USB_PRINTF("%c", ___is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
CONFIG_USB_PRINTF("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USB_LOG_H */
|
||||
|
|
|
@ -58,4 +58,7 @@ void usb_osal_leave_critical_section(size_t flag);
|
|||
|
||||
void usb_osal_msleep(uint32_t delay);
|
||||
|
||||
void *usb_osal_malloc(size_t size);
|
||||
void usb_osal_free(void *ptr);
|
||||
|
||||
#endif /* USB_OSAL_H */
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_VERSION_H
|
||||
#define USB_VERSION_H
|
||||
|
||||
#ifdef CHERRYUSB_VERSION
|
||||
#warning "Please do not define CHERRYUSB_VERSION in usb_config.h"
|
||||
#undef CHERRYUSB_VERSION
|
||||
#endif
|
||||
#ifdef CHERRYUSB_VERSION_STR
|
||||
#warning "Please do not define CHERRYUSB_VERSION_STR in usb_config.h"
|
||||
#undef CHERRYUSB_VERSION_STR
|
||||
#endif
|
||||
|
||||
#define CHERRYUSB_VERSION 0x010400
|
||||
#define CHERRYUSB_VERSION_STR "v1.4.0"
|
||||
|
||||
#endif
|
|
@ -45,12 +45,18 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
|
|||
struct usb_msosv1_descriptor *msosv1_desc;
|
||||
struct usb_msosv2_descriptor *msosv2_desc;
|
||||
struct usb_bos_descriptor *bos_desc;
|
||||
struct usb_webusb_descriptor *webusb_url_desc;
|
||||
#endif
|
||||
/* Buffer used for storing standard, class and vendor request data */
|
||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||
|
||||
/** Currently selected configuration */
|
||||
uint8_t configuration;
|
||||
uint8_t device_address;
|
||||
bool self_powered;
|
||||
bool remote_wakeup_support;
|
||||
bool remote_wakeup_enabled;
|
||||
bool is_suspend;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
uint8_t speed;
|
||||
#endif
|
||||
|
@ -174,6 +180,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
|
|||
break;
|
||||
}
|
||||
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
|
||||
|
||||
g_usbd_core[busid].self_powered = (desc[7] & USB_CONFIG_POWERED_MASK) ? true : false;
|
||||
g_usbd_core[busid].remote_wakeup_support = (desc[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
||||
|
@ -336,6 +345,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
|
|||
*/
|
||||
*len = (p[CONF_DESC_wTotalLength]) |
|
||||
(p[CONF_DESC_wTotalLength + 1] << 8);
|
||||
|
||||
g_usbd_core[busid].self_powered = (p[7] & USB_CONFIG_POWERED_MASK) ? true : false;
|
||||
g_usbd_core[busid].remote_wakeup_support = (p[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
|
||||
} else {
|
||||
/* normally length is at offset 0 */
|
||||
*len = p[DESC_bLength];
|
||||
|
@ -522,6 +534,12 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||
/* bit 0: self-powered */
|
||||
/* bit 1: remote wakeup */
|
||||
(*data)[0] = 0x00;
|
||||
if (g_usbd_core[busid].self_powered) {
|
||||
(*data)[0] |= USB_GETSTATUS_SELF_POWERED;
|
||||
}
|
||||
if (g_usbd_core[busid].remote_wakeup_enabled) {
|
||||
(*data)[0] |= USB_GETSTATUS_REMOTE_WAKEUP;
|
||||
}
|
||||
(*data)[1] = 0x00;
|
||||
*len = 2;
|
||||
break;
|
||||
|
@ -530,8 +548,10 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||
case USB_REQUEST_SET_FEATURE:
|
||||
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
||||
if (setup->bRequest == USB_REQUEST_SET_FEATURE) {
|
||||
g_usbd_core[busid].remote_wakeup_enabled = true;
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SET_REMOTE_WAKEUP);
|
||||
} else {
|
||||
g_usbd_core[busid].remote_wakeup_enabled = false;
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CLR_REMOTE_WAKEUP);
|
||||
}
|
||||
} else if (value == USB_FEATURE_TEST_MODE) {
|
||||
|
@ -543,6 +563,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||
break;
|
||||
|
||||
case USB_REQUEST_SET_ADDRESS:
|
||||
g_usbd_core[busid].device_address = value;
|
||||
usbd_set_address(busid, value);
|
||||
*len = 0;
|
||||
break;
|
||||
|
@ -556,17 +577,20 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||
break;
|
||||
|
||||
case USB_REQUEST_GET_CONFIGURATION:
|
||||
*data = (uint8_t *)&g_usbd_core[busid].configuration;
|
||||
(*data)[0] = g_usbd_core[busid].configuration;
|
||||
*len = 1;
|
||||
break;
|
||||
|
||||
case USB_REQUEST_SET_CONFIGURATION:
|
||||
value &= 0xFF;
|
||||
|
||||
if (!usbd_set_configuration(busid, value, 0)) {
|
||||
if (value == 0) {
|
||||
g_usbd_core[busid].configuration = 0;
|
||||
} else if (!usbd_set_configuration(busid, value, 0)) {
|
||||
ret = false;
|
||||
} else {
|
||||
g_usbd_core[busid].configuration = value;
|
||||
g_usbd_core[busid].is_suspend = false;
|
||||
usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CONFIGURED);
|
||||
}
|
||||
|
@ -600,6 +624,16 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
|
|||
uint8_t type = HI_BYTE(setup->wValue);
|
||||
uint8_t intf_num = LO_BYTE(setup->wIndex);
|
||||
bool ret = true;
|
||||
const uint8_t *p;
|
||||
uint32_t desc_len = 0;
|
||||
uint32_t current_desc_len = 0;
|
||||
uint8_t cur_iface = 0xFF;
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed);
|
||||
#else
|
||||
p = (uint8_t *)g_usbd_core[busid].descriptors;
|
||||
#endif
|
||||
|
||||
/* Only when device is configured, then interface requests can be valid. */
|
||||
if (!is_device_configured(busid)) {
|
||||
|
@ -614,7 +648,39 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
|
|||
break;
|
||||
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
|
||||
if (type == 0x21) { /* HID_DESCRIPTOR_TYPE_HID */
|
||||
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:
|
||||
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||
break;
|
||||
case 0x21:
|
||||
if (cur_iface == intf_num) {
|
||||
*data = (uint8_t *)p;
|
||||
//memcpy(*data, p, p[DESC_bLength]);
|
||||
*len = p[DESC_bLength];
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
current_desc_len += p[DESC_bLength];
|
||||
if (current_desc_len >= desc_len && desc_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
|
||||
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
|
||||
|
||||
|
@ -663,6 +729,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
|
|||
{
|
||||
uint8_t ep = (uint8_t)setup->wIndex;
|
||||
bool ret = true;
|
||||
uint8_t stalled;
|
||||
|
||||
/* Only when device is configured, then endpoint requests can be valid. */
|
||||
if (!is_device_configured(busid)) {
|
||||
|
@ -671,7 +738,12 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
|
|||
|
||||
switch (setup->bRequest) {
|
||||
case USB_REQUEST_GET_STATUS:
|
||||
usbd_ep_is_stalled(busid, ep, &stalled);
|
||||
if (stalled) {
|
||||
(*data)[0] = 0x01;
|
||||
} else {
|
||||
(*data)[0] = 0x00;
|
||||
}
|
||||
(*data)[1] = 0x00;
|
||||
*len = 2;
|
||||
break;
|
||||
|
@ -841,10 +913,12 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
|
||||
}
|
||||
|
||||
if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
|
||||
if (setup->bRequest == g_usbd_core[busid].descriptors->webusb_url_descriptor->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
|
||||
case WEBUSB_REQUEST_GET_URL:
|
||||
desclen = g_usbd_core[busid].descriptors->webusb_url_descriptor->string_len;
|
||||
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
|
||||
//memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen);
|
||||
|
@ -897,6 +971,22 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_usbd_core[busid].webusb_url_desc) {
|
||||
if (setup->bRequest == g_usbd_core[busid].webusb_url_desc->vendor_code) {
|
||||
switch (setup->wIndex) {
|
||||
case WEBUSB_REQUEST_GET_URL:
|
||||
desclen = g_usbd_core[busid].webusb_url_desc->string_len;
|
||||
*data = (uint8_t *)g_usbd_core[busid].webusb_url_desc->string;
|
||||
//memcpy(*data, g_usbd_core[busid].webusb_url_desc->string, desclen);
|
||||
*len = desclen;
|
||||
return 0;
|
||||
default:
|
||||
USB_LOG_ERR("unknown vendor code\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
|
||||
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
|
||||
|
@ -985,17 +1075,22 @@ void usbd_event_disconnect_handler(uint8_t busid)
|
|||
|
||||
void usbd_event_resume_handler(uint8_t busid)
|
||||
{
|
||||
g_usbd_core[busid].is_suspend = false;
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESUME);
|
||||
}
|
||||
|
||||
void usbd_event_suspend_handler(uint8_t busid)
|
||||
{
|
||||
if (g_usbd_core[busid].device_address > 0) {
|
||||
g_usbd_core[busid].is_suspend = true;
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_event_reset_handler(uint8_t busid)
|
||||
{
|
||||
usbd_set_address(busid, 0);
|
||||
g_usbd_core[busid].device_address = 0;
|
||||
g_usbd_core[busid].configuration = 0;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
|
||||
|
@ -1091,6 +1186,8 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
|
|||
{
|
||||
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
|
||||
|
||||
(void)ep;
|
||||
|
||||
g_usbd_core[busid].ep0_data_buf += nbytes;
|
||||
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
|
||||
|
||||
|
@ -1130,6 +1227,8 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
|
|||
{
|
||||
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
|
||||
|
||||
(void)ep;
|
||||
|
||||
if (nbytes > 0) {
|
||||
g_usbd_core[busid].ep0_data_buf += nbytes;
|
||||
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
|
||||
|
@ -1213,6 +1312,11 @@ void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc)
|
|||
{
|
||||
g_usbd_core[busid].bos_desc = desc;
|
||||
}
|
||||
|
||||
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc)
|
||||
{
|
||||
g_usbd_core[busid].webusb_url_desc = desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
|
||||
|
@ -1256,7 +1360,30 @@ bool usb_device_is_configured(uint8_t busid)
|
|||
return g_usbd_core[busid].configuration;
|
||||
}
|
||||
|
||||
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
|
||||
bool usb_device_is_suspend(uint8_t busid)
|
||||
{
|
||||
return g_usbd_core[busid].is_suspend;
|
||||
}
|
||||
|
||||
int usbd_send_remote_wakeup(uint8_t busid)
|
||||
{
|
||||
if (g_usbd_core[busid].remote_wakeup_support && g_usbd_core[busid].remote_wakeup_enabled && g_usbd_core[busid].is_suspend) {
|
||||
return usbd_set_remote_wakeup(busid);
|
||||
} else {
|
||||
if (!g_usbd_core[busid].remote_wakeup_support) {
|
||||
USB_LOG_ERR("device does not support remote wakeup\r\n");
|
||||
}
|
||||
if (!g_usbd_core[busid].remote_wakeup_enabled) {
|
||||
USB_LOG_ERR("device remote wakeup is not enabled\r\n");
|
||||
}
|
||||
if (!g_usbd_core[busid].is_suspend) {
|
||||
USB_LOG_ERR("device is not in suspend state\r\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
|
||||
{
|
||||
int ret;
|
||||
struct usbd_bus *bus;
|
||||
|
@ -1279,9 +1406,9 @@ int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint
|
|||
|
||||
int usbd_deinitialize(uint8_t busid)
|
||||
{
|
||||
g_usbd_core[busid].intf_offset = 0;
|
||||
usb_dc_deinit(busid);
|
||||
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
|
||||
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
|
||||
usb_dc_deinit(busid);
|
||||
g_usbd_core[busid].intf_offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ extern "C" {
|
|||
#include "usb_log.h"
|
||||
#include "usb_dc.h"
|
||||
#include "usb_memcpy.h"
|
||||
#include "usb_version.h"
|
||||
|
||||
enum usbd_event_type {
|
||||
/* USB DCD IRQ */
|
||||
|
@ -71,13 +72,13 @@ struct usb_descriptor {
|
|||
const char *(*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_webusb_descriptor *webusb_url_descriptor;
|
||||
const struct usb_bos_descriptor *bos_descriptor;
|
||||
};
|
||||
|
||||
struct usbd_bus {
|
||||
uint8_t busid;
|
||||
uint32_t reg_base;
|
||||
uintptr_t reg_base;
|
||||
};
|
||||
|
||||
extern struct usbd_bus g_usbdev_bus[];
|
||||
|
@ -93,6 +94,7 @@ void usbd_desc_register(uint8_t busid, const uint8_t *desc);
|
|||
void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc);
|
||||
void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc);
|
||||
void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc);
|
||||
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc);
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
|
||||
|
@ -101,8 +103,10 @@ void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
|
|||
uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep);
|
||||
uint8_t usbd_get_ep_mult(uint8_t busid, uint8_t ep);
|
||||
bool usb_device_is_configured(uint8_t busid);
|
||||
bool usb_device_is_suspend(uint8_t busid);
|
||||
int usbd_send_remote_wakeup(uint8_t busid);
|
||||
|
||||
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
|
||||
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
|
||||
int usbd_deinitialize(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -486,7 +486,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||
goto errout;
|
||||
}
|
||||
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
|
||||
hport->raw_config_desc = usb_malloc(wTotalLength);
|
||||
hport->raw_config_desc = usb_osal_malloc(wTotalLength);
|
||||
if (hport->raw_config_desc == NULL) {
|
||||
ret = -USB_ERR_NOMEM;
|
||||
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
||||
|
@ -549,7 +549,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||
setup->wLength = 16;
|
||||
|
||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
||||
if (ret < 0 && (ret != -EPERM)) {
|
||||
if (ret < 0 && (ret != -USB_ERR_STALL)) {
|
||||
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||
|
||||
errout:
|
||||
if (hport->raw_config_desc) {
|
||||
usb_free(hport->raw_config_desc);
|
||||
usb_osal_free(hport->raw_config_desc);
|
||||
hport->raw_config_desc = NULL;
|
||||
}
|
||||
return ret;
|
||||
|
@ -600,7 +600,7 @@ void usbh_hubport_release(struct usbh_hubport *hport)
|
|||
}
|
||||
}
|
||||
|
||||
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
|
||||
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
memset(bus, 0, sizeof(struct usbh_bus));
|
||||
bus->busid = busid;
|
||||
|
@ -613,7 +613,7 @@ static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base
|
|||
usb_slist_add_tail(&g_bus_head, &bus->list);
|
||||
}
|
||||
|
||||
int usbh_initialize(uint8_t busid, uint32_t reg_base)
|
||||
int usbh_initialize(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
struct usbh_bus *bus;
|
||||
|
||||
|
@ -731,7 +731,7 @@ static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devn
|
|||
struct usbh_hub *hub_next;
|
||||
void *priv;
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
|
@ -760,8 +760,9 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
|
|||
{
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub_next;
|
||||
const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
|
@ -770,11 +771,12 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
|
|||
USB_LOG_RAW("\t");
|
||||
}
|
||||
|
||||
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
|
||||
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
|
||||
hport->port,
|
||||
hport->dev_addr,
|
||||
itf,
|
||||
hport->config.intf[itf].class_driver->driver_name);
|
||||
hport->config.intf[itf].class_driver->driver_name,
|
||||
speed_table[hport->speed]);
|
||||
|
||||
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
|
||||
hub_next = hport->config.intf[itf].priv;
|
||||
|
@ -794,7 +796,7 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *
|
|||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub_next;
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
|
||||
|
@ -888,7 +890,7 @@ int lsusb(int argc, char **argv)
|
|||
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
|
||||
bus->busid,
|
||||
hub->index,
|
||||
hub->hub_desc.bNbrPorts);
|
||||
hub->nports);
|
||||
usbh_list_all_interface_driver(hub);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "usb_osal.h"
|
||||
#include "usbh_hub.h"
|
||||
#include "usb_memcpy.h"
|
||||
#include "usb_version.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -101,6 +102,9 @@ struct usbh_hubport {
|
|||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
uint8_t depth; /* distance from root hub */
|
||||
uint8_t route; /* route string */
|
||||
uint8_t slot_id; /* slot id */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
|
@ -109,6 +113,7 @@ struct usbh_hubport {
|
|||
uint8_t *raw_config_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usbh_hub *parent;
|
||||
struct usbh_hub *self; /* if this hubport is a hub */
|
||||
struct usbh_bus *bus;
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
struct usbh_urb ep0_urb;
|
||||
|
@ -120,7 +125,13 @@ struct usbh_hub {
|
|||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
uint8_t speed;
|
||||
uint8_t nports;
|
||||
uint8_t powerdelay;
|
||||
uint8_t tt_think;
|
||||
bool ismtt;
|
||||
struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
|
||||
struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
struct usbh_bus *bus;
|
||||
|
@ -143,9 +154,9 @@ struct usbh_devaddr_map {
|
|||
};
|
||||
|
||||
struct usbh_hcd {
|
||||
uint32_t reg_base;
|
||||
uintptr_t reg_base;
|
||||
uint8_t hcd_id;
|
||||
uint8_t roothub_intbuf[1];
|
||||
uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
|
||||
struct usbh_hub roothub;
|
||||
};
|
||||
|
||||
|
@ -261,7 +272,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(uint8_t busid, uint32_t reg_base);
|
||||
int usbh_initialize(uint8_t busid, uintptr_t reg_base);
|
||||
int usbh_deinitialize(uint8_t busid);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "event_groups.h"
|
||||
#include "csh.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
#include "chry_ringbuffer.h"
|
||||
|
||||
static chry_ringbuffer_t shell_rb;
|
||||
static uint8_t mempool[1024];
|
||||
|
||||
#ifndef task_repl_PRIORITY
|
||||
#define task_repl_PRIORITY (configMAX_PRIORITIES - 4U)
|
||||
#endif
|
||||
|
||||
#ifndef task_exec_PRIORITY
|
||||
#define task_exec_PRIORITY (configMAX_PRIORITIES - 5U)
|
||||
#endif
|
||||
|
||||
static chry_shell_t csh;
|
||||
static volatile bool login = false;
|
||||
|
||||
static StaticTask_t task_buffer_repl;
|
||||
static StaticTask_t task_buffer_exec;
|
||||
|
||||
static StackType_t task_stack_repl[1024];
|
||||
static StackType_t task_stack_exec[1024];
|
||||
|
||||
static TaskHandle_t task_hdl_repl = NULL;
|
||||
static TaskHandle_t task_hdl_exec = NULL;
|
||||
|
||||
static EventGroupHandle_t event_hdl;
|
||||
static StaticEventGroup_t event_grp;
|
||||
|
||||
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
|
||||
{
|
||||
chry_ringbuffer_write(&shell_rb, data, len);
|
||||
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xEventGroupSetBitsFromISR(event_hdl, 0x10, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void usbd_adb_notify_write_done(void)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xEventGroupSetBitsFromISR(event_hdl, 0x20, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
static uint16_t csh_sput_cb(chry_readline_t *rl, const void *data, uint16_t size)
|
||||
{
|
||||
(void)rl;
|
||||
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (usbd_adb_can_write() && size) {
|
||||
usbd_abd_write(ADB_SHELL_LOALID, data, size);
|
||||
xEventGroupWaitBits(event_hdl, 0x20, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static uint16_t csh_sget_cb(chry_readline_t *rl, void *data, uint16_t size)
|
||||
{
|
||||
(void)rl;
|
||||
|
||||
return chry_ringbuffer_read(&shell_rb, data, size);
|
||||
}
|
||||
|
||||
static void wait_char(void)
|
||||
{
|
||||
EventBits_t event;
|
||||
wait:
|
||||
/* In order to lock the log from being disrupted , wait for REPL task execution to complete */
|
||||
event = xEventGroupWaitBits(event_hdl, (0x10 | 0x01 | 0x04), pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
if ((event & 0x10) == 0) {
|
||||
if (event & 0x01) {
|
||||
chry_readline_erase_line(&csh.rl);
|
||||
xEventGroupSetBits(event_hdl, 0x02);
|
||||
}
|
||||
if (event & 0x04) {
|
||||
chry_readline_edit_refresh(&csh.rl);
|
||||
xEventGroupSetBits(event_hdl, 0x08);
|
||||
}
|
||||
|
||||
goto wait;
|
||||
}
|
||||
}
|
||||
|
||||
static void task_repl(void *param)
|
||||
{
|
||||
(void)param;
|
||||
int ret;
|
||||
volatile uint8_t *pexec = (void *)&csh.exec;
|
||||
|
||||
for (;;) {
|
||||
restart:
|
||||
if (login) {
|
||||
goto repl;
|
||||
} else {
|
||||
}
|
||||
|
||||
ret = csh_login(&csh);
|
||||
if (ret == 0) {
|
||||
login = true;
|
||||
} else if (ret == 1) {
|
||||
/*!< no enough char */
|
||||
wait_char();
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
repl:
|
||||
ret = chry_shell_task_repl(&csh);
|
||||
|
||||
if (ret == -1) {
|
||||
/*!< error */
|
||||
goto restart;
|
||||
} else if (ret == 1) {
|
||||
/*!< no enough char */
|
||||
wait_char();
|
||||
} else {
|
||||
/*!< restart */
|
||||
}
|
||||
|
||||
/*!< check flag */
|
||||
if (*pexec == CSH_STATUS_EXEC_DONE) {
|
||||
*pexec = CSH_STATUS_EXEC_IDLE;
|
||||
chry_readline_auto_refresh(&csh.rl, true);
|
||||
chry_readline_ignore(&csh.rl, false);
|
||||
chry_readline_edit_refresh(&csh.rl);
|
||||
}
|
||||
|
||||
if (login == false) {
|
||||
chry_readline_erase_line(&csh.rl);
|
||||
csh.rl.noblock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void task_exec(void *param)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
/*!< execute shell command */
|
||||
chry_shell_task_exec(&csh);
|
||||
|
||||
/*!< notify REPL task execute done */
|
||||
xEventGroupSetBits(event_hdl, 0x10);
|
||||
|
||||
/*!< wait for REPL task delete */
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
int chry_shell_port_create_context(chry_shell_t *csh, int argc, const char **argv)
|
||||
{
|
||||
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
|
||||
(void)csh;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if (*p_task_hdl_exec != NULL) {
|
||||
vTaskDelete(*p_task_hdl_exec);
|
||||
}
|
||||
|
||||
*p_task_hdl_exec = xTaskCreateStatic(task_exec, "task_exec", 1024U, NULL, task_exec_PRIORITY, task_stack_exec, &task_buffer_exec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chry_shell_port_default_handler(chry_shell_t *csh, int sig)
|
||||
{
|
||||
volatile uint8_t *pexec = (void *)&csh->exec;
|
||||
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
|
||||
|
||||
switch (sig) {
|
||||
case CSH_SIGINT:
|
||||
case CSH_SIGQUIT:
|
||||
case CSH_SIGKILL:
|
||||
case CSH_SIGTERM:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/*!< force delete task */
|
||||
if (*p_task_hdl_exec != NULL) {
|
||||
vTaskDelete(task_hdl_exec);
|
||||
*p_task_hdl_exec = NULL;
|
||||
}
|
||||
|
||||
switch (sig) {
|
||||
case CSH_SIGINT:
|
||||
csh->rl.sput(&csh->rl, "^SIGINT" CONFIG_CSH_NEWLINE, sizeof("^SIGINT" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGQUIT:
|
||||
csh->rl.sput(&csh->rl, "^SIGQUIT" CONFIG_CSH_NEWLINE, sizeof("^SIGQUIT" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGKILL:
|
||||
csh->rl.sput(&csh->rl, "^SIGKILL" CONFIG_CSH_NEWLINE, sizeof("^SIGKILL" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
case CSH_SIGTERM:
|
||||
csh->rl.sput(&csh->rl, "^SIGTERM" CONFIG_CSH_NEWLINE, sizeof("^SIGTERM" CONFIG_CSH_NEWLINE) - 1);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
*pexec = CSH_STATUS_EXEC_IDLE;
|
||||
chry_readline_auto_refresh(&csh->rl, true);
|
||||
chry_readline_ignore(&csh->rl, false);
|
||||
chry_readline_edit_refresh(&csh->rl);
|
||||
}
|
||||
|
||||
int shell_init(bool need_login)
|
||||
{
|
||||
chry_shell_init_t csh_init;
|
||||
|
||||
if (chry_ringbuffer_init(&shell_rb, mempool, sizeof(mempool))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (need_login) {
|
||||
login = false;
|
||||
} else {
|
||||
login = true;
|
||||
}
|
||||
|
||||
/*!< I/O callback */
|
||||
csh_init.sput = csh_sput_cb;
|
||||
csh_init.sget = csh_sget_cb;
|
||||
|
||||
#if defined(CONFIG_CSH_SYMTAB) && CONFIG_CSH_SYMTAB
|
||||
extern const int __fsymtab_start;
|
||||
extern const int __fsymtab_end;
|
||||
extern const int __vsymtab_start;
|
||||
extern const int __vsymtab_end;
|
||||
|
||||
/*!< get table from ld symbol */
|
||||
csh_init.command_table_beg = &__fsymtab_start;
|
||||
csh_init.command_table_end = &__fsymtab_end;
|
||||
csh_init.variable_table_beg = &__vsymtab_start;
|
||||
csh_init.variable_table_end = &__vsymtab_end;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_PROMPTEDIT) && CONFIG_CSH_PROMPTEDIT
|
||||
static char csh_prompt_buffer[128];
|
||||
|
||||
/*!< set prompt buffer */
|
||||
csh_init.prompt_buffer = csh_prompt_buffer;
|
||||
csh_init.prompt_buffer_size = sizeof(csh_prompt_buffer);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_HISTORY) && CONFIG_CSH_HISTORY
|
||||
static char csh_history_buffer[128];
|
||||
|
||||
/*!< set history buffer */
|
||||
csh_init.history_buffer = csh_history_buffer;
|
||||
csh_init.history_buffer_size = sizeof(csh_history_buffer);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CSH_LNBUFF_STATIC) && CONFIG_CSH_LNBUFF_STATIC
|
||||
static char csh_line_buffer[128];
|
||||
|
||||
/*!< set linebuffer */
|
||||
csh_init.line_buffer = csh_line_buffer;
|
||||
csh_init.line_buffer_size = sizeof(csh_line_buffer);
|
||||
#endif
|
||||
|
||||
csh_init.uid = 0;
|
||||
csh_init.user[0] = "cherry";
|
||||
|
||||
/*!< The port hash function is required,
|
||||
and the strcmp attribute is used weakly by default,
|
||||
int chry_shell_port_hash_strcmp(const char *hash, const char *str); */
|
||||
csh_init.hash[0] = "12345678"; /*!< If there is no password, set to NULL */
|
||||
csh_init.host = "cherryadb";
|
||||
csh_init.user_data = NULL;
|
||||
|
||||
int ret = chry_shell_init(&csh, &csh_init);
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
task_hdl_exec = NULL;
|
||||
event_hdl = xEventGroupCreateStatic(&event_grp);
|
||||
task_hdl_repl = xTaskCreateStatic(task_repl, "task_repl", 1024U, NULL, task_repl_PRIORITY, task_stack_repl, &task_buffer_repl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shell_lock(void)
|
||||
{
|
||||
xEventGroupSetBits(event_hdl, 0x01);
|
||||
xEventGroupWaitBits(event_hdl, 0x02, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void shell_unlock(void)
|
||||
{
|
||||
xEventGroupSetBits(event_hdl, 0x04);
|
||||
xEventGroupWaitBits(event_hdl, 0x08, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static int csh_exit(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
usbd_adb_close(ADB_SHELL_LOALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
CSH_SCMD_EXPORT_ALIAS(csh_exit, exit, );
|
||||
|
||||
#define __ENV_PATH "/sbin:/bin"
|
||||
const char ENV_PATH[] = __ENV_PATH;
|
||||
CSH_RVAR_EXPORT(ENV_PATH, PATH, sizeof(__ENV_PATH));
|
||||
|
||||
#define __ENV_ZERO ""
|
||||
const char ENV_ZERO[] = __ENV_ZERO;
|
||||
CSH_RVAR_EXPORT(ENV_ZERO, ZERO, sizeof(__ENV_ZERO));
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define WINUSB_MAX_MPS 512
|
||||
#else
|
||||
#define WINUSB_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
#define ADB_INTF_NUM 0
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// MS OS string descriptor
|
||||
///////////////////////////////////////
|
||||
0x12, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
/* MSFT100 */
|
||||
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
|
||||
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
|
||||
WCID_VENDOR_CODE, /* bVendorCode */
|
||||
0x00, /* bReserved */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID descriptor
|
||||
///////////////////////////////////////
|
||||
0x28, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x04, 0x00, /* wIndex */
|
||||
0x01, /* bCount */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// WCID function descriptor
|
||||
///////////////////////////////////////
|
||||
ADB_INTF_NUM, /* bFirstInterfaceNumber */
|
||||
0x01, /* bReserved */
|
||||
/* Compatible ID */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8: WINUSB */
|
||||
/* */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||
///////////////////////////////////////
|
||||
/// WCID property descriptor
|
||||
///////////////////////////////////////
|
||||
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||
0x00, 0x01, /* bcdVersion */
|
||||
0x05, 0x00, /* wIndex */
|
||||
0x01, 0x00, /* wCount */
|
||||
|
||||
///////////////////////////////////////
|
||||
/// registry propter descriptor
|
||||
///////////////////////////////////////
|
||||
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||
0x28, 0x00, /* wPropertyNameLength */
|
||||
/* DeviceInterfaceGUID */
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
|
||||
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
|
||||
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
|
||||
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
|
||||
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
|
||||
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
|
||||
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
|
||||
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||
};
|
||||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
};
|
||||
|
||||
/*!< global descriptor */
|
||||
static const uint8_t adb_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
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 */
|
||||
'A', 0x00, /* wcChar6 */
|
||||
'D', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x1C, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'A', 0x00, /* wcChar6 */
|
||||
'D', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
'2', 0x00, /* wcChar9 */
|
||||
'0', 0x00, /* wcChar10 */
|
||||
'2', 0x00, /* wcChar11 */
|
||||
'4', 0x00, /* wcChar12 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x02,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
extern int shell_init(bool need_login);
|
||||
void cherryadb_init(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
/* default password is : 12345678 */
|
||||
/* shell_init() must be called in-task */
|
||||
if (0 != shell_init(false)) {
|
||||
/* shell failed to be initialized */
|
||||
printf("Failed to initialize shell\r\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
usbd_desc_register(busid, adb_descriptor);
|
||||
usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
|
@ -212,7 +212,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v1_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
|
||||
|
|
|
@ -238,7 +238,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v1_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v1_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
|
||||
|
|
|
@ -229,7 +229,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||
|
|
|
@ -346,7 +346,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_IN_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
|
||||
|
|
|
@ -247,7 +247,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void audio_v2_init(uint8_t busid, uint32_t reg_base)
|
||||
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, audio_v2_descriptor);
|
||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||
|
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2024, Egahp
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "bootuf2.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
char file_INFO[] = {
|
||||
"CherryUSB UF2 BOOT\r\n"
|
||||
"Model: " CONFIG_PRODUCT "\r\n"
|
||||
"Board-ID: " CONFIG_BOARD "\r\n"
|
||||
};
|
||||
|
||||
const char file_IDEX[] = {
|
||||
"<!doctype html>\n"
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<script>\n"
|
||||
"location.replace(\"" CONFIG_BOOTUF2_INDEX_URL "\");\n"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>\n"
|
||||
};
|
||||
|
||||
const char file_JOIN[] = {
|
||||
"<!doctype html>\n"
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<script>\n"
|
||||
"location.replace(\"" CONFIG_BOOTUF2_JOIN_URL "\");\n"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>\n"
|
||||
};
|
||||
|
||||
const char file_ID__[12] = BOOTUF2_FAMILYID_ARRAY;
|
||||
|
||||
static struct bootuf2_FILE files[] = {
|
||||
[0] = { .Name = file_ID__, .Content = NULL, .FileSize = 0 },
|
||||
[1] = { .Name = "INFO_UF2TXT", .Content = file_INFO, .FileSize = sizeof(file_INFO) - 1 },
|
||||
[2] = { .Name = "INDEX HTM", .Content = file_IDEX, .FileSize = sizeof(file_IDEX) - 1 },
|
||||
[3] = { .Name = "JOIN HTM", .Content = file_JOIN, .FileSize = sizeof(file_JOIN) - 1 },
|
||||
};
|
||||
|
||||
struct bootuf2_data {
|
||||
const struct bootuf2_DBR *const DBR;
|
||||
struct bootuf2_STATE *const STATE;
|
||||
uint8_t *const fbuff;
|
||||
uint8_t *const erase;
|
||||
size_t page_count;
|
||||
uint8_t *const cache;
|
||||
const size_t cache_size;
|
||||
uint32_t cached_address;
|
||||
size_t cached_bytes;
|
||||
};
|
||||
|
||||
/*!< define DBRs */
|
||||
static const struct bootuf2_DBR bootuf2_DBR = {
|
||||
.JMPInstruction = { 0xEB, 0x3C, 0x90 },
|
||||
.OEM = "UF2 UF2 ",
|
||||
.BPB = {
|
||||
.BytesPerSector = CONFIG_BOOTUF2_SECTOR_SIZE,
|
||||
.SectorsPerCluster = CONFIG_BOOTUF2_SECTOR_PER_CLUSTER,
|
||||
.ReservedSectors = CONFIG_BOOTUF2_SECTOR_RESERVED,
|
||||
.NumberOfFAT = CONFIG_BOOTUF2_NUM_OF_FAT,
|
||||
.RootEntries = CONFIG_BOOTUF2_ROOT_ENTRIES,
|
||||
.Sectors = (BOOTUF2_SECTORS(0) > 0xFFFF) ? 0 : BOOTUF2_SECTORS(0),
|
||||
.MediaDescriptor = 0xF8,
|
||||
.SectorsPerFAT = BOOTUF2_SECTORS_PER_FAT(0),
|
||||
.SectorsPerTrack = 1,
|
||||
.Heads = 1,
|
||||
.HiddenSectors = 0,
|
||||
.SectorsOver32MB = (BOOTUF2_SECTORS(0) > 0xFFFF) ? BOOTUF2_SECTORS(0) : 0,
|
||||
.BIOSDrive = 0x80,
|
||||
.Reserved = 0,
|
||||
.ExtendBootSignature = 0x29,
|
||||
.VolumeSerialNumber = 0x00420042,
|
||||
.VolumeLabel = "CHERRYUF2",
|
||||
.FileSystem = "FAT16 ",
|
||||
},
|
||||
};
|
||||
|
||||
/*!< define mask */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_mask[BOOTUF2_BLOCKSMAX / 8 + 1] = { 0 };
|
||||
|
||||
/*!< define state */
|
||||
static struct bootuf2_STATE bootuf2_STATE = {
|
||||
.NumberOfBlock = 0,
|
||||
.NumberOfWritten = 0,
|
||||
.Mask = bootuf2_mask,
|
||||
.Enable = 1,
|
||||
};
|
||||
|
||||
/*!< define flash cache */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_cache[CONFIG_BOOTUF2_CACHE_SIZE];
|
||||
|
||||
/*!< define flash buff */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_fbuff[256];
|
||||
|
||||
/*!< define erase flag buff */
|
||||
static uint8_t __attribute__((aligned(4))) bootuf2_disk_erase[BOOTUF2_DIVCEIL(CONFIG_BOOTUF2_PAGE_COUNTMAX, 8)];
|
||||
|
||||
/*!< define disk */
|
||||
static struct bootuf2_data bootuf2_disk = {
|
||||
.DBR = &bootuf2_DBR,
|
||||
.STATE = &bootuf2_STATE,
|
||||
.fbuff = bootuf2_disk_fbuff,
|
||||
.erase = bootuf2_disk_erase,
|
||||
.cache = bootuf2_disk_cache,
|
||||
.cache_size = sizeof(bootuf2_disk_cache),
|
||||
};
|
||||
|
||||
static void fname_copy(char *dst, char const *src, uint16_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (*src)
|
||||
*dst++ = *src++;
|
||||
else
|
||||
*dst++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
static void fcalculate_cluster(struct bootuf2_data *ctx)
|
||||
{
|
||||
/*!< init files cluster */
|
||||
uint16_t cluster_beg = 2;
|
||||
for (int i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
files[i].ClusterBeg = cluster_beg;
|
||||
files[i].ClusterEnd = -1 + cluster_beg +
|
||||
BOOTUF2_DIVCEIL(files[i].FileSize,
|
||||
ctx->DBR->BPB.BytesPerSector *
|
||||
ctx->DBR->BPB.SectorsPerCluster);
|
||||
cluster_beg = files[i].ClusterEnd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int ffind_by_cluster(uint32_t cluster)
|
||||
{
|
||||
if (cluster >= 0xFFF0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
if ((files[i].ClusterBeg <= cluster) &&
|
||||
(cluster <= files[i].ClusterEnd)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool bootuf2block_check_writable(struct bootuf2_STATE *STATE,
|
||||
struct bootuf2_BLOCK *uf2, uint32_t block_max)
|
||||
{
|
||||
if (uf2->NumberOfBlock) {
|
||||
if (uf2->BlockIndex < block_max) {
|
||||
uint8_t mask = 1 << (uf2->BlockIndex % 8);
|
||||
uint32_t pos = uf2->BlockIndex / 8;
|
||||
|
||||
if ((STATE->Mask[pos] & mask) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bootuf2block_state_update(struct bootuf2_STATE *STATE,
|
||||
struct bootuf2_BLOCK *uf2, uint32_t block_max)
|
||||
{
|
||||
if (uf2->NumberOfBlock) {
|
||||
if (STATE->NumberOfBlock != uf2->NumberOfBlock) {
|
||||
if ((uf2->NumberOfBlock >= BOOTUF2_BLOCKSMAX) ||
|
||||
STATE->NumberOfBlock) {
|
||||
/*!< uf2 block only can be update once */
|
||||
/*!< this will cause never auto reboot */
|
||||
STATE->NumberOfBlock = 0xffffffff;
|
||||
} else {
|
||||
STATE->NumberOfBlock = uf2->NumberOfBlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (uf2->BlockIndex < block_max) {
|
||||
uint8_t mask = 1 << (uf2->BlockIndex % 8);
|
||||
uint32_t pos = uf2->BlockIndex / 8;
|
||||
|
||||
if ((STATE->Mask[pos] & mask) == 0) {
|
||||
STATE->Mask[pos] |= mask;
|
||||
STATE->NumberOfWritten++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_DBG("UF2 block total %d written %d index %d\r\n",
|
||||
uf2->NumberOfBlock, STATE->NumberOfWritten, uf2->BlockIndex);
|
||||
}
|
||||
|
||||
static bool bootuf2block_state_check(struct bootuf2_STATE *STATE)
|
||||
{
|
||||
return (STATE->NumberOfWritten >= STATE->NumberOfBlock) &&
|
||||
STATE->NumberOfBlock;
|
||||
}
|
||||
|
||||
static int bootuf2_flash_flush(struct bootuf2_data *ctx)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (ctx->cached_bytes == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bootuf2_flash_write(ctx->cached_address, ctx->cache, ctx->cached_bytes);
|
||||
|
||||
if (err) {
|
||||
USB_LOG_ERR("UF2 slot flash write error %d at offset %08lx len %d\r\n",
|
||||
err, ctx->cached_address, ctx->cached_bytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->cached_bytes = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bootuf2_flash_write_internal(struct bootuf2_data *ctx, struct bootuf2_BLOCK *uf2)
|
||||
{
|
||||
/*!< 1.cache not empty and address not continue */
|
||||
/*!< 2.cache full */
|
||||
if ((ctx->cached_bytes && ((ctx->cached_address + ctx->cached_bytes) != uf2->TargetAddress)) ||
|
||||
(ctx->cached_bytes == ctx->cache_size)) {
|
||||
int err = bootuf2_flash_flush(ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!< write len always is 256, cache_size always is a multiple of 256 */
|
||||
memcpy(ctx->cache + ctx->cached_bytes, uf2->Data, uf2->PayloadSize);
|
||||
|
||||
ctx->cached_address = uf2->TargetAddress - ctx->cached_bytes;
|
||||
ctx->cached_bytes += uf2->PayloadSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bootuf2_init(void)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
fcalculate_cluster(ctx);
|
||||
|
||||
ctx->cached_bytes = 0;
|
||||
ctx->cached_address = 0;
|
||||
}
|
||||
|
||||
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
while (sector_count) {
|
||||
memset(buff, 0, ctx->DBR->BPB.BytesPerSector);
|
||||
|
||||
uint32_t sector_relative = start_sector;
|
||||
|
||||
/*!< DBR sector */
|
||||
if (start_sector == BOOTUF2_SECTOR_DBR_END) {
|
||||
memcpy(buff, ctx->DBR, sizeof(struct bootuf2_DBR));
|
||||
buff[510] = 0x55;
|
||||
buff[511] = 0xaa;
|
||||
}
|
||||
/*!< FAT sector */
|
||||
else if (start_sector < BOOTUF2_SECTOR_FAT_END(ctx->DBR)) {
|
||||
uint16_t *buff16 = (uint16_t *)buff;
|
||||
|
||||
sector_relative -= BOOTUF2_SECTOR_RSVD_END(ctx->DBR);
|
||||
|
||||
/*!< Perform the same operation on all FAT tables */
|
||||
while (sector_relative >= ctx->DBR->BPB.SectorsPerFAT) {
|
||||
sector_relative -= ctx->DBR->BPB.SectorsPerFAT;
|
||||
}
|
||||
|
||||
uint16_t cluster_unused = files[ARRAY_SIZE(files) - 1].ClusterEnd + 1;
|
||||
uint16_t cluster_absolute_first = sector_relative *
|
||||
BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
|
||||
|
||||
/*!< cluster used link to chain, or unsed */
|
||||
for (uint16_t i = 0, cluster_absolute = cluster_absolute_first;
|
||||
i < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
|
||||
i++, cluster_absolute++) {
|
||||
if (cluster_absolute >= cluster_unused)
|
||||
buff16[i] = 0;
|
||||
else
|
||||
buff16[i] = cluster_absolute + 1;
|
||||
}
|
||||
|
||||
/*!< cluster 0 and 1 */
|
||||
if (sector_relative == 0) {
|
||||
buff[0] = ctx->DBR->BPB.MediaDescriptor;
|
||||
buff[1] = 0xff;
|
||||
buff16[1] = 0xffff;
|
||||
}
|
||||
|
||||
/*!< cluster end of file */
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
uint16_t cluster_file_last = files[i].ClusterEnd;
|
||||
|
||||
if (cluster_file_last >= cluster_absolute_first) {
|
||||
uint16_t idx = cluster_file_last - cluster_absolute_first;
|
||||
if (idx < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR)) {
|
||||
buff16[idx] = 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!< root entries */
|
||||
else if (start_sector < BOOTUF2_SECTOR_ROOT_END(ctx->DBR)) {
|
||||
sector_relative -= BOOTUF2_SECTOR_FAT_END(ctx->DBR);
|
||||
|
||||
struct bootuf2_ENTRY *ent = (void *)buff;
|
||||
int remain_entries = BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR);
|
||||
|
||||
uint32_t file_index_first;
|
||||
|
||||
/*!< volume label entry */
|
||||
if (sector_relative == 0) {
|
||||
fname_copy(ent->Name, (char const *)ctx->DBR->BPB.VolumeLabel, 11);
|
||||
ent->Attribute = 0x28;
|
||||
ent++;
|
||||
remain_entries--;
|
||||
file_index_first = 0;
|
||||
} else {
|
||||
/*!< -1 to account for volume label in first sector */
|
||||
file_index_first = sector_relative * BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR) - 1;
|
||||
}
|
||||
|
||||
for (uint32_t idx = file_index_first;
|
||||
(remain_entries > 0) && (idx < ARRAY_SIZE(files));
|
||||
idx++, ent++) {
|
||||
const uint32_t cluster_beg = files[idx].ClusterBeg;
|
||||
|
||||
const struct bootuf2_FILE *f = &files[idx];
|
||||
|
||||
if ((0 == f->FileSize) &&
|
||||
(0 != idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fname_copy(ent->Name, f->Name, 11);
|
||||
ent->Attribute = 0x05;
|
||||
ent->CreateTimeTeenth = BOOTUF2_SECONDS_INT % 2 * 100;
|
||||
ent->CreateTime = BOOTUF2_DOS_TIME;
|
||||
ent->CreateDate = BOOTUF2_DOS_DATE;
|
||||
ent->LastAccessDate = BOOTUF2_DOS_DATE;
|
||||
ent->FirstClustH16 = cluster_beg >> 16;
|
||||
ent->UpdateTime = BOOTUF2_DOS_TIME;
|
||||
ent->UpdateDate = BOOTUF2_DOS_DATE;
|
||||
ent->FirstClustL16 = cluster_beg & 0xffff;
|
||||
ent->FileSize = f->FileSize;
|
||||
}
|
||||
}
|
||||
/*!< data */
|
||||
else if (start_sector < BOOTUF2_SECTOR_DATA_END(ctx->DBR)) {
|
||||
sector_relative -= BOOTUF2_SECTOR_ROOT_END(ctx->DBR);
|
||||
|
||||
int fid = ffind_by_cluster(2 + sector_relative / ctx->DBR->BPB.SectorsPerCluster);
|
||||
|
||||
if (fid >= 0) {
|
||||
const struct bootuf2_FILE *f = &files[fid];
|
||||
|
||||
uint32_t sector_relative_file =
|
||||
sector_relative -
|
||||
(files[fid].ClusterBeg - 2) * ctx->DBR->BPB.SectorsPerCluster;
|
||||
|
||||
size_t fcontent_offset = sector_relative_file * ctx->DBR->BPB.BytesPerSector;
|
||||
size_t fcontent_length = f->FileSize;
|
||||
|
||||
if (fcontent_length > fcontent_offset) {
|
||||
const void *src = (void *)((uint8_t *)(f->Content) + fcontent_offset);
|
||||
size_t copy_size = fcontent_length - fcontent_offset;
|
||||
|
||||
if (copy_size > ctx->DBR->BPB.BytesPerSector) {
|
||||
copy_size = ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
memcpy(buff, src, copy_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!< unknown sector, ignore */
|
||||
|
||||
start_sector++;
|
||||
sector_count--;
|
||||
buff += ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count)
|
||||
{
|
||||
struct bootuf2_data *ctx;
|
||||
|
||||
ctx = &bootuf2_disk;
|
||||
|
||||
while (sector_count) {
|
||||
struct bootuf2_BLOCK *uf2 = (void *)buff;
|
||||
|
||||
if (!((uf2->MagicStart0 == BOOTUF2_MAGIC_START0) &&
|
||||
(uf2->MagicStart1 == BOOTUF2_MAGIC_START1) &&
|
||||
(uf2->MagicEnd == BOOTUF2_MAGIC_END) &&
|
||||
(uf2->Flags & BOOTUF2_FLAG_FAMILID_PRESENT) &&
|
||||
!(uf2->Flags & BOOTUF2_FLAG_NOT_MAIN_FLASH))) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uf2->FamilyID == CONFIG_BOOTUF2_FAMILYID) {
|
||||
if (bootuf2block_check_writable(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX)) {
|
||||
bootuf2_flash_write_internal(ctx, uf2);
|
||||
bootuf2block_state_update(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX);
|
||||
} else {
|
||||
USB_LOG_DBG("UF2 block %d already written\r\n",
|
||||
uf2->BlockIndex);
|
||||
}
|
||||
} else {
|
||||
USB_LOG_DBG("UF2 block illegal id %08x\r\n", uf2->FamilyID);
|
||||
}
|
||||
|
||||
next:
|
||||
start_sector++;
|
||||
sector_count--;
|
||||
buff += ctx->DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t bootuf2_get_sector_size(void)
|
||||
{
|
||||
return bootuf2_disk.DBR->BPB.BytesPerSector;
|
||||
}
|
||||
|
||||
uint32_t bootuf2_get_sector_count(void)
|
||||
{
|
||||
return bootuf2_disk.DBR->BPB.SectorsOver32MB + bootuf2_disk.DBR->BPB.Sectors;
|
||||
}
|
||||
|
||||
bool bootuf2_is_write_done(void)
|
||||
{
|
||||
if (bootuf2block_state_check(bootuf2_disk.STATE)) {
|
||||
bootuf2_flash_flush(&bootuf2_disk);
|
||||
USB_LOG_DBG("UF2 update ok\r\n");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2024, Egahp
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BOOTUF2_H
|
||||
#define BOOTUF2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <bootuf2_config.h>
|
||||
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) \
|
||||
((int)((sizeof(array) / sizeof((array)[0]))))
|
||||
#endif
|
||||
|
||||
struct bootuf2_BLOCK
|
||||
{
|
||||
// 32 byte header
|
||||
uint32_t MagicStart0;
|
||||
uint32_t MagicStart1;
|
||||
uint32_t Flags;
|
||||
uint32_t TargetAddress;
|
||||
uint32_t PayloadSize;
|
||||
uint32_t BlockIndex;
|
||||
uint32_t NumberOfBlock;
|
||||
uint32_t FamilyID; // or file_size
|
||||
uint8_t Data[476];
|
||||
uint32_t MagicEnd;
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_BLOCK) == 512, "bootuf2_BLOCK not sector sized");
|
||||
|
||||
struct bootuf2_STATE
|
||||
{
|
||||
uint32_t NumberOfBlock;
|
||||
uint32_t NumberOfWritten;
|
||||
uint8_t *const Mask;
|
||||
uint8_t Enable;
|
||||
};
|
||||
|
||||
struct bootuf2_DBR
|
||||
{
|
||||
/*!< offset 0 */
|
||||
uint8_t JMPInstruction[3];
|
||||
/*!< offset 3 */
|
||||
uint8_t OEM[8];
|
||||
/*!< offset 11 */
|
||||
struct
|
||||
{
|
||||
uint16_t BytesPerSector;
|
||||
uint8_t SectorsPerCluster;
|
||||
uint16_t ReservedSectors;
|
||||
uint8_t NumberOfFAT;
|
||||
uint16_t RootEntries;
|
||||
uint16_t Sectors;
|
||||
uint8_t MediaDescriptor;
|
||||
uint16_t SectorsPerFAT;
|
||||
uint16_t SectorsPerTrack;
|
||||
uint16_t Heads;
|
||||
uint32_t HiddenSectors;
|
||||
uint32_t SectorsOver32MB;
|
||||
uint8_t BIOSDrive;
|
||||
uint8_t Reserved;
|
||||
uint8_t ExtendBootSignature;
|
||||
uint32_t VolumeSerialNumber;
|
||||
uint8_t VolumeLabel[11];
|
||||
uint8_t FileSystem[8];
|
||||
} __PACKED BPB;
|
||||
/*!< offset 62 */
|
||||
/*!< BootLoader */
|
||||
/*!< offset 511 */
|
||||
/*!< 0x55 0xAA */
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_DBR) == 62, "bootuf2_DBR size must be 62 byte");
|
||||
|
||||
struct bootuf2_ENTRY
|
||||
{
|
||||
char Name[11];
|
||||
uint8_t Attribute;
|
||||
uint8_t NTReserved;
|
||||
uint8_t CreateTimeTeenth;
|
||||
uint16_t CreateTime;
|
||||
uint16_t CreateDate;
|
||||
uint16_t LastAccessDate;
|
||||
uint16_t FirstClustH16;
|
||||
uint16_t UpdateTime;
|
||||
uint16_t UpdateDate;
|
||||
uint16_t FirstClustL16;
|
||||
uint32_t FileSize;
|
||||
} __PACKED;
|
||||
//BUILD_ASSERT(sizeof(struct bootuf2_ENTRY) == 32, "bootuf2_ENTRY size must be 32 byte");
|
||||
|
||||
struct bootuf2_FILE
|
||||
{
|
||||
const char *const Name;
|
||||
const void *const Content;
|
||||
uint32_t FileSize;
|
||||
uint16_t ClusterBeg;
|
||||
uint16_t ClusterEnd;
|
||||
};
|
||||
|
||||
#define BOOTUF2_DIVCEIL(_v, _d) (((_v) / (_d)) + ((_v) % (_d) ? 1 : 0))
|
||||
|
||||
#define BOOTUF2_MAGIC_START0 0x0A324655u
|
||||
#define BOOTUF2_MAGIC_START1 0x9E5D5157u
|
||||
#define BOOTUF2_MAGIC_SERIAL 0x251B18BDu
|
||||
#define BOOTUF2_MAGIC_END 0x0AB16F30u
|
||||
|
||||
#define BOOTUF2_FLAG_NOT_MAIN_FLASH 0x00000001u
|
||||
#define BOOTUF2_FLAG_FILE_CONTAINER 0x00001000u
|
||||
#define BOOTUF2_FLAG_FAMILID_PRESENT 0x00002000u
|
||||
#define BOOTUF2_FLAG_MD5_PRESENT 0x00004000u
|
||||
|
||||
#define BOOTUF2_CMD_READ 0
|
||||
#define BOOTUF2_CMD_SYNC 1
|
||||
|
||||
#define BOOTUF2_BLOCKSMAX (((CONFIG_BOOTUF2_FLASHMAX) / 256) + (((CONFIG_BOOTUF2_FLASHMAX) % 256) ? 1 : 0))
|
||||
|
||||
#define BOOTUF2_FAMILYID_POSNUM(n) (((CONFIG_BOOTUF2_FAMILYID) / (0x10000000 >> ((n) * 4))) % 0x10)
|
||||
#define BOOTUF2_FAMILYID_ARRAY \
|
||||
{ \
|
||||
((BOOTUF2_FAMILYID_POSNUM(0) >= 10) ? BOOTUF2_FAMILYID_POSNUM(0) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(0) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(1) >= 10) ? BOOTUF2_FAMILYID_POSNUM(1) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(1) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(2) >= 10) ? BOOTUF2_FAMILYID_POSNUM(2) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(2) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(3) >= 10) ? BOOTUF2_FAMILYID_POSNUM(3) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(3) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(4) >= 10) ? BOOTUF2_FAMILYID_POSNUM(4) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(4) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(5) >= 10) ? BOOTUF2_FAMILYID_POSNUM(5) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(5) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(6) >= 10) ? BOOTUF2_FAMILYID_POSNUM(6) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(6) + '0'), \
|
||||
((BOOTUF2_FAMILYID_POSNUM(7) >= 10) ? BOOTUF2_FAMILYID_POSNUM(7) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(7) + '0'), \
|
||||
('I'), \
|
||||
('D'), \
|
||||
(' '), \
|
||||
('\0'), \
|
||||
};
|
||||
|
||||
#define BOOTUF2_FAT16_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / 2)
|
||||
#define BOOTUF2_ENTRY_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY))
|
||||
#define BOOTUF2_CLUSTERSMAX (0xFFF0 - 2)
|
||||
#define BOOTUF2_SECTOR_DBR_END (0)
|
||||
#define BOOTUF2_SECTOR_RSVD_END(pDBR) BOOTUF2_SECTOR_DBR_END + (pDBR->BPB.ReservedSectors)
|
||||
#define BOOTUF2_SECTOR_FAT_END(pDBR) BOOTUF2_SECTOR_RSVD_END(pDBR) + (pDBR->BPB.SectorsPerFAT * pDBR->BPB.NumberOfFAT)
|
||||
#define BOOTUF2_SECTOR_ROOT_END(pDBR) BOOTUF2_SECTOR_FAT_END(pDBR) + (pDBR->BPB.RootEntries / (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY)))
|
||||
#define BOOTUF2_SECTOR_DATA_END(pDBR) (pDBR->BPB.Sectors + pDBR->BPB.SectorsOver32MB)
|
||||
|
||||
#define BOOTUF2_SECTORS_PER_FAT(n) \
|
||||
BOOTUF2_DIVCEIL(BOOTUF2_CLUSTERSMAX, (CONFIG_BOOTUF2_SECTOR_SIZE / 2))
|
||||
#define BOOTUF2_SECTORS_FOR_ENTRIES(n) \
|
||||
(CONFIG_BOOTUF2_ROOT_ENTRIES / (CONFIG_BOOTUF2_SECTOR_SIZE / sizeof(struct bootuf2_ENTRY)))
|
||||
#define BOOTUF2_SECTORS(n) \
|
||||
(CONFIG_BOOTUF2_SECTOR_RESERVED + \
|
||||
CONFIG_BOOTUF2_NUM_OF_FAT * BOOTUF2_SECTORS_PER_FAT(n) + \
|
||||
BOOTUF2_SECTORS_FOR_ENTRIES(n) + \
|
||||
BOOTUF2_CLUSTERSMAX * CONFIG_BOOTUF2_SECTOR_PER_CLUSTER)
|
||||
|
||||
#define BOOTUF2_YEAR_INT ( \
|
||||
(__DATE__[7u] - '0') * 1000u + \
|
||||
(__DATE__[8u] - '0') * 100u + \
|
||||
(__DATE__[9u] - '0') * 10u + \
|
||||
(__DATE__[10u] - '0') * 1u)
|
||||
|
||||
#define BOOTUF2_MONTH_INT ( \
|
||||
(__DATE__[2u] == 'n' && __DATE__[1u] == 'a') ? 1u /*Jan*/ \
|
||||
: (__DATE__[2u] == 'b') ? 2u /*Feb*/ \
|
||||
: (__DATE__[2u] == 'r' && __DATE__[1u] == 'a') ? 3u /*Mar*/ \
|
||||
: (__DATE__[2u] == 'r') ? 4u /*Apr*/ \
|
||||
: (__DATE__[2u] == 'y') ? 5u /*May*/ \
|
||||
: (__DATE__[2u] == 'n') ? 6u /*Jun*/ \
|
||||
: (__DATE__[2u] == 'l') ? 7u /*Jul*/ \
|
||||
: (__DATE__[2u] == 'g') ? 8u /*Aug*/ \
|
||||
: (__DATE__[2u] == 'p') ? 9u /*Sep*/ \
|
||||
: (__DATE__[2u] == 't') ? 10u /*Oct*/ \
|
||||
: (__DATE__[2u] == 'v') ? 11u /*Nov*/ \
|
||||
: 12u /*Dec*/)
|
||||
|
||||
#define BOOTUF2_DAY_INT ( \
|
||||
(__DATE__[4u] == ' ' ? 0 : __DATE__[4u] - '0') * 10u + \
|
||||
(__DATE__[5u] - '0'))
|
||||
|
||||
#define BOOTUF2_HOUR_INT ( \
|
||||
(__TIME__[0u] == '?' ? 0 : __TIME__[0u] - '0') * 10u + (__TIME__[1u] == '?' ? 0 : __TIME__[1u] - '0'))
|
||||
|
||||
#define BOOTUF2_MINUTE_INT ( \
|
||||
(__TIME__[3u] == '?' ? 0 : __TIME__[3u] - '0') * 10u + (__TIME__[4u] == '?' ? 0 : __TIME__[4u] - '0'))
|
||||
|
||||
#define BOOTUF2_SECONDS_INT ( \
|
||||
(__TIME__[6u] == '?' ? 0 : __TIME__[6u] - '0') * 10u + (__TIME__[7u] == '?' ? 0 : __TIME__[7u] - '0'))
|
||||
|
||||
#define BOOTUF2_DOS_DATE ( \
|
||||
((BOOTUF2_YEAR_INT - 1980u) << 9u) | \
|
||||
(BOOTUF2_MONTH_INT << 5u) | \
|
||||
(BOOTUF2_DAY_INT << 0u))
|
||||
|
||||
#define BOOTUF2_DOS_TIME ( \
|
||||
(BOOTUF2_HOUR_INT << 11u) | \
|
||||
(BOOTUF2_MINUTE_INT << 5u) | \
|
||||
(BOOTUF2_SECONDS_INT << 0u))
|
||||
|
||||
void bootuf2_init(void);
|
||||
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count);
|
||||
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count);
|
||||
uint16_t bootuf2_get_sector_size(void);
|
||||
uint32_t bootuf2_get_sector_count(void);
|
||||
|
||||
bool bootuf2_is_write_done(void);
|
||||
|
||||
void boot2uf2_flash_init(void);
|
||||
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size);
|
||||
|
||||
#endif /* BOOTUF2_H */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BOOTUF2_CONFIG_H
|
||||
#define BOOTUF2_CONFIG_H
|
||||
|
||||
#define CONFIG_PRODUCT "CherryUSB"
|
||||
#define CONFIG_BOARD "CherryUSB BOARD"
|
||||
#define CONFIG_BOOTUF2_INDEX_URL "https://github.com/cherry-embedded"
|
||||
#define CONFIG_BOOTUF2_JOIN_URL "http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GyH2M5XfWTHQzmZis4ClpgvfdObPrvtk&authKey=LmcLhfno%2BiW51wmgVC%2F8WoYwUXqiclzWDHMU1Jy1d6S8cECJ4Q7bfJ%2FTe67RLakI&noverify=0&group_code=642693751"
|
||||
|
||||
#define CONFIG_BOOTUF2_CACHE_SIZE 4096
|
||||
#define CONFIG_BOOTUF2_SECTOR_SIZE 512
|
||||
#define CONFIG_BOOTUF2_SECTOR_PER_CLUSTER 2
|
||||
#define CONFIG_BOOTUF2_SECTOR_RESERVED 1
|
||||
#define CONFIG_BOOTUF2_NUM_OF_FAT 2
|
||||
#define CONFIG_BOOTUF2_ROOT_ENTRIES 64
|
||||
|
||||
#define CONFIG_BOOTUF2_FAMILYID 0xFFFFFFFF
|
||||
#define CONFIG_BOOTUF2_FLASHMAX 0x800000
|
||||
#define CONFIG_BOOTUF2_PAGE_COUNTMAX 1024
|
||||
|
||||
#endif
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "bootuf2.h"
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x02
|
||||
|
||||
#define USBD_VID 0xFFFF
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MSC_MAX_MPS 512
|
||||
#else
|
||||
#define MSC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
const uint8_t msc_bootuf2_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'U', 0x00, /* wcChar10 */
|
||||
'F', 0x00, /* wcChar11 */
|
||||
'2', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
bootuf2_init();
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||
{
|
||||
*block_num = bootuf2_get_sector_count();
|
||||
*block_size = bootuf2_get_sector_size();
|
||||
|
||||
USB_LOG_INFO("sector count:%d, sector size:%d\n", *block_num, *block_size);
|
||||
}
|
||||
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
boot2uf2_read_sector(sector, buffer, length / bootuf2_get_sector_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
bootuf2_write_sector(sector, buffer, length / bootuf2_get_sector_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void msc_bootuf2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
boot2uf2_flash_init();
|
||||
usbd_desc_register(busid, msc_bootuf2_descriptor);
|
||||
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
void boot2uf2_flash_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size)
|
||||
{
|
||||
USB_LOG_INFO("address:%08x, size:%d\n", address, size);
|
||||
return 0;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
|
@ -301,7 +301,7 @@ struct usbd_interface intf1;
|
|||
struct usbd_interface intf2;
|
||||
struct usbd_interface intf3;
|
||||
|
||||
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
#include "usbd_msc.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
|
@ -247,7 +247,7 @@ struct usbd_interface intf0;
|
|||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
|
||||
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
usbd_desc_register(busid, &cdc_msc_descriptor);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
|
@ -223,7 +223,7 @@ struct usbd_interface intf5;
|
|||
struct usbd_interface intf6;
|
||||
struct usbd_interface intf7;
|
||||
|
||||
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_multi_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, cdc_descriptor);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
|
@ -174,7 +174,7 @@ struct usbd_endpoint cdc_in_ep = {
|
|||
static struct usbd_interface intf0;
|
||||
static struct usbd_interface intf1;
|
||||
|
||||
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ struct usbd_interface intf1;
|
|||
* sudo ifconfig enxaabbccddeeff up
|
||||
* sudo dhcpclient enxaabbccddeeff
|
||||
*/
|
||||
void cdc_ecm_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
cdc_ecm_lwip_init();
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
|
|||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void cdc_rndis_init(uint8_t busid, uint32_t reg_base)
|
||||
void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
#ifdef RT_USING_LWIP
|
||||
rt_usbd_rndis_init();
|
||||
|
|
|
@ -169,7 +169,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
|
|||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void dfu_flash_init(uint8_t busid, uint32_t reg_base)
|
||||
void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, dfu_flash_descriptor);
|
||||
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
|
||||
|
|
|
@ -272,7 +272,7 @@ static struct usbd_endpoint custom_out_ep = {
|
|||
*/
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_custom_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_custom_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||
|
|
|
@ -221,7 +221,7 @@ static struct usbd_endpoint hid_in_ep = {
|
|||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_keyboard_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/*!< endpoint address */
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 4
|
||||
#define HID_INT_EP_INTERVAL 10
|
||||
#define HID_INT_EP_INTERVAL 1
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
|
@ -239,7 +239,7 @@ static struct usbd_endpoint hid_in_ep = {
|
|||
|
||||
struct usbd_interface intf0;
|
||||
|
||||
void hid_mouse_init(uint8_t busid, uint32_t reg_base)
|
||||
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||
|
@ -254,20 +254,59 @@ void hid_mouse_init(uint8_t busid, uint32_t reg_base)
|
|||
mouse_cfg.y = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief hid mouse test
|
||||
* @pre none
|
||||
* @param[in] none
|
||||
* @retval none
|
||||
*/
|
||||
#define CURSOR_STEP 2U
|
||||
#define CURSOR_WIDTH 20U
|
||||
|
||||
void draw_circle(uint8_t *buf)
|
||||
{
|
||||
static int32_t move_cnt = 0;
|
||||
static uint8_t step_x_y = 0;
|
||||
static int8_t x = 0, y = 0;
|
||||
|
||||
move_cnt++;
|
||||
if (move_cnt > CURSOR_WIDTH) {
|
||||
step_x_y++;
|
||||
step_x_y = step_x_y % 4;
|
||||
move_cnt = 0;
|
||||
}
|
||||
switch (step_x_y) {
|
||||
case 0: {
|
||||
y = 0;
|
||||
x = CURSOR_STEP;
|
||||
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
x = 0;
|
||||
y = CURSOR_STEP;
|
||||
|
||||
} break;
|
||||
|
||||
case 2: {
|
||||
y = 0;
|
||||
x = (int8_t)(-CURSOR_STEP);
|
||||
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
x = 0;
|
||||
y = (int8_t)(-CURSOR_STEP);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = x;
|
||||
buf[2] = y;
|
||||
buf[3] = 0;
|
||||
}
|
||||
|
||||
/* https://cps-check.com/cn/polling-rate-check */
|
||||
void hid_mouse_test(uint8_t busid)
|
||||
{
|
||||
int counter = 0;
|
||||
while (counter < 1000) {
|
||||
/*!< move mouse pointer */
|
||||
mouse_cfg.x += 40;
|
||||
mouse_cfg.y += 0;
|
||||
|
||||
draw_circle((uint8_t *)&mouse_cfg);
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 4
|
||||
#define HID_INT_EP_INTERVAL 1
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||
/*!< report descriptor size */
|
||||
#define HID_MOUSE_REPORT_DESC_SIZE 74
|
||||
|
||||
/*!< global descriptor */
|
||||
const uint8_t hid_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_REMOTE_WAKEUP | USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
0x09, /* bLength: HID Descriptor size */
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||
0x11, /* bcdHID: HID Class Spec release number */
|
||||
0x01,
|
||||
0x00, /* bCountryCode: Hardware target country */
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||
0x22, /* bDescriptorType */
|
||||
HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 34 */
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'H', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'D', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
/*!< hid mouse report descriptor */
|
||||
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xA1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Pointer)
|
||||
|
||||
0xA1, 0x00, // COLLECTION (Physical)
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x01, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38,
|
||||
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (2)
|
||||
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xC0, 0x09,
|
||||
0x3c, 0x05,
|
||||
0xff, 0x09,
|
||||
|
||||
0x01, 0x15,
|
||||
0x00, 0x25,
|
||||
0x01, 0x75,
|
||||
0x01, 0x95,
|
||||
|
||||
0x02, 0xb1,
|
||||
0x22, 0x75,
|
||||
0x06, 0x95,
|
||||
0x01, 0xb1,
|
||||
|
||||
0x01, 0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
/*!< mouse report struct */
|
||||
struct hid_mouse {
|
||||
uint8_t buttons;
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
int8_t wheel;
|
||||
};
|
||||
|
||||
/*!< mouse report */
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
hid_state = HID_STATE_IDLE;
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* function ------------------------------------------------------------------*/
|
||||
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
/*!< endpoint call back */
|
||||
static struct usbd_endpoint hid_in_ep = {
|
||||
.ep_cb = usbd_hid_int_callback,
|
||||
.ep_addr = HID_INT_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
|
||||
usbd_add_endpoint(busid, &hid_in_ep);
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
|
||||
/*!< init mouse report data */
|
||||
mouse_cfg.buttons = 0;
|
||||
mouse_cfg.wheel = 0;
|
||||
mouse_cfg.x = 0;
|
||||
mouse_cfg.y = 0;
|
||||
}
|
||||
|
||||
#define CURSOR_STEP 2U
|
||||
#define CURSOR_WIDTH 20U
|
||||
|
||||
void draw_circle(uint8_t *buf)
|
||||
{
|
||||
static int32_t move_cnt = 0;
|
||||
static uint8_t step_x_y = 0;
|
||||
static int8_t x = 0, y = 0;
|
||||
|
||||
move_cnt++;
|
||||
if (move_cnt > CURSOR_WIDTH) {
|
||||
step_x_y++;
|
||||
step_x_y = step_x_y % 4;
|
||||
move_cnt = 0;
|
||||
}
|
||||
switch (step_x_y) {
|
||||
case 0: {
|
||||
y = 0;
|
||||
x = CURSOR_STEP;
|
||||
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
x = 0;
|
||||
y = CURSOR_STEP;
|
||||
|
||||
} break;
|
||||
|
||||
case 2: {
|
||||
y = 0;
|
||||
x = (int8_t)(-CURSOR_STEP);
|
||||
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
x = 0;
|
||||
y = (int8_t)(-CURSOR_STEP);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = x;
|
||||
buf[2] = y;
|
||||
buf[3] = 0;
|
||||
}
|
||||
|
||||
/* https://cps-check.com/cn/polling-rate-check */
|
||||
void hid_mouse_test(uint8_t busid)
|
||||
{
|
||||
static uint32_t count = 1000;
|
||||
int ret;
|
||||
|
||||
// if (gpio_read_pin(GPIO_PIN) == 1) {
|
||||
// ret = usbd_send_remote_wakeup(busid);
|
||||
// if (ret < 0) {
|
||||
// return;
|
||||
// }
|
||||
// count = 5000;
|
||||
// }
|
||||
|
||||
while (count) {
|
||||
draw_circle((uint8_t *)&mouse_cfg);
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
hid_state = HID_STATE_BUSY;
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
}
|
|
@ -202,7 +202,7 @@ struct usbd_endpoint midi_in_ep = {
|
|||
.ep_cb = usbd_midi_bulk_in
|
||||
};
|
||||
|
||||
void midi_init(uint8_t busid, uint32_t reg_base)
|
||||
void midi_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, midi_descriptor);
|
||||
usbd_add_interface(busid, &intf0);
|
||||
|
|
|
@ -154,12 +154,19 @@ int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct usbd_interface intf0;
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void msc_ram_init(uint8_t busid, uint32_t reg_base)
|
||||
void msc_ram_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, msc_ram_descriptor);
|
||||
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
void msc_ram_polling(uint8_t busid)
|
||||
{
|
||||
usbd_msc_polling(busid);
|
||||
}
|
||||
#endif
|
|
@ -154,7 +154,7 @@ int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
void msc_storage_init(uint8_t busid, uint32_t reg_base)
|
||||
void msc_storage_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
rt_err_t res;
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ void usbh_hid_callback(void *arg, int nbytes)
|
|||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
USB_LOG_RAW("0x%02x ", hid_buffer[i]);
|
||||
}
|
||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||
|
|
|
@ -416,7 +416,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||
.ep = AUDIO_OUT_EP },
|
||||
};
|
||||
|
||||
void composite_init(uint8_t busid, uint32_t reg_base)
|
||||
void composite_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_audio_hid_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
|
|
|
@ -192,7 +192,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
|
|
|
@ -192,7 +192,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
|
|
|
@ -194,7 +194,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
void video_init(uint8_t busid, uint32_t reg_base)
|
||||
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, video_descriptor);
|
||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
#define USBD_VID 0xffff
|
||||
#define USBD_PID 0xffff
|
||||
#define USBD_MAX_POWER 100
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define HID_INT_EP 0x81
|
||||
#define HID_INT_EP_SIZE 8
|
||||
#define HID_INT_EP_INTERVAL 10
|
||||
|
||||
#define USB_HID_CONFIG_DESC_SIZ (34 + 9)
|
||||
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
|
||||
|
||||
#define USBD_WEBUSB_VENDOR_CODE (0x22)
|
||||
#define USBD_WINUSB_VENDOR_CODE (0x21)
|
||||
|
||||
#define USBD_WINUSB_DESC_SET_LEN (0xB2)
|
||||
#define URL_DESCRIPTOR_LENGTH (3 + 36)
|
||||
|
||||
#define USBD_WEBUSB_INTF_NUM 0x01
|
||||
|
||||
#define WEBUSB_URL_STRINGS \
|
||||
'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', \
|
||||
'c', 'h', 'e', 'r', 'r', 'y', '-', 'e', 'm', 'b', 'e', 'd', 'd', 'e', 'd', '/', 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B',
|
||||
|
||||
const uint8_t USBD_WinUSBDescriptorSetDescriptor[USBD_WINUSB_DESC_SET_LEN] = {
|
||||
// Microsoft OS 2.0 描述符集标头
|
||||
0x0A, 0x00, // Descriptor size (10 bytes)
|
||||
0x00, 0x00, // MS OS 2.0 descriptor set header
|
||||
0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
|
||||
USBD_WINUSB_DESC_SET_LEN, 0x00, // Size, MS OS 2.0 descriptor set
|
||||
|
||||
// Microsoft OS 2.0 配置子集标头
|
||||
0x08, 0x00, // wLength
|
||||
0x01, 0x00, // wDescriptorType
|
||||
0x00, // 适用于配置 1
|
||||
0x00, // bReserved
|
||||
0XA8, 0X00, // Size, MS OS 2.0 configuration subset
|
||||
|
||||
// Microsoft OS 2.0 功能子集头
|
||||
0x08, 0x00, // Descriptor size (8 bytes)
|
||||
0x02, 0x00, // MS OS 2.0 function subset header
|
||||
USBD_WEBUSB_INTF_NUM, // bFirstInterface
|
||||
0x00, // 必须设置为 0
|
||||
0xA0, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 兼容 ID 描述符
|
||||
// 兼容 ID 描述符告诉 Windows 此设备与 WinUSB 驱动程序兼容
|
||||
0x14, 0x00, // wLength 20
|
||||
0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 注册表属性描述符
|
||||
// 注册表属性分配设备接口 GUID
|
||||
0x84, 0x00, //wLength: 132
|
||||
0x04, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
|
||||
0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
|
||||
0x2a, 0x00, //wPropertyNameLength:
|
||||
//bPropertyName: “DeviceInterfaceGUID”
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
|
||||
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
|
||||
0x00, 0x00,
|
||||
0x50, 0x00, // wPropertyDataLength
|
||||
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
|
||||
'{', 0x00, '9', 0x00, 'd', 0x00, '7', 0x00, 'd', 0x00, 'e', 0x00, 'b', 0x00, 'b', 0x00, 'c', 0x00, '-', 0x00,
|
||||
'c', 0x00, '8', 0x00, '5', 0x00, 'd', 0x00, '-', 0x00, '1', 0x00, '1', 0x00, 'd', 0x00, '1', 0x00, '-', 0x00,
|
||||
'9', 0x00, 'e', 0x00, 'b', 0x00, '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '6', 0x00, '0', 0x00, '0', 0x00,
|
||||
'8', 0x00, 'c', 0x00, '3', 0x00, 'a', 0x00, '1', 0x00, '9', 0x00, 'a', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = {
|
||||
URL_DESCRIPTOR_LENGTH,
|
||||
WEBUSB_URL_TYPE,
|
||||
WEBUSB_URL_SCHEME_HTTPS,
|
||||
WEBUSB_URL_STRINGS
|
||||
};
|
||||
|
||||
#define USBD_BOS_WTOTALLENGTH 0x39
|
||||
|
||||
#define LANDING_PAGE 0x01
|
||||
uint8_t USBD_BinaryObjectStoreDescriptor[USBD_BOS_WTOTALLENGTH] = {
|
||||
// BOS描述符
|
||||
0x05, // bLength 固长为5
|
||||
0x0F, // bDescriptorType 固定为15
|
||||
USBD_BOS_WTOTALLENGTH, 0x00, // wTotalLength BOS描述符的总大小
|
||||
0x02, // bNumDeviceCaps BOS描述符中独立设备功能特性描述符的数量
|
||||
|
||||
// WebUSB 平台功能描述符
|
||||
0x18, // Descriptor size (24 bytes)
|
||||
0x10, // Descriptor type (Device Capability) 设备功能描述符
|
||||
0x05, // Capability type (Platform) 平台描述符
|
||||
0x00, // Reserved
|
||||
|
||||
// WebUSB Platform Capability ID (3408b638-09a9-47a0-8bfd-a0768815b665)
|
||||
// 平台功能 UUID 将此标识为WebUSB 平台功能描述符,它提供有关设备的基本信息
|
||||
0x38, 0xB6, 0x08, 0x34,
|
||||
0xA9, 0x09,
|
||||
0xA0, 0x47,
|
||||
0x8B, 0xFD,
|
||||
0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
|
||||
|
||||
0x00, 0x01, // WebUSB version 1.0
|
||||
USBD_WEBUSB_VENDOR_CODE, // Vendor-assigned WebUSB request code
|
||||
LANDING_PAGE, // Landing page
|
||||
|
||||
// Microsoft 平台功能描述符
|
||||
// 标头
|
||||
0x1C, // Descriptor size (28 bytes)
|
||||
0x10, // Descriptor type (Device Capability)
|
||||
0x05, // Capability type (Platform)
|
||||
0x00, // Reserved
|
||||
|
||||
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||
0x89, 0x45, 0xC7, 0x4C,
|
||||
0x9C, 0xD2, 0x65, 0x9D,
|
||||
0x9E, 0x64, 0x8A, 0x9F,
|
||||
|
||||
// 描述符集信息结构
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 * dwWindowsVersion 最低兼容 Windows 版本 */
|
||||
|
||||
USBD_WINUSB_DESC_SET_LEN, 0X00, /* wDescriptorSetTotalLength */
|
||||
|
||||
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||
0X00 /* bAltEnumCode */
|
||||
};
|
||||
|
||||
struct usb_webusb_descriptor webusb_url_desc = {
|
||||
.vendor_code = USBD_WEBUSB_VENDOR_CODE,
|
||||
.string = USBD_WebUSBURLDescriptor,
|
||||
.string_len = USBD_WINUSB_DESC_SET_LEN
|
||||
};
|
||||
|
||||
struct usb_msosv2_descriptor msosv2_desc = {
|
||||
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||
};
|
||||
|
||||
struct usb_bos_descriptor bos_desc = {
|
||||
.string = USBD_BinaryObjectStoreDescriptor,
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
static const uint8_t webusb_hid_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||
0, /* iInterface: Index of string descriptor */
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
0x09, /* bLength: HID Descriptor size */
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||
0x11, /* bcdHID: HID Class Spec release number */
|
||||
0x01,
|
||||
0x00, /* bCountryCode: Hardware target country */
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||
0x22, /* bDescriptorType */
|
||||
HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||
0x03, /* bmAttributes: Interrupt endpoint */
|
||||
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||
/* 34 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
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 */
|
||||
'H', 0x00, /* wcChar10 */
|
||||
'I', 0x00, /* wcChar11 */
|
||||
'D', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 0x00, /* wcChar0 */
|
||||
'0', 0x00, /* wcChar1 */
|
||||
'2', 0x00, /* wcChar2 */
|
||||
'2', 0x00, /* wcChar3 */
|
||||
'1', 0x00, /* wcChar4 */
|
||||
'2', 0x00, /* wcChar5 */
|
||||
'3', 0x00, /* wcChar6 */
|
||||
'4', 0x00, /* wcChar7 */
|
||||
'5', 0x00, /* wcChar8 */
|
||||
'6', 0x00, /* wcChar9 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
|
||||
/* USB HID device Configuration Descriptor */
|
||||
static uint8_t hid_desc[9] __ALIGN_END = {
|
||||
/* 18 */
|
||||
0x09, /* bLength: HID Descriptor size */
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||
0x11, /* bcdHID: HID Class Spec release number */
|
||||
0x01,
|
||||
0x00, /* bCountryCode: Hardware target country */
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||
0x22, /* bDescriptorType */
|
||||
HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x06, // USAGE (Keyboard)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x05, 0x08, // USAGE_PAGE (LEDs)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
||||
0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x03, // REPORT_SIZE (3)
|
||||
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
||||
0x95, 0x06, // REPORT_COUNT (6)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
/*!< hid state ! Data can be sent only when state is idle */
|
||||
static volatile uint8_t hid_state = HID_STATE_IDLE;
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
hid_state = HID_STATE_IDLE;
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
static struct usbd_endpoint hid_in_ep = {
|
||||
.ep_cb = usbd_hid_int_callback,
|
||||
.ep_addr = HID_INT_EP
|
||||
};
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
|
||||
void webusb_hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, webusb_hid_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||
usbd_webusb_desc_register(busid, &webusb_url_desc);
|
||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||
usbd_add_endpoint(busid, &hid_in_ep);
|
||||
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64];
|
||||
|
||||
void hid_keyboard_test(uint8_t busid)
|
||||
{
|
||||
const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(write_buffer, sendbuffer, 8);
|
||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
hid_state = HID_STATE_BUSY;
|
||||
while (hid_state == HID_STATE_BUSY) {
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
|
||||
#define MS_OS_20_DESCRIPTOR_LENGTH (0xB2)
|
||||
|
||||
#define WEBUSB_URL_STRINGS \
|
||||
'd', 'e', 'v', 'a', 'n', 'l', 'a', 'i', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'i', 'o', '/', 'w', 'e', 'b', 'd', 'f', 'u', '/', 'd', 'f', 'u', '-', 'u', 't', 'i', 'l'
|
||||
|
||||
#define WL_REQUEST_WEBUSB (0x22)
|
||||
#define WL_REQUEST_WINUSB (0x21)
|
||||
|
||||
#define URL_DESCRIPTOR_LENGTH 0x2C
|
||||
|
||||
// 描述符集信息
|
||||
const uint8_t MS_OS_20_DESCRIPTOR_SET[MS_OS_20_DESCRIPTOR_LENGTH] = {
|
||||
// Microsoft OS 2.0 描述符集标头
|
||||
0x0A, 0x00, // Descriptor size (10 bytes)
|
||||
0x00, 0x00, // MS OS 2.0 descriptor set header
|
||||
0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
|
||||
MS_OS_20_DESCRIPTOR_LENGTH, 0x00, // Size, MS OS 2.0 descriptor set
|
||||
|
||||
// Microsoft OS 2.0 配置子集标头
|
||||
0x08, 0x00, // wLength
|
||||
0x01, 0x00, // wDescriptorType
|
||||
0x00, // 适用于配置 1
|
||||
0x00, // bReserved
|
||||
0XA8, 0X00, // Size, MS OS 2.0 configuration subset
|
||||
|
||||
// Microsoft OS 2.0 功能子集头
|
||||
0x08, 0x00, // Descriptor size (8 bytes)
|
||||
0x02, 0x00, // MS OS 2.0 function subset header
|
||||
0x01, // 第2个接口
|
||||
0x00, // 必须设置为 0
|
||||
0xA0, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 兼容 ID 描述符
|
||||
// 兼容 ID 描述符告诉 Windows 此设备与 WinUSB 驱动程序兼容
|
||||
0x14, 0x00, // wLength 20
|
||||
0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// Microsoft OS 2.0 注册表属性描述符
|
||||
// 注册表属性分配设备接口 GUID
|
||||
0x84, 0x00, //wLength: 132
|
||||
0x04, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
|
||||
0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
|
||||
0x2a, 0x00, //wPropertyNameLength:
|
||||
//bPropertyName: “DeviceInterfaceGUID”
|
||||
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
|
||||
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
|
||||
0x00, 0x00,
|
||||
0x50, 0x00, // wPropertyDataLength
|
||||
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
|
||||
'{', 0x00, '9', 0x00, 'd', 0x00, '7', 0x00, 'd', 0x00, 'e', 0x00, 'b', 0x00, 'b', 0x00, 'c', 0x00, '-', 0x00,
|
||||
'c', 0x00, '8', 0x00, '5', 0x00, 'd', 0x00, '-', 0x00, '1', 0x00, '1', 0x00, 'd', 0x00, '1', 0x00, '-', 0x00,
|
||||
'9', 0x00, 'e', 0x00, 'b', 0x00, '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '6', 0x00, '0', 0x00, '0', 0x00,
|
||||
'8', 0x00, 'c', 0x00, '3', 0x00, 'a', 0x00, '1', 0x00, '9', 0x00, 'a', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = {
|
||||
URL_DESCRIPTOR_LENGTH,
|
||||
WEBUSB_URL_TYPE,
|
||||
WEBUSB_URL_SCHEME_HTTPS,
|
||||
WEBUSB_URL_STRINGS
|
||||
};
|
||||
|
||||
struct usb_webusb_url_ex_descriptor webusb_url_desc = {
|
||||
.vendor_code = WL_REQUEST_WEBUSB,
|
||||
.string = MS_OS_20_DESCRIPTOR_SET,
|
||||
.string_len = MS_OS_20_DESCRIPTOR_LENGTH
|
||||
};
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
#define WCID_VENDOR_CODE 0x17
|
||||
|
||||
|
@ -151,18 +151,16 @@ __ALIGN_BEGIN const uint8_t WINUSB_IF1_WCIDProperties [142] __ALIGN_END = {
|
|||
|
||||
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||
WINUSB_IF0_WCIDProperties,
|
||||
#if DOUBLE_WINUSB == 1
|
||||
WINUSB_IF1_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor msosv1_desc = {
|
||||
.string = WCID_StringDescriptor_MSOS,
|
||||
.vendor_code = WCID_VENDOR_CODE,
|
||||
.compat_id = WINUSB_WCIDDescriptor,
|
||||
#if DOUBLE_WINUSB == 0
|
||||
.comp_id_property = &WINUSB_IF0_WCIDProperties,
|
||||
#else
|
||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
|
@ -446,7 +444,7 @@ struct usbd_interface intf1;
|
|||
|
||||
#endif
|
||||
|
||||
void winusb_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusb_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusb_descriptor);
|
||||
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
#define WINUSB_IN_EP 0x81
|
||||
#define WINUSB_OUT_EP 0x02
|
||||
|
@ -318,7 +318,7 @@ struct usb_bos_descriptor bos_desc = {
|
|||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusbv2_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
|
|
|
@ -422,7 +422,7 @@ struct usb_bos_descriptor bos_desc = {
|
|||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
void winusbv2_init(uint8_t busid, uint32_t reg_base)
|
||||
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
usbd_desc_register(busid, winusbv2_descriptor);
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
|
|
|
@ -129,7 +129,7 @@ struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_
|
|||
timer = rt_malloc(sizeof(struct usb_osal_timer));
|
||||
memset(timer, 0, sizeof(struct usb_osal_timer));
|
||||
|
||||
timer->timer = (void *)rt_timer_create("usb_tim", handler, argument, timeout_ms, is_period ? (RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER) : (RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER));
|
||||
timer->timer = (void *)rt_timer_create(name, handler, argument, timeout_ms, is_period ? (RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER) : (RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER));
|
||||
if (timer->timer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -167,3 +167,13 @@ void usb_osal_msleep(uint32_t delay)
|
|||
{
|
||||
rt_thread_mdelay(delay);
|
||||
}
|
||||
|
||||
void *usb_osal_malloc(size_t size)
|
||||
{
|
||||
return rt_malloc(size);
|
||||
}
|
||||
|
||||
void usb_osal_free(void *ptr)
|
||||
{
|
||||
rt_free(ptr);
|
||||
}
|
|
@ -7,11 +7,11 @@
|
|||
#endif
|
||||
|
||||
#if IDLE_THREAD_STACK_SIZE < 2048
|
||||
#error "IDLE_THREAD_STACK_SIZE must be greater than 2048"
|
||||
#error "IDLE_THREAD_STACK_SIZE must be greater than or equal to 2048"
|
||||
#endif
|
||||
|
||||
#if RT_TIMER_THREAD_STACK_SIZE < 2048
|
||||
#error "RT_TIMER_THREAD_STACK_SIZE must be greater than 2048"
|
||||
#error "RT_TIMER_THREAD_STACK_SIZE must be greater than or equal to 2048"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,17 +36,6 @@ void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
|
|||
bflb_l1c_dcache_invalidate_range(addr, size);
|
||||
}
|
||||
}
|
||||
#elif defined(SOC_HPM5000) || defined(SOC_HPM6000)
|
||||
#include "hpm_l1c_drv.h"
|
||||
|
||||
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_FLUSH) {
|
||||
l1c_dc_flush((uint32_t)addr, size);
|
||||
} else {
|
||||
l1c_dc_invalidate((uint32_t)addr, size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t msc_sector[512];
|
||||
|
|
|
@ -613,6 +613,23 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_remote_wakeup(uint8_t busid)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
|
||||
regval |= USB_CAP_RMWAKUP;
|
||||
putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
|
||||
|
||||
bflb_mtimer_delay_ms(10);
|
||||
|
||||
regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
|
||||
regval &= ~USB_CAP_RMWAKUP;
|
||||
putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
uint8_t speed = 3;
|
||||
|
@ -638,7 +655,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
|||
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep_addr);
|
||||
|
||||
if ((ep_idx > 4) && (ep_idx < 9)) {
|
||||
if (ep_idx > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -822,6 +839,29 @@ int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
|||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (ep_idx == 0) {
|
||||
} else {
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
regval = getreg32(BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4);
|
||||
if (regval & USB_STL_OEP1) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
} else {
|
||||
regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4);
|
||||
if (regval & USB_STL_IEP1) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1019,12 +1059,11 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
void usbd_execute_test_mode(struct usb_setup_packet *setup)
|
||||
void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint8_t index = setup->wIndex >> 8;
|
||||
|
||||
switch (index) {
|
||||
switch (test_mode) {
|
||||
case 1: // Test_J
|
||||
{
|
||||
regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# Note
|
||||
|
||||
## Support Chip List
|
||||
|
||||
### NXP
|
||||
|
||||
Modify USB_NOCACHE_RAM_SECTION
|
||||
|
||||
```
|
||||
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".NonCacheable")))
|
||||
```
|
||||
|
||||
- IMRT10XX/IMRT11XX
|
||||
- MCXN9XX/MCXN236
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,707 @@
|
|||
#include "usbd_core.h"
|
||||
#include "usb_chipidea_reg.h"
|
||||
|
||||
#define USB_OTG_DEV ((CHIPIDEA_TypeDef *)g_usbdev_bus[busid].reg_base)
|
||||
|
||||
#define CHIPIDEA_BITSMASK(val, offset) ((uint32_t)(val) << (offset))
|
||||
#define QTD_COUNT_EACH_ENDPOINT (8U)
|
||||
|
||||
/* ENDPTCTRL */
|
||||
enum {
|
||||
ENDPTCTRL_STALL = CHIPIDEA_BITSMASK(1, 0),
|
||||
ENDPTCTRL_TYPE = CHIPIDEA_BITSMASK(3, 2),
|
||||
ENDPTCTRL_TOGGLE_INHIBIT = CHIPIDEA_BITSMASK(1, 5),
|
||||
ENDPTCTRL_TOGGLE_RESET = CHIPIDEA_BITSMASK(1, 6),
|
||||
ENDPTCTRL_ENABLE = CHIPIDEA_BITSMASK(1, 7),
|
||||
};
|
||||
|
||||
/* USBSTS, USBINTR */
|
||||
enum {
|
||||
intr_usb = CHIPIDEA_BITSMASK(1, 0),
|
||||
intr_error = CHIPIDEA_BITSMASK(1, 1),
|
||||
intr_port_change = CHIPIDEA_BITSMASK(1, 2),
|
||||
intr_reset = CHIPIDEA_BITSMASK(1, 6),
|
||||
intr_sof = CHIPIDEA_BITSMASK(1, 7),
|
||||
intr_suspend = CHIPIDEA_BITSMASK(1, 8),
|
||||
intr_nak = CHIPIDEA_BITSMASK(1, 16)
|
||||
};
|
||||
|
||||
/* Queue Transfer Descriptor */
|
||||
typedef struct {
|
||||
/* Word 0: Next QTD Pointer */
|
||||
volatile uint32_t next; /* Next link pointer This field contains the physical memory address of the next dTD to be processed */
|
||||
|
||||
/* Word 1: qTQ Token */
|
||||
volatile uint32_t : 3;
|
||||
volatile uint32_t xact_err : 1;
|
||||
volatile uint32_t : 1;
|
||||
volatile uint32_t buffer_err : 1;
|
||||
volatile uint32_t halted : 1;
|
||||
volatile uint32_t active : 1;
|
||||
volatile uint32_t : 2;
|
||||
volatile uint32_t iso_mult_override : 2; /* This field can be used for transmit ISOs to override the MULT field in the dQH. This field must be zero for all packet types that are not transmit-ISO. */
|
||||
volatile uint32_t : 3;
|
||||
volatile uint32_t int_on_complete : 1;
|
||||
volatile uint32_t total_bytes : 15;
|
||||
volatile uint32_t : 0;
|
||||
|
||||
/* Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page */
|
||||
volatile uint32_t buffer[5];
|
||||
|
||||
/*------------- DCD Area -------------*/
|
||||
volatile uint16_t expected_bytes;
|
||||
volatile uint8_t reserved[2];
|
||||
} dcd_qtd_t;
|
||||
|
||||
/* Queue Head */
|
||||
typedef struct {
|
||||
/* Word 0: Capabilities and Characteristics */
|
||||
|
||||
volatile uint32_t : 15; /* Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed. */
|
||||
volatile uint32_t int_on_setup : 1; /* Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received. */
|
||||
volatile uint32_t max_packet_size : 11; /* This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) */
|
||||
volatile uint32_t : 2;
|
||||
volatile uint32_t zero_length_termination : 1; /* This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length. */
|
||||
volatile uint32_t iso_mult : 2;
|
||||
volatile uint32_t : 0;
|
||||
|
||||
/* Word 1: Current qTD Pointer */
|
||||
volatile uint32_t qtd_addr;
|
||||
|
||||
/* Word 2-9: Transfer Overlay */
|
||||
volatile dcd_qtd_t qtd_overlay;
|
||||
|
||||
/* Word 10-11: Setup request (control OUT only) */
|
||||
volatile struct usb_setup_packet setup_request;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes
|
||||
* thus there are 16 bytes padding free that we can make use of.
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
volatile uint8_t reserved[16];
|
||||
} dcd_qhd_t;
|
||||
|
||||
typedef struct {
|
||||
dcd_qhd_t qhd[CONFIG_USBDEV_EP_NUM * 2];
|
||||
dcd_qtd_t qtd[CONFIG_USBDEV_EP_NUM * 2 * QTD_COUNT_EACH_ENDPOINT];
|
||||
} dcd_data_t;
|
||||
|
||||
/* Endpoint state */
|
||||
struct chipidea_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 *xfer_buf;
|
||||
uint32_t xfer_len;
|
||||
uint32_t actual_xfer_len;
|
||||
};
|
||||
|
||||
/* Driver state */
|
||||
struct chipidea_udc {
|
||||
dcd_data_t *dcd_data;
|
||||
bool is_suspend;
|
||||
struct chipidea_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
|
||||
struct chipidea_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
|
||||
} g_chipidea_udc[CONFIG_USBDEV_MAX_BUS];
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION __attribute__((aligned(2048))) dcd_data_t _dcd_data0;
|
||||
#if CONFIG_USBDEV_MAX_BUS == 2
|
||||
static USB_NOCACHE_RAM_SECTION __attribute__((aligned(2048))) dcd_data_t _dcd_data1;
|
||||
#endif
|
||||
|
||||
static dcd_data_t *g_dcd_data[CONFIG_USBDEV_MAX_BUS] = {
|
||||
&_dcd_data0,
|
||||
#if CONFIG_USBDEV_MAX_BUS == 2
|
||||
&_dcd_data1
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Index to bit position in register */
|
||||
static inline uint8_t ep_idx2bit(uint8_t ep_idx)
|
||||
{
|
||||
return ep_idx / 2 + ((ep_idx % 2) ? 16 : 0);
|
||||
}
|
||||
|
||||
static void __chipidea_bus_reset(CHIPIDEA_TypeDef *ptr)
|
||||
{
|
||||
/* The reset value for all endpoint types is the control endpoint. If one endpoint
|
||||
* direction is enabled and the paired endpoint of opposite direction is disabled, then the
|
||||
* endpoint type of the unused direction must be changed from the control type to any other
|
||||
* type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
|
||||
* for the data PID tracking on the active endpoint.
|
||||
*/
|
||||
|
||||
for (uint32_t i = 1; i < CONFIG_USBDEV_EP_NUM; i++) {
|
||||
ptr->ENDPTCTRL[i] = USB_ENDPTCTRL_TXT_SET(USB_ENDPOINT_TYPE_BULK) | USB_ENDPTCTRL_RXT_SET(USB_ENDPOINT_TYPE_BULK);
|
||||
}
|
||||
|
||||
/* Clear All Registers */
|
||||
ptr->ENDPTNAK = ptr->ENDPTNAK;
|
||||
ptr->ENDPTNAKEN = 0;
|
||||
ptr->USBSTS = ptr->USBSTS;
|
||||
ptr->ENDPTSETUPSTAT = ptr->ENDPTSETUPSTAT;
|
||||
ptr->ENDPTCOMPLETE = ptr->ENDPTCOMPLETE;
|
||||
|
||||
while (ptr->ENDPTPRIME) {
|
||||
}
|
||||
ptr->ENDPTFLUSH = 0xFFFFFFFF;
|
||||
while (ptr->ENDPTFLUSH) {
|
||||
}
|
||||
}
|
||||
|
||||
static void chipidea_init(CHIPIDEA_TypeDef *ptr)
|
||||
{
|
||||
/* Reset controller */
|
||||
ptr->USBCMD |= USB_USBCMD_RST_MASK;
|
||||
while (USB_USBCMD_RST_GET(ptr->USBCMD)) {
|
||||
}
|
||||
|
||||
/* Set mode to device, must be set immediately after reset */
|
||||
ptr->USBMODE &= ~USB_USBMODE_CM_MASK;
|
||||
ptr->USBMODE |= USB_USBMODE_CM_SET(2);
|
||||
|
||||
/* Disable setup lockout, please refer to "Control Endpoint Operation" section in RM. */
|
||||
ptr->USBMODE &= ~USB_USBMODE_SLOM_MASK;
|
||||
|
||||
/* Set the endian */
|
||||
ptr->USBMODE &= ~USB_USBMODE_ES_MASK;
|
||||
|
||||
/* Set parallel interface signal */
|
||||
ptr->PORTSC1 &= ~USB_PORTSC1_STS_MASK;
|
||||
|
||||
/* Set parallel transceiver width */
|
||||
ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK;
|
||||
|
||||
/* Set usb forced to full speed mode */
|
||||
//ptr->PORTSC1 |= USB_PORTSC1_PFSC_MASK;
|
||||
|
||||
/* Not use interrupt threshold. */
|
||||
ptr->USBCMD &= ~USB_USBCMD_ITC_MASK;
|
||||
|
||||
/* Enable VBUS discharge */
|
||||
ptr->OTGSC |= USB_OTGSC_VD_MASK;
|
||||
}
|
||||
|
||||
static void chipidea_deinit(CHIPIDEA_TypeDef *ptr)
|
||||
{
|
||||
/* Stop */
|
||||
ptr->USBCMD &= ~USB_USBCMD_RS_MASK;
|
||||
|
||||
/* Reset controller */
|
||||
ptr->USBCMD |= USB_USBCMD_RST_MASK;
|
||||
while (USB_USBCMD_RST_GET(ptr->USBCMD)) {
|
||||
}
|
||||
|
||||
/* Reset endpoint list address register */
|
||||
ptr->ENDPTLISTADDR = 0;
|
||||
|
||||
/* Reset status register */
|
||||
ptr->USBSTS = ptr->USBSTS;
|
||||
|
||||
/* Reset interrupt enable register */
|
||||
ptr->USBINTR = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* Endpoint API
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
static void __chipidea_edpt_open(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr, uint8_t ep_type)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
|
||||
/* Enable EP Control */
|
||||
uint32_t temp = ptr->ENDPTCTRL[epnum];
|
||||
temp &= ~((0x03 << 2) << (dir ? 16 : 0));
|
||||
temp |= ((ep_type << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0);
|
||||
ptr->ENDPTCTRL[epnum] = temp;
|
||||
}
|
||||
|
||||
static void chipidea_edpt_xfer(CHIPIDEA_TypeDef *ptr, uint8_t ep_idx)
|
||||
{
|
||||
uint32_t offset = ep_idx / 2 + ((ep_idx % 2) ? 16 : 0);
|
||||
|
||||
/* Start transfer */
|
||||
ptr->ENDPTPRIME = 1 << offset;
|
||||
}
|
||||
|
||||
static void chipidea_edpt_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
|
||||
ptr->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
|
||||
}
|
||||
|
||||
static void chipidea_edpt_clear_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
|
||||
/* data toggle also need to be reset */
|
||||
ptr->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << (dir ? 16 : 0);
|
||||
ptr->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << (dir ? 16 : 0));
|
||||
}
|
||||
|
||||
static bool chipidea_edpt_check_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
|
||||
return (ptr->ENDPTCTRL[epnum] & (ENDPTCTRL_STALL << (dir ? 16 : 0))) ? true : false;
|
||||
}
|
||||
|
||||
static void chipidea_edpt_close(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
|
||||
uint32_t primebit = CHIPIDEA_BITSMASK(1, epnum) << (dir ? 16 : 0);
|
||||
|
||||
/* Flush the endpoint to stop a transfer. */
|
||||
do {
|
||||
/* Set the corresponding bit(s) in the ENDPTFLUSH register */
|
||||
ptr->ENDPTFLUSH |= primebit;
|
||||
|
||||
/* Wait until all bits in the ENDPTFLUSH register are cleared. */
|
||||
while (0U != (ptr->ENDPTFLUSH & primebit)) {
|
||||
}
|
||||
/*
|
||||
* Read the ENDPTSTAT register to ensure that for all endpoints
|
||||
* commanded to be flushed, that the corresponding bits
|
||||
* are now cleared.
|
||||
*/
|
||||
} while (0U != (ptr->ENDPTSTAT & primebit));
|
||||
|
||||
/* Disable the endpoint */
|
||||
ptr->ENDPTCTRL[epnum] &= ~((ENDPTCTRL_TYPE | ENDPTCTRL_ENABLE | ENDPTCTRL_STALL) << (dir ? 16 : 0));
|
||||
ptr->ENDPTCTRL[epnum] |= (USB_ENDPOINT_TYPE_BULK << 2) << (dir ? 16 : 0);
|
||||
}
|
||||
|
||||
/* Initialize qtd */
|
||||
static void usb_qtd_init(dcd_qtd_t *p_qtd, void *data_ptr, uint16_t total_bytes)
|
||||
{
|
||||
memset(p_qtd, 0, sizeof(dcd_qtd_t));
|
||||
|
||||
p_qtd->next = 1;
|
||||
p_qtd->active = 1;
|
||||
p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
|
||||
|
||||
if (data_ptr != NULL) {
|
||||
p_qtd->buffer[0] = (uint32_t)data_ptr;
|
||||
for (uint8_t i = 1; i < 5; i++) {
|
||||
p_qtd->buffer[i] |= ((p_qtd->buffer[i - 1]) & 0xFFFFF000UL) + 4096U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dcd_qhd_t *chipidea_qhd_get(uint8_t busid, uint8_t ep_idx)
|
||||
{
|
||||
dcd_data_t *dcd_data;
|
||||
|
||||
dcd_data = g_chipidea_udc[busid].dcd_data;
|
||||
return &dcd_data->qhd[ep_idx];
|
||||
}
|
||||
|
||||
static dcd_qtd_t *chipidea_qtd_get(uint8_t busid, uint8_t ep_idx)
|
||||
{
|
||||
dcd_data_t *dcd_data;
|
||||
|
||||
dcd_data = g_chipidea_udc[busid].dcd_data;
|
||||
return &dcd_data->qtd[ep_idx * QTD_COUNT_EACH_ENDPOINT];
|
||||
}
|
||||
|
||||
static void chipidea_bus_reset(uint8_t busid, uint16_t ep0_max_packet_size)
|
||||
{
|
||||
dcd_data_t *dcd_data;
|
||||
|
||||
dcd_data = g_chipidea_udc[busid].dcd_data;
|
||||
__chipidea_bus_reset(USB_OTG_DEV);
|
||||
|
||||
/* Queue Head & Queue TD */
|
||||
memset(dcd_data, 0, sizeof(dcd_data_t));
|
||||
|
||||
/* Set up Control Endpoints (0 OUT, 1 IN) */
|
||||
dcd_data->qhd[0].zero_length_termination = dcd_data->qhd[1].zero_length_termination = 1;
|
||||
dcd_data->qhd[0].max_packet_size = dcd_data->qhd[1].max_packet_size = ep0_max_packet_size;
|
||||
dcd_data->qhd[0].qtd_overlay.next = dcd_data->qhd[1].qtd_overlay.next = 1;
|
||||
|
||||
/* OUT only */
|
||||
dcd_data->qhd[0].int_on_setup = 1;
|
||||
}
|
||||
|
||||
static void chipidea_edpt_open(uint8_t busid, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
uint8_t const ep_idx = 2 * epnum + dir;
|
||||
dcd_data_t *dcd_data;
|
||||
dcd_qhd_t *p_qhd;
|
||||
|
||||
/* Prepare Queue Head */
|
||||
dcd_data = g_chipidea_udc[busid].dcd_data;
|
||||
p_qhd = &dcd_data->qhd[ep_idx];
|
||||
memset(p_qhd, 0, sizeof(dcd_qhd_t));
|
||||
|
||||
p_qhd->zero_length_termination = 1;
|
||||
p_qhd->max_packet_size = ep_mps & 0x7FFu;
|
||||
p_qhd->qtd_overlay.next = 1;
|
||||
if (ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
p_qhd->iso_mult = ((ep_mps >> 11u) & 0x3u) + 1u;
|
||||
}
|
||||
|
||||
__chipidea_edpt_open(USB_OTG_DEV, ep_addr, ep_type);
|
||||
}
|
||||
|
||||
static bool chipidea_start_xfer(uint8_t busid, uint8_t ep_addr, uint8_t *buffer, uint32_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = ep_addr & 0x0f;
|
||||
uint8_t const dir = (ep_addr & 0x80) >> 7;
|
||||
uint8_t const ep_idx = 2 * epnum + dir;
|
||||
uint8_t qtd_num;
|
||||
uint8_t i;
|
||||
uint32_t xfer_len;
|
||||
dcd_qhd_t *p_qhd;
|
||||
dcd_qtd_t *p_qtd;
|
||||
dcd_qtd_t *first_p_qtd = NULL;
|
||||
dcd_qtd_t *prev_p_qtd = NULL;
|
||||
dcd_data_t *dcd_data;
|
||||
|
||||
dcd_data = g_chipidea_udc[busid].dcd_data;
|
||||
|
||||
if (epnum == 0) {
|
||||
/* follows UM Setup packet handling using setup lockout mechanism
|
||||
* wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
|
||||
*/
|
||||
while (USB_OTG_DEV->ENDPTSETUPSTAT & CHIPIDEA_BITSMASK(1, 0)) {
|
||||
}
|
||||
}
|
||||
|
||||
qtd_num = (total_bytes + 0x3fff) / 0x4000;
|
||||
if (qtd_num > QTD_COUNT_EACH_ENDPOINT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer != NULL) {
|
||||
buffer = (uint8_t *)buffer;
|
||||
}
|
||||
p_qhd = &dcd_data->qhd[ep_idx];
|
||||
i = 0;
|
||||
do {
|
||||
p_qtd = &dcd_data->qtd[ep_idx * QTD_COUNT_EACH_ENDPOINT + i];
|
||||
i++;
|
||||
|
||||
if (total_bytes > 0x4000) {
|
||||
xfer_len = 0x4000;
|
||||
total_bytes -= 0x4000;
|
||||
} else {
|
||||
xfer_len = total_bytes;
|
||||
total_bytes = 0;
|
||||
}
|
||||
|
||||
usb_qtd_init(p_qtd, (void *)buffer, xfer_len);
|
||||
if (total_bytes == 0) {
|
||||
p_qtd->int_on_complete = true;
|
||||
}
|
||||
buffer += xfer_len;
|
||||
|
||||
if (prev_p_qtd) {
|
||||
prev_p_qtd->next = (uint32_t)p_qtd;
|
||||
} else {
|
||||
first_p_qtd = p_qtd;
|
||||
}
|
||||
prev_p_qtd = p_qtd;
|
||||
} while (total_bytes > 0);
|
||||
|
||||
p_qhd->qtd_overlay.next = (uint32_t)first_p_qtd; /* link qtd to qhd */
|
||||
|
||||
chipidea_edpt_xfer(USB_OTG_DEV, ep_idx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_init(uint8_t busid)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_deinit(uint8_t busid)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_dc_init(uint8_t busid)
|
||||
{
|
||||
uint32_t int_mask;
|
||||
int_mask = (USB_USBINTR_UE_MASK | USB_USBINTR_UEE_MASK | USB_USBINTR_SLE_MASK |
|
||||
USB_USBINTR_PCE_MASK | USB_USBINTR_URE_MASK);
|
||||
|
||||
usb_dc_low_level_init(busid);
|
||||
|
||||
memset(&g_chipidea_udc[busid], 0, sizeof(struct chipidea_udc));
|
||||
g_chipidea_udc[busid].dcd_data = g_dcd_data[busid];
|
||||
memset(g_chipidea_udc[busid].dcd_data, 0, sizeof(dcd_data_t));
|
||||
|
||||
chipidea_init(USB_OTG_DEV);
|
||||
|
||||
/* Set endpoint list address */
|
||||
USB_OTG_DEV->ENDPTLISTADDR = ((uint32_t)g_chipidea_udc[busid].dcd_data->qhd) & USB_ENDPTLISTADDR_EPBASE_MASK;
|
||||
|
||||
/* Clear status */
|
||||
USB_OTG_DEV->USBSTS = USB_OTG_DEV->USBSTS;
|
||||
|
||||
/* Enable interrupt mask */
|
||||
USB_OTG_DEV->USBINTR |= int_mask;
|
||||
|
||||
/* Connect by enabling internal pull-up resistor on D+/D- */
|
||||
USB_OTG_DEV->USBCMD |= USB_USBCMD_RS_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_dc_deinit(uint8_t busid)
|
||||
{
|
||||
chipidea_deinit(USB_OTG_DEV);
|
||||
|
||||
for (uint32_t i = 0; i < CONFIG_USBDEV_EP_NUM; i++) {
|
||||
chipidea_edpt_close(USB_OTG_DEV, (i | 0x80));
|
||||
chipidea_edpt_close(USB_OTG_DEV, (i | 0x00));
|
||||
}
|
||||
|
||||
usb_dc_low_level_deinit(busid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr)
|
||||
{
|
||||
USB_OTG_DEV->DEVICEADDR = USB_DEVICEADDR_USBADR_SET(addr) | USB_DEVICEADDR_USBADRA_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_remote_wakeup(uint8_t busid)
|
||||
{
|
||||
if (!USB_PORTSC1_SUSP_GET(USB_OTG_DEV->PORTSC1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
USB_OTG_DEV->PORTSC1 |= USB_PORTSC1_FPR_MASK;
|
||||
while (USB_OTG_DEV->PORTSC1 & USB_PORTSC1_FPR_MASK) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
uint8_t speed;
|
||||
|
||||
speed = USB_PORTSC1_PSPD_GET(USB_OTG_DEV->PORTSC1);
|
||||
|
||||
if (speed == 0x00) {
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
if (speed == 0x01) {
|
||||
return USB_SPEED_LOW;
|
||||
}
|
||||
if (speed == 0x02) {
|
||||
return USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
/* Must not exceed max endpoint number */
|
||||
if (ep_idx >= CONFIG_USBDEV_EP_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
chipidea_edpt_open(busid, ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), ep->wMaxPacketSize);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].ep_enable = true;
|
||||
} else {
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].ep_enable = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_close(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].ep_enable = false;
|
||||
} else {
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].ep_enable = false;
|
||||
}
|
||||
|
||||
chipidea_edpt_close(USB_OTG_DEV, ep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
chipidea_edpt_stall(USB_OTG_DEV, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
chipidea_edpt_clear_stall(USB_OTG_DEV, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
*stalled = chipidea_edpt_check_stall(USB_OTG_DEV, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_write(uint8_t busid, 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_chipidea_udc[busid].in_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].xfer_len = data_len;
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
chipidea_start_xfer(busid, ep, (uint8_t *)data, data_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_read(uint8_t busid, 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_chipidea_udc[busid].out_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].xfer_len = data_len;
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
chipidea_start_xfer(busid, ep, data, data_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(uint8_t busid)
|
||||
{
|
||||
uint32_t int_status;
|
||||
uint32_t transfer_len;
|
||||
bool ep_cb_req;
|
||||
|
||||
/* Acknowledge handled interrupt */
|
||||
int_status = USB_OTG_DEV->USBSTS;
|
||||
int_status &= USB_OTG_DEV->USBINTR;
|
||||
USB_OTG_DEV->USBSTS = int_status;
|
||||
|
||||
if (int_status & intr_error) {
|
||||
USB_LOG_ERR("usbd intr error!\r\n");
|
||||
}
|
||||
|
||||
if (int_status & intr_reset) {
|
||||
g_chipidea_udc[busid].is_suspend = false;
|
||||
memset(g_chipidea_udc[busid].in_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
|
||||
memset(g_chipidea_udc[busid].out_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
|
||||
usbd_event_reset_handler(busid);
|
||||
chipidea_bus_reset(busid, 64);
|
||||
}
|
||||
|
||||
if (int_status & intr_suspend) {
|
||||
if (USB_PORTSC1_SUSP_GET(USB_OTG_DEV->PORTSC1)) {
|
||||
/* Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. */
|
||||
if (USB_DEVICEADDR_USBADR_GET(USB_OTG_DEV->DEVICEADDR)) {
|
||||
g_chipidea_udc[busid].is_suspend = true;
|
||||
usbd_event_suspend_handler(busid);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if (int_status & intr_port_change) {
|
||||
if (!USB_PORTSC1_CCS_GET(USB_OTG_DEV->PORTSC1)) {
|
||||
usbd_event_disconnect_handler(busid);
|
||||
} else {
|
||||
if (g_chipidea_udc[busid].is_suspend) {
|
||||
g_chipidea_udc[busid].is_suspend = false;
|
||||
usbd_event_resume_handler(busid);
|
||||
}
|
||||
usbd_event_connect_handler(busid);
|
||||
}
|
||||
}
|
||||
|
||||
if (int_status & intr_usb) {
|
||||
uint32_t const edpt_complete = USB_OTG_DEV->ENDPTCOMPLETE;
|
||||
USB_OTG_DEV->ENDPTCOMPLETE = edpt_complete;
|
||||
uint32_t edpt_setup_status = USB_OTG_DEV->ENDPTSETUPSTAT;
|
||||
|
||||
if (edpt_setup_status) {
|
||||
/*------------- Set up Received -------------*/
|
||||
USB_OTG_DEV->ENDPTSETUPSTAT = edpt_setup_status;
|
||||
dcd_qhd_t *qhd0 = chipidea_qhd_get(busid, 0);
|
||||
usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&qhd0->setup_request);
|
||||
}
|
||||
|
||||
if (edpt_complete) {
|
||||
for (uint8_t ep_idx = 0; ep_idx < (CONFIG_USBDEV_EP_NUM * 2); ep_idx++) {
|
||||
if (edpt_complete & (1 << ep_idx2bit(ep_idx))) {
|
||||
transfer_len = 0;
|
||||
ep_cb_req = true;
|
||||
|
||||
/* Failed QTD also get ENDPTCOMPLETE set */
|
||||
dcd_qtd_t *p_qtd = chipidea_qtd_get(busid, ep_idx);
|
||||
while (1) {
|
||||
if (p_qtd->halted || p_qtd->xact_err || p_qtd->buffer_err) {
|
||||
USB_LOG_ERR("usbd transfer error!\r\n");
|
||||
ep_cb_req = false;
|
||||
break;
|
||||
} else if (p_qtd->active) {
|
||||
ep_cb_req = false;
|
||||
break;
|
||||
} else {
|
||||
transfer_len += p_qtd->expected_bytes - p_qtd->total_bytes;
|
||||
}
|
||||
|
||||
if (p_qtd->next == 1) {
|
||||
break;
|
||||
} else {
|
||||
p_qtd = (dcd_qtd_t *)p_qtd->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (ep_cb_req) {
|
||||
uint8_t const ep_addr = (ep_idx / 2) | ((ep_idx & 0x01) ? 0x80 : 0);
|
||||
if (ep_addr & 0x80) {
|
||||
usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
|
||||
} else {
|
||||
usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
#include "usbd_core.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*! @brief USB controller ID */
|
||||
typedef enum _usb_controller_index {
|
||||
kUSB_ControllerKhci0 = 0U, /*!< KHCI 0U */
|
||||
kUSB_ControllerKhci1 = 1U, /*!< KHCI 1U, Currently, there are no platforms which have two KHCI IPs, this is reserved
|
||||
to be used in the future. */
|
||||
kUSB_ControllerEhci0 = 2U, /*!< EHCI 0U */
|
||||
kUSB_ControllerEhci1 = 3U, /*!< EHCI 1U */
|
||||
} usb_controller_index_t;
|
||||
|
||||
#define USB_DEVICE_CONFIG_EHCI 1
|
||||
|
||||
/* USB PHY condfiguration */
|
||||
#define BOARD_USB_PHY_D_CAL (0x04U)
|
||||
#define BOARD_USB_PHY_TXCAL45DP (0x07U)
|
||||
#define BOARD_USB_PHY_TXCAL45DM (0x07U)
|
||||
#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal0 frequency in Hz */
|
||||
|
||||
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
||||
#include "usb_phy.h"
|
||||
#endif
|
||||
|
||||
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U))
|
||||
void USB1_HS_IRQHandler(void)
|
||||
{
|
||||
extern void USBD_IRQHandler(uint8_t busid);
|
||||
USBD_IRQHandler(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void USB_ClockInit(void)
|
||||
{
|
||||
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
||||
usb_phy_config_struct_t phyConfig = {
|
||||
BOARD_USB_PHY_D_CAL,
|
||||
BOARD_USB_PHY_TXCAL45DP,
|
||||
BOARD_USB_PHY_TXCAL45DM,
|
||||
};
|
||||
#endif
|
||||
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
||||
SPC0->ACTIVE_VDELAY = 0x0500;
|
||||
/* Change the power DCDC to 1.8v (By deafult, DCDC is 1.8V), CORELDO to 1.1v (By deafult, CORELDO is 1.0V) */
|
||||
SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK;
|
||||
SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) |
|
||||
SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u);
|
||||
/* Wait until it is done */
|
||||
while (SPC0->SC & SPC_SC_BUSY_MASK)
|
||||
;
|
||||
if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) {
|
||||
SCG0->TRIM_LOCK = 0x5a5a0001U;
|
||||
SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
|
||||
/* wait LDO ready */
|
||||
while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK))
|
||||
;
|
||||
}
|
||||
SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK | SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK;
|
||||
SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK);
|
||||
/* xtal = 20 ~ 30MHz */
|
||||
SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT);
|
||||
SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK;
|
||||
while (1) {
|
||||
if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK | SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK;
|
||||
CLOCK_EnableClock(kCLOCK_UsbHs);
|
||||
CLOCK_EnableClock(kCLOCK_UsbHsPhy);
|
||||
CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, 24000000U);
|
||||
CLOCK_EnableUsbhsClock();
|
||||
USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &phyConfig);
|
||||
#endif
|
||||
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
|
||||
CLOCK_AttachClk(kCLK_48M_to_USB0);
|
||||
CLOCK_EnableClock(kCLOCK_Usb0Ram);
|
||||
CLOCK_EnableClock(kCLOCK_Usb0Fs);
|
||||
CLOCK_EnableUsbfsClock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void usb_dc_low_level_init(uint8_t busid)
|
||||
{
|
||||
USB_ClockInit();
|
||||
/* Install isr, set priority, and enable IRQ. */
|
||||
NVIC_SetPriority((IRQn_Type)USB1_HS_IRQn, 3);
|
||||
EnableIRQ((IRQn_Type)USB1_HS_IRQn);
|
||||
}
|
||||
|
||||
void usb_dc_low_level_deinit(uint8_t busid)
|
||||
{
|
||||
DisableIRQ((IRQn_Type)USB1_HS_IRQn);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
# Note
|
||||
|
||||
If you are using more than one port, all ip parameters must be the same(like fifo num, endpoint num, dma support and so on), otherwise give up using multi ports.
|
||||
|
||||
## Support Chip List
|
||||
|
||||
## STM32
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
|
||||
#endif
|
||||
|
||||
#define USBD_BASE (g_usbdev_bus[0].reg_base)
|
||||
#define USBD_BASE (g_usbdev_bus[busid].reg_base)
|
||||
|
||||
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(USBD_BASE))
|
||||
#define USB_OTG_DEV ((DWC2_DeviceTypeDef *)(USBD_BASE + USB_OTG_DEVICE_BASE))
|
||||
|
@ -119,9 +119,9 @@ USB_NOCACHE_RAM_SECTION struct dwc2_udc {
|
|||
__attribute__((aligned(32))) struct usb_setup_packet setup;
|
||||
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;
|
||||
} g_dwc2_udc[CONFIG_USBHOST_MAX_BUS];
|
||||
|
||||
static inline int dwc2_reset(void)
|
||||
static inline int dwc2_reset(uint8_t busid)
|
||||
{
|
||||
volatile uint32_t count = 0U;
|
||||
|
||||
|
@ -145,7 +145,7 @@ static inline int dwc2_reset(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int dwc2_core_init(void)
|
||||
static inline int dwc2_core_init(uint8_t busid)
|
||||
{
|
||||
int ret;
|
||||
#if defined(CONFIG_USB_HS)
|
||||
|
@ -156,18 +156,18 @@ static inline int dwc2_core_init(void)
|
|||
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
|
||||
|
||||
/* Reset after a PHY select */
|
||||
ret = dwc2_reset();
|
||||
ret = dwc2_reset(busid);
|
||||
#else
|
||||
/* Select FS Embedded PHY */
|
||||
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
|
||||
|
||||
/* Reset after a PHY select */
|
||||
ret = dwc2_reset();
|
||||
ret = dwc2_reset(busid);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void dwc2_set_mode(uint8_t mode)
|
||||
static inline void dwc2_set_mode(uint8_t busid, uint8_t mode)
|
||||
{
|
||||
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
|
||||
|
||||
|
@ -176,12 +176,22 @@ static inline void dwc2_set_mode(uint8_t mode)
|
|||
} else if (mode == USB_OTG_MODE_DEVICE) {
|
||||
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
|
||||
}
|
||||
|
||||
usbd_dwc2_delay_ms(50);
|
||||
}
|
||||
|
||||
static inline int dwc2_flush_rxfifo(void)
|
||||
static inline int dwc2_flush_rxfifo(uint8_t busid)
|
||||
{
|
||||
volatile uint32_t count = 0;
|
||||
volatile uint32_t count = 0U;
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
do {
|
||||
if (++count > 200000U) {
|
||||
return -1;
|
||||
}
|
||||
} while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
|
||||
count = 0;
|
||||
USB_OTG_GLB->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
|
||||
|
||||
do {
|
||||
|
@ -193,10 +203,18 @@ static inline int dwc2_flush_rxfifo(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int dwc2_flush_txfifo(uint32_t num)
|
||||
static inline int dwc2_flush_txfifo(uint8_t busid, uint32_t num)
|
||||
{
|
||||
volatile uint32_t count = 0U;
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
do {
|
||||
if (++count > 200000U) {
|
||||
return -1;
|
||||
}
|
||||
} while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
|
||||
count = 0;
|
||||
USB_OTG_GLB->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
|
||||
|
||||
do {
|
||||
|
@ -208,7 +226,7 @@ static inline int dwc2_flush_txfifo(uint32_t num)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dwc2_set_turnaroundtime(uint32_t hclk, uint8_t speed)
|
||||
static void dwc2_set_turnaroundtime(uint8_t busid, uint32_t hclk, uint8_t speed)
|
||||
{
|
||||
uint32_t UsbTrd;
|
||||
|
||||
|
@ -261,7 +279,7 @@ static void dwc2_set_turnaroundtime(uint32_t hclk, uint8_t speed)
|
|||
USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << USB_OTG_GUSBCFG_TRDT_Pos) & USB_OTG_GUSBCFG_TRDT);
|
||||
}
|
||||
|
||||
static void dwc2_set_txfifo(uint8_t fifo, uint16_t size)
|
||||
static void dwc2_set_txfifo(uint8_t busid, uint8_t fifo, uint16_t size)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t tx_offset;
|
||||
|
@ -293,7 +311,7 @@ static void dwc2_set_txfifo(uint8_t fifo, uint16_t size)
|
|||
USB_LOG_INFO("fifo%d size:%04x, offset:%04x\r\n", fifo, size, tx_offset);
|
||||
}
|
||||
|
||||
static uint8_t dwc2_get_devspeed(void)
|
||||
static uint8_t dwc2_get_devspeed(uint8_t busid)
|
||||
{
|
||||
uint8_t speed;
|
||||
uint32_t DevEnumSpeed = USB_OTG_DEV->DSTS & USB_OTG_DSTS_ENUMSPD;
|
||||
|
@ -310,7 +328,7 @@ static uint8_t dwc2_get_devspeed(void)
|
|||
return speed;
|
||||
}
|
||||
|
||||
static void dwc2_ep0_start_read_setup(uint8_t *psetup)
|
||||
static void dwc2_ep0_start_read_setup(uint8_t busid, uint8_t *psetup)
|
||||
{
|
||||
USB_OTG_OUTEP(0U)->DOEPTSIZ = 0U;
|
||||
USB_OTG_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
|
||||
|
@ -324,7 +342,7 @@ static void dwc2_ep0_start_read_setup(uint8_t *psetup)
|
|||
#endif
|
||||
}
|
||||
|
||||
void dwc2_ep_write(uint8_t ep_idx, uint8_t *src, uint16_t len)
|
||||
void dwc2_ep_write(uint8_t busid, uint8_t ep_idx, uint8_t *src, uint16_t len)
|
||||
{
|
||||
uint32_t *pSrc = (uint32_t *)src;
|
||||
uint32_t count32b, i;
|
||||
|
@ -336,7 +354,7 @@ void dwc2_ep_write(uint8_t ep_idx, uint8_t *src, uint16_t len)
|
|||
}
|
||||
}
|
||||
|
||||
void dwc2_ep_read(uint8_t *dest, uint16_t len)
|
||||
void dwc2_ep_read(uint8_t busid, uint8_t *dest, uint16_t len)
|
||||
{
|
||||
uint32_t *pDest = (uint32_t *)dest;
|
||||
uint32_t i;
|
||||
|
@ -348,33 +366,33 @@ void dwc2_ep_read(uint8_t *dest, uint16_t len)
|
|||
}
|
||||
}
|
||||
|
||||
static void dwc2_tx_fifo_empty_procecss(uint8_t ep_idx)
|
||||
static void dwc2_tx_fifo_empty_procecss(uint8_t busid, uint8_t ep_idx)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t len32b;
|
||||
uint32_t fifoemptymsk;
|
||||
|
||||
len = g_dwc2_udc.in_ep[ep_idx].xfer_len - g_dwc2_udc.in_ep[ep_idx].actual_xfer_len;
|
||||
if (len > g_dwc2_udc.in_ep[ep_idx].ep_mps) {
|
||||
len = g_dwc2_udc.in_ep[ep_idx].ep_mps;
|
||||
len = g_dwc2_udc[busid].in_ep[ep_idx].xfer_len - g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len;
|
||||
if (len > g_dwc2_udc[busid].in_ep[ep_idx].ep_mps) {
|
||||
len = g_dwc2_udc[busid].in_ep[ep_idx].ep_mps;
|
||||
}
|
||||
|
||||
len32b = (len + 3U) / 4U;
|
||||
|
||||
while (((USB_OTG_INEP(ep_idx)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
|
||||
(g_dwc2_udc.in_ep[ep_idx].actual_xfer_len < g_dwc2_udc.in_ep[ep_idx].xfer_len) && (g_dwc2_udc.in_ep[ep_idx].xfer_len != 0U)) {
|
||||
(g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len < g_dwc2_udc[busid].in_ep[ep_idx].xfer_len) && (g_dwc2_udc[busid].in_ep[ep_idx].xfer_len != 0U)) {
|
||||
/* Write the FIFO */
|
||||
len = g_dwc2_udc.in_ep[ep_idx].xfer_len - g_dwc2_udc.in_ep[ep_idx].actual_xfer_len;
|
||||
if (len > g_dwc2_udc.in_ep[ep_idx].ep_mps) {
|
||||
len = g_dwc2_udc.in_ep[ep_idx].ep_mps;
|
||||
len = g_dwc2_udc[busid].in_ep[ep_idx].xfer_len - g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len;
|
||||
if (len > g_dwc2_udc[busid].in_ep[ep_idx].ep_mps) {
|
||||
len = g_dwc2_udc[busid].in_ep[ep_idx].ep_mps;
|
||||
}
|
||||
|
||||
dwc2_ep_write(ep_idx, g_dwc2_udc.in_ep[ep_idx].xfer_buf, len);
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_buf += len;
|
||||
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len += len;
|
||||
dwc2_ep_write(busid, ep_idx, g_dwc2_udc[busid].in_ep[ep_idx].xfer_buf, len);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_buf += len;
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len += len;
|
||||
}
|
||||
|
||||
if (g_dwc2_udc.in_ep[ep_idx].xfer_len <= g_dwc2_udc.in_ep[ep_idx].actual_xfer_len) {
|
||||
if (g_dwc2_udc[busid].in_ep[ep_idx].xfer_len <= g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len) {
|
||||
fifoemptymsk = (uint32_t)(0x1UL << (ep_idx & 0x0f));
|
||||
USB_OTG_DEV->DIEPEMPMSK &= ~fifoemptymsk;
|
||||
}
|
||||
|
@ -384,7 +402,7 @@ static void dwc2_tx_fifo_empty_procecss(uint8_t ep_idx)
|
|||
* @brief dwc2_get_glb_intstatus: return the global USB interrupt status
|
||||
* @retval status
|
||||
*/
|
||||
static inline uint32_t dwc2_get_glb_intstatus(void)
|
||||
static inline uint32_t dwc2_get_glb_intstatus(uint8_t busid)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
|
@ -398,7 +416,7 @@ static inline uint32_t dwc2_get_glb_intstatus(void)
|
|||
* @brief dwc2_get_outeps_intstatus: return the USB device OUT endpoints interrupt status
|
||||
* @retval status
|
||||
*/
|
||||
static inline uint32_t dwc2_get_outeps_intstatus(void)
|
||||
static inline uint32_t dwc2_get_outeps_intstatus(uint8_t busid)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
|
@ -412,7 +430,7 @@ static inline uint32_t dwc2_get_outeps_intstatus(void)
|
|||
* @brief dwc2_get_ineps_intstatus: return the USB device IN endpoints interrupt status
|
||||
* @retval status
|
||||
*/
|
||||
static inline uint32_t dwc2_get_ineps_intstatus(void)
|
||||
static inline uint32_t dwc2_get_ineps_intstatus(uint8_t busid)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
|
@ -428,12 +446,13 @@ static inline uint32_t dwc2_get_ineps_intstatus(void)
|
|||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device OUT EP Interrupt register
|
||||
*/
|
||||
static inline uint32_t dwc2_get_outep_intstatus(uint8_t epnum)
|
||||
static inline uint32_t dwc2_get_outep_intstatus(uint8_t busid, uint8_t epnum)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USB_OTG_OUTEP((uint32_t)epnum)->DOEPINT;
|
||||
tmpreg &= USB_OTG_DEV->DOEPMSK;
|
||||
USB_OTG_OUTEP((uint32_t)epnum)->DOEPINT = tmpreg;
|
||||
tmpreg = tmpreg & USB_OTG_DEV->DOEPMSK;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
@ -444,26 +463,21 @@ static inline uint32_t dwc2_get_outep_intstatus(uint8_t epnum)
|
|||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device IN EP Interrupt register
|
||||
*/
|
||||
static inline uint32_t dwc2_get_inep_intstatus(uint8_t epnum)
|
||||
static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum)
|
||||
{
|
||||
uint32_t tmpreg, msk, emp;
|
||||
|
||||
msk = USB_OTG_DEV->DIEPMSK;
|
||||
emp = USB_OTG_DEV->DIEPEMPMSK;
|
||||
msk |= ((emp >> (epnum & 0x07)) & 0x1U) << 7;
|
||||
tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT & msk;
|
||||
|
||||
tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT;
|
||||
USB_OTG_INEP((uint32_t)epnum)->DIEPINT = tmpreg;
|
||||
tmpreg = tmpreg & msk;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_dc_init(uint8_t busid)
|
||||
{
|
||||
int ret;
|
||||
|
@ -473,9 +487,9 @@ int usb_dc_init(uint8_t busid)
|
|||
uint8_t endpoints;
|
||||
uint32_t fifo_num;
|
||||
|
||||
memset(&g_dwc2_udc, 0, sizeof(struct dwc2_udc));
|
||||
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
|
||||
|
||||
usb_dc_low_level_init();
|
||||
usb_dc_low_level_init(busid);
|
||||
|
||||
/*
|
||||
Full-Speed PHY Interface Type (FSPhyType)
|
||||
|
@ -526,14 +540,10 @@ int usb_dc_init(uint8_t busid)
|
|||
/* This is vendor register */
|
||||
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf(USBD_BASE);
|
||||
|
||||
ret = dwc2_core_init();
|
||||
ret = dwc2_core_init(busid);
|
||||
|
||||
/* 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;
|
||||
dwc2_set_mode(busid, USB_OTG_MODE_DEVICE);
|
||||
|
||||
for (uint8_t i = 0U; i < 15U; i++) {
|
||||
USB_OTG_GLB->DIEPTXF[i] = 0U;
|
||||
|
@ -567,6 +577,7 @@ int usb_dc_init(uint8_t busid)
|
|||
/* Enable interrupts matching to the Device mode ONLY */
|
||||
USB_OTG_GLB->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
|
||||
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT |
|
||||
USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM |
|
||||
USB_OTG_GINTMSK_IISOIXFRM | USB_OTG_GINTMSK_PXFRM_IISOOXFRM;
|
||||
|
||||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
|
@ -590,10 +601,10 @@ int usb_dc_init(uint8_t busid)
|
|||
|
||||
USB_OTG_GLB->GRXFSIZ = (CONFIG_USB_DWC2_RXALL_FIFO_SIZE);
|
||||
|
||||
dwc2_set_txfifo(0, CONFIG_USB_DWC2_TX0_FIFO_SIZE);
|
||||
dwc2_set_txfifo(1, CONFIG_USB_DWC2_TX1_FIFO_SIZE);
|
||||
dwc2_set_txfifo(2, CONFIG_USB_DWC2_TX2_FIFO_SIZE);
|
||||
dwc2_set_txfifo(3, CONFIG_USB_DWC2_TX3_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 0, CONFIG_USB_DWC2_TX0_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 1, CONFIG_USB_DWC2_TX1_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 2, CONFIG_USB_DWC2_TX2_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 3, CONFIG_USB_DWC2_TX3_FIFO_SIZE);
|
||||
|
||||
fifo_num = CONFIG_USB_DWC2_RXALL_FIFO_SIZE;
|
||||
fifo_num += CONFIG_USB_DWC2_TX0_FIFO_SIZE;
|
||||
|
@ -601,23 +612,23 @@ int usb_dc_init(uint8_t busid)
|
|||
fifo_num += CONFIG_USB_DWC2_TX2_FIFO_SIZE;
|
||||
fifo_num += CONFIG_USB_DWC2_TX3_FIFO_SIZE;
|
||||
#if CONFIG_USBDEV_EP_NUM > 4
|
||||
dwc2_set_txfifo(4, CONFIG_USB_DWC2_TX4_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 4, CONFIG_USB_DWC2_TX4_FIFO_SIZE);
|
||||
fifo_num += CONFIG_USB_DWC2_TX4_FIFO_SIZE;
|
||||
#endif
|
||||
#if CONFIG_USBDEV_EP_NUM > 5
|
||||
dwc2_set_txfifo(5, CONFIG_USB_DWC2_TX5_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 5, CONFIG_USB_DWC2_TX5_FIFO_SIZE);
|
||||
fifo_num += CONFIG_USB_DWC2_TX5_FIFO_SIZE;
|
||||
#endif
|
||||
#if CONFIG_USBDEV_EP_NUM > 6
|
||||
dwc2_set_txfifo(6, CONFIG_USB_DWC2_TX6_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 6, CONFIG_USB_DWC2_TX6_FIFO_SIZE);
|
||||
fifo_num += CONFIG_USB_DWC2_TX6_FIFO_SIZE;
|
||||
#endif
|
||||
#if CONFIG_USBDEV_EP_NUM > 7
|
||||
dwc2_set_txfifo(7, CONFIG_USB_DWC2_TX7_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 7, CONFIG_USB_DWC2_TX7_FIFO_SIZE);
|
||||
fifo_num += CONFIG_USB_DWC2_TX7_FIFO_SIZE;
|
||||
#endif
|
||||
#if CONFIG_USBDEV_EP_NUM > 8
|
||||
dwc2_set_txfifo(8, CONFIG_USB_DWC2_TX8_FIFO_SIZE);
|
||||
dwc2_set_txfifo(busid, 8, CONFIG_USB_DWC2_TX8_FIFO_SIZE);
|
||||
fifo_num += CONFIG_USB_DWC2_TX8_FIFO_SIZE;
|
||||
#endif
|
||||
|
||||
|
@ -634,8 +645,8 @@ int usb_dc_init(uint8_t busid)
|
|||
}
|
||||
}
|
||||
|
||||
ret = dwc2_flush_txfifo(0x10U);
|
||||
ret = dwc2_flush_rxfifo();
|
||||
ret = dwc2_flush_txfifo(busid, 0x10U);
|
||||
ret = dwc2_flush_rxfifo(busid);
|
||||
|
||||
USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
|
||||
USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_SDIS;
|
||||
|
@ -660,10 +671,10 @@ int usb_dc_deinit(uint8_t busid)
|
|||
USB_OTG_DEV->DAINTMSK = 0U;
|
||||
|
||||
/* Flush the FIFO */
|
||||
dwc2_flush_txfifo(0x10U);
|
||||
dwc2_flush_rxfifo();
|
||||
dwc2_flush_txfifo(busid, 0x10U);
|
||||
dwc2_flush_rxfifo(busid);
|
||||
|
||||
usb_dc_low_level_deinit();
|
||||
usb_dc_low_level_deinit(busid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -674,6 +685,17 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_remote_wakeup(uint8_t busid)
|
||||
{
|
||||
if (!(USB_OTG_DEV->DSTS & USB_OTG_DSTS_SUSPSTS)) {
|
||||
return -1;
|
||||
}
|
||||
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_RWUSIG;
|
||||
usbd_dwc2_delay_ms(10);
|
||||
USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
uint8_t speed;
|
||||
|
@ -701,8 +723,8 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
|||
}
|
||||
|
||||
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);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc[busid].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));
|
||||
|
||||
|
@ -724,8 +746,8 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
|||
return -2;
|
||||
}
|
||||
|
||||
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);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc[busid].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);
|
||||
|
||||
|
@ -735,7 +757,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
|||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
}
|
||||
dwc2_flush_txfifo(ep_idx);
|
||||
dwc2_flush_txfifo(busid, ep_idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -806,7 +828,7 @@ int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
|||
}
|
||||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
if (ep_idx == 0) {
|
||||
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -818,14 +840,14 @@ int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
|||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
|
||||
if ((g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
|
||||
(g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
|
||||
if ((g_dwc2_udc[busid].out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
|
||||
(g_dwc2_udc[busid].out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
|
||||
}
|
||||
} else {
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
|
||||
if ((g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
|
||||
(g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
|
||||
if ((g_dwc2_udc[busid].in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) ||
|
||||
(g_dwc2_udc[busid].in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) {
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
|
||||
}
|
||||
}
|
||||
|
@ -834,8 +856,20 @@ int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
|||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if(USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_STALL) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
} else {
|
||||
if(USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_STALL) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -860,9 +894,9 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
|
|||
return -4;
|
||||
}
|
||||
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len = 0;
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
|
@ -874,20 +908,20 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
|
|||
}
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len > g_dwc2_udc.in_ep[ep_idx].ep_mps) {
|
||||
data_len = g_dwc2_udc.in_ep[ep_idx].ep_mps;
|
||||
if (data_len > g_dwc2_udc[busid].in_ep[ep_idx].ep_mps) {
|
||||
data_len = g_dwc2_udc[busid].in_ep[ep_idx].ep_mps;
|
||||
}
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_len = data_len;
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & data_len);
|
||||
} else {
|
||||
pktcnt = (uint16_t)((data_len + g_dwc2_udc.in_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc.in_ep[ep_idx].ep_mps);
|
||||
pktcnt = (uint16_t)((data_len + g_dwc2_udc[busid].in_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc[busid].in_ep[ep_idx].ep_mps);
|
||||
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (pktcnt << 19));
|
||||
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & data_len);
|
||||
}
|
||||
|
||||
if (g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
if (g_dwc2_udc[busid].in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
|
||||
|
@ -933,28 +967,28 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
|
|||
return -4;
|
||||
}
|
||||
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc.out_ep[ep_idx].actual_xfer_len = 0;
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
if (data_len == 0) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19));
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & g_dwc2_udc.out_ep[ep_idx].ep_mps);
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & g_dwc2_udc[busid].out_ep[ep_idx].ep_mps);
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len > g_dwc2_udc.out_ep[ep_idx].ep_mps) {
|
||||
data_len = g_dwc2_udc.out_ep[ep_idx].ep_mps;
|
||||
if (data_len > g_dwc2_udc[busid].out_ep[ep_idx].ep_mps) {
|
||||
data_len = g_dwc2_udc[busid].out_ep[ep_idx].ep_mps;
|
||||
}
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = data_len;
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & data_len);
|
||||
} else {
|
||||
pktcnt = (uint16_t)((data_len + g_dwc2_udc.out_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc.out_ep[ep_idx].ep_mps);
|
||||
pktcnt = (uint16_t)((data_len + g_dwc2_udc[busid].out_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc[busid].out_ep[ep_idx].ep_mps);
|
||||
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19));
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & data_len);
|
||||
|
@ -963,7 +997,7 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
|
|||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
|
||||
#endif
|
||||
if (g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
if (g_dwc2_udc[busid].out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
|
||||
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
|
||||
|
@ -979,7 +1013,7 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
|
|||
void USBD_IRQHandler(uint8_t busid)
|
||||
{
|
||||
uint32_t gint_status, temp, ep_idx, ep_intr, epint, read_count, daintmask;
|
||||
gint_status = dwc2_get_glb_intstatus();
|
||||
gint_status = dwc2_get_glb_intstatus(busid);
|
||||
|
||||
if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_DEVICE) {
|
||||
/* Avoid spurious interrupt */
|
||||
|
@ -998,12 +1032,12 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) {
|
||||
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
if (read_count != 0) {
|
||||
dwc2_ep_read(g_dwc2_udc.out_ep[ep_idx].xfer_buf, read_count);
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_buf += read_count;
|
||||
dwc2_ep_read(busid, g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, read_count);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf += read_count;
|
||||
}
|
||||
} else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) {
|
||||
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
dwc2_ep_read((uint8_t *)&g_dwc2_udc.setup, read_count);
|
||||
dwc2_ep_read(busid, (uint8_t *)&g_dwc2_udc[busid].setup, read_count);
|
||||
} else {
|
||||
/* ... */
|
||||
}
|
||||
|
@ -1012,32 +1046,30 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
#endif
|
||||
if (gint_status & USB_OTG_GINTSTS_OEPINT) {
|
||||
ep_idx = 0;
|
||||
ep_intr = dwc2_get_outeps_intstatus();
|
||||
ep_intr = dwc2_get_outeps_intstatus(busid);
|
||||
while (ep_intr != 0U) {
|
||||
if ((ep_intr & 0x1U) != 0U) {
|
||||
epint = dwc2_get_outep_intstatus(ep_idx);
|
||||
uint32_t DoepintReg = USB_OTG_OUTEP(ep_idx)->DOEPINT;
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPINT = DoepintReg;
|
||||
epint = dwc2_get_outep_intstatus(busid, ep_idx);
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) {
|
||||
if (ep_idx == 0) {
|
||||
if (g_dwc2_udc.out_ep[ep_idx].xfer_len == 0) {
|
||||
if (g_dwc2_udc[busid].out_ep[ep_idx].xfer_len == 0) {
|
||||
/* Out status, start reading setup */
|
||||
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
} else {
|
||||
g_dwc2_udc.out_ep[ep_idx].actual_xfer_len = g_dwc2_udc.out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_out_complete_handler(0, 0x00, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_out_complete_handler(busid, 0x00, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
} else {
|
||||
g_dwc2_udc.out_ep[ep_idx].actual_xfer_len = g_dwc2_udc.out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc.out_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_out_complete_handler(0, ep_idx, g_dwc2_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_out_complete_handler(busid, ep_idx, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) {
|
||||
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_dwc2_udc.setup);
|
||||
usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
}
|
||||
}
|
||||
ep_intr >>= 1U;
|
||||
|
@ -1046,34 +1078,32 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
}
|
||||
if (gint_status & USB_OTG_GINTSTS_IEPINT) {
|
||||
ep_idx = 0U;
|
||||
ep_intr = dwc2_get_ineps_intstatus();
|
||||
ep_intr = dwc2_get_ineps_intstatus(busid);
|
||||
while (ep_intr != 0U) {
|
||||
if ((ep_intr & 0x1U) != 0U) {
|
||||
epint = dwc2_get_inep_intstatus(ep_idx);
|
||||
uint32_t DiepintReg = USB_OTG_INEP(ep_idx)->DIEPINT;
|
||||
USB_OTG_INEP(ep_idx)->DIEPINT = DiepintReg;
|
||||
epint = dwc2_get_inep_intstatus(busid, ep_idx);
|
||||
|
||||
if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) {
|
||||
if (ep_idx == 0) {
|
||||
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len = g_dwc2_udc.in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(0, 0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(busid, 0x80, g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len);
|
||||
|
||||
if (g_dwc2_udc.setup.wLength && ((g_dwc2_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
if (g_dwc2_udc[busid].setup.wLength && ((g_dwc2_udc[busid].setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
/* In status, start reading setup */
|
||||
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
|
||||
} else if (g_dwc2_udc.setup.wLength == 0) {
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
} else if (g_dwc2_udc[busid].setup.wLength == 0) {
|
||||
/* In status, start reading setup */
|
||||
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
}
|
||||
} else {
|
||||
g_dwc2_udc.in_ep[ep_idx].actual_xfer_len = g_dwc2_udc.in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_dwc2_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].in_ep[ep_idx].xfer_len - ((USB_OTG_INEP(ep_idx)->DIEPTSIZ) & USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(busid, ep_idx | 0x80, g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
|
||||
dwc2_tx_fifo_empty_procecss(ep_idx);
|
||||
dwc2_tx_fifo_empty_procecss(busid, ep_idx);
|
||||
}
|
||||
}
|
||||
ep_intr >>= 1U;
|
||||
|
@ -1084,8 +1114,8 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_USBRST;
|
||||
USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
|
||||
dwc2_flush_txfifo(0x10U);
|
||||
dwc2_flush_rxfifo();
|
||||
dwc2_flush_txfifo(busid, 0x10U);
|
||||
dwc2_flush_rxfifo(busid);
|
||||
|
||||
for (uint8_t i = 0U; i < CONFIG_USBDEV_EP_NUM; i++) {
|
||||
if (i == 0U) {
|
||||
|
@ -1116,14 +1146,14 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
|
||||
USB_OTG_DEV->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
|
||||
|
||||
memset(&g_dwc2_udc, 0, sizeof(struct dwc2_udc));
|
||||
usbd_event_reset_handler(0);
|
||||
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
|
||||
usbd_event_reset_handler(busid);
|
||||
/* Start reading setup */
|
||||
dwc2_ep0_start_read_setup((uint8_t *)&g_dwc2_udc.setup);
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
}
|
||||
if (gint_status & USB_OTG_GINTSTS_ENUMDNE) {
|
||||
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE;
|
||||
dwc2_set_turnaroundtime(SystemCoreClock, dwc2_get_devspeed());
|
||||
dwc2_set_turnaroundtime(busid, SystemCoreClock, dwc2_get_devspeed(busid));
|
||||
|
||||
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK;
|
||||
}
|
||||
|
@ -1132,7 +1162,7 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
daintmask >>= 16;
|
||||
|
||||
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))
|
||||
if ((BIT(ep_idx) & ~daintmask) || (g_dwc2_udc[busid].out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
|
||||
continue;
|
||||
if (!(USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP))
|
||||
continue;
|
||||
|
@ -1154,7 +1184,7 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
daintmask >>= 16;
|
||||
|
||||
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))
|
||||
if (((BIT(ep_idx) & ~daintmask)) || (g_dwc2_udc[busid].in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS))
|
||||
continue;
|
||||
|
||||
if (!(USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP))
|
||||
|
@ -1176,9 +1206,11 @@ void USBD_IRQHandler(uint8_t busid)
|
|||
}
|
||||
if (gint_status & USB_OTG_GINTSTS_USBSUSP) {
|
||||
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_USBSUSP;
|
||||
usbd_event_suspend_handler(busid);
|
||||
}
|
||||
if (gint_status & USB_OTG_GINTSTS_WKUINT) {
|
||||
USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_WKUINT;
|
||||
usbd_event_resume_handler(busid);
|
||||
}
|
||||
if (gint_status & USB_OTG_GINTSTS_OTGINT) {
|
||||
temp = USB_OTG_GLB->GOTGINT;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue