Compare commits
87 Commits
release/v1
...
v1.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0fac3260a | ||
|
|
e6fde5efab | ||
|
|
0487af6900 | ||
|
|
be2880a7e8 | ||
|
|
97e2a38b4a | ||
|
|
a139a70782 | ||
|
|
cb6a0c2ad6 | ||
|
|
bacacdb32c | ||
|
|
0323ffb424 | ||
|
|
89e93f6c93 | ||
|
|
1deab668ef | ||
|
|
fbe2e3f8a3 | ||
|
|
d03dfe43ca | ||
|
|
e42e99e975 | ||
|
|
8a7979378d | ||
|
|
a8a5d95f8f | ||
|
|
02ac1db3ff | ||
|
|
0d561ea313 | ||
|
|
e603389638 | ||
|
|
b932cc5803 | ||
|
|
5f43dc8662 | ||
|
|
f5ce56990c | ||
|
|
f517adcf6d | ||
|
|
2a563dc41f | ||
|
|
b045a1d490 | ||
|
|
563fbf58e1 | ||
|
|
8435f1af32 | ||
|
|
2726e2e7b6 | ||
|
|
e8b22163bb | ||
|
|
35da8d6747 | ||
|
|
43dc854b4d | ||
|
|
f0fc75179e | ||
|
|
f1e7043384 | ||
|
|
e4954d4194 | ||
|
|
07c6c296ed | ||
|
|
500367dd82 | ||
|
|
1efc29be5f | ||
|
|
143a5ce3fd | ||
|
|
b171b28a75 | ||
|
|
668e414917 | ||
|
|
03f8711b20 | ||
|
|
393756f111 | ||
|
|
4a252c3f73 | ||
|
|
4b2000b405 | ||
|
|
9720eb2f76 | ||
|
|
68badf6f4c | ||
|
|
907d23871e | ||
|
|
70944027c5 | ||
|
|
a41da8928e | ||
|
|
bbcc767465 | ||
|
|
72e8eb7d84 | ||
|
|
18d9c21553 | ||
|
|
cbd6955bde | ||
|
|
b4bbe69d12 | ||
|
|
e1cbccc58a | ||
|
|
dfc90da28a | ||
|
|
8451bc64bb | ||
|
|
3fc30cd058 | ||
|
|
e95387c558 | ||
|
|
35a76f58bb | ||
|
|
564d568732 | ||
|
|
9394f1f8d6 | ||
|
|
bef45dc360 | ||
|
|
50b62c946d | ||
|
|
b399ff63ce | ||
|
|
4c4ee7f003 | ||
|
|
1c2fd3407a | ||
|
|
1927566dfc | ||
|
|
b7556b2ddc | ||
|
|
f1058c5e1a | ||
|
|
643578e5be | ||
|
|
390e24fbe5 | ||
|
|
ba02a48873 | ||
|
|
c766cbe91e | ||
|
|
9dd52fddf0 | ||
|
|
9c14ea19a9 | ||
|
|
218fa8e85d | ||
|
|
eb147d7276 | ||
|
|
c0bfbf7952 | ||
|
|
1a9c1481f4 | ||
|
|
3d3c6bb5a2 | ||
|
|
a942ec85a8 | ||
|
|
a4a06573ea | ||
|
|
7fab3c29f0 | ||
|
|
4f3a3f496e | ||
|
|
e4b56cee89 | ||
|
|
53114c0f16 |
150
CMakeLists.txt
Normal file
150
CMakeLists.txt
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
if(BL_SDK_BASE)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE 1)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_DCD "bl")
|
||||||
|
|
||||||
|
set(CONFIG_CHERRYUSB_HOST 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
|
||||||
|
set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_HCD "ehci_bouffalo")
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||||
|
|
||||||
|
sdk_generate_library(cherryusb)
|
||||||
|
sdk_add_include_directories(${cherryusb_incs})
|
||||||
|
sdk_library_add_sources(${cherryusb_srcs})
|
||||||
|
|
||||||
|
sdk_library_add_sources(platform/none/usbh_lwip.c)
|
||||||
|
|
||||||
|
elseif(HPM_SDK_BASE)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||||
|
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_BL616 1)
|
||||||
|
set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_HCD "ehci_hpm")
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||||
|
|
||||||
|
sdk_inc(${cherryusb_incs})
|
||||||
|
sdk_src(${cherryusb_srcs})
|
||||||
|
|
||||||
|
sdk_src(platform/none/usbh_lwip.c)
|
||||||
|
|
||||||
|
elseif(ESP_PLATFORM)
|
||||||
|
|
||||||
|
set(CONFIG_CHERRYUSB_DEVICE_DCD "dwc2_esp")
|
||||||
|
set(CONFIG_CHERRYUSB_HOST_HCD "dwc2_esp")
|
||||||
|
set(CONFIG_CHERRYUSB_OSAL "idf")
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||||
|
|
||||||
|
set(ldfragments "osal/idf/linker.lf")
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_ECM OR CONFIG_CHERRYUSB_HOST_CDC_RNDIS OR CONFIG_CHERRYUSB_HOST_CDC_NCM
|
||||||
|
OR CONFIG_CHERRYUSB_HOST_ASIX OR CONFIG_CHERRYUSB_HOST_RTL8152 OR CONFIG_CHERRYUSB_HOST_BL616)
|
||||||
|
list(APPEND cherryusb_srcs platform/none/usbh_lwip.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${cherryusb_srcs}
|
||||||
|
INCLUDE_DIRS ${cherryusb_incs}
|
||||||
|
PRIV_REQUIRES usb
|
||||||
|
LDFRAGMENTS ${ldfragments}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB_HOST)
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "osal/idf/usbh_class_info.ld")
|
||||||
|
|
||||||
|
# 强制链接器不删除符号
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_acm_class_info")
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_data_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_HID)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u hid_custom_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u msc_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ecm_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rndis_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ncm_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_ctrl_class_info")
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_streaming_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_ctrl_intf_class_info")
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_streaming_intf_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||||
|
if(CONFIG_USBHOST_BLUETOOTH_HCI_H4)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_h4_nrf_class_info")
|
||||||
|
else()
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_class_info")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_ASIX)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u asix_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_RTL8152)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rtl8152_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_FTDI)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ftdi_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CH34X)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ch34x_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_CP210X)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cp210x_class_info")
|
||||||
|
endif()
|
||||||
|
if(CONFIG_CHERRYUSB_HOST_PL2303)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u pl2303_class_info")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_CHERRYUSB)
|
||||||
|
set_source_files_properties("class/audio/usbd_audio.c"
|
||||||
|
PROPERTIES COMPILE_FLAGS
|
||||||
|
-Wno-maybe-uninitialized)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Kconfig file for CherryUSB
|
# Kconfig file for CherryUSB
|
||||||
menuconfig CHERRYUSB
|
menuconfig CHERRYUSB
|
||||||
bool "Using CherryUSB"
|
bool "CherryUSB Configuration"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
if CHERRYUSB
|
if CHERRYUSB
|
||||||
@@ -48,6 +48,10 @@ if CHERRYUSB
|
|||||||
bool "musb_bk"
|
bool "musb_bk"
|
||||||
config CHERRYUSB_DEVICE_MUSB_CUSTOM
|
config CHERRYUSB_DEVICE_MUSB_CUSTOM
|
||||||
bool "musb_custom"
|
bool "musb_custom"
|
||||||
|
config CHERRYUSB_DEVICE_CHIPIDEA_MCX
|
||||||
|
bool "chipidea_mcx"
|
||||||
|
config CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
|
||||||
|
bool "chipidea_custom"
|
||||||
config CHERRYUSB_DEVICE_BL
|
config CHERRYUSB_DEVICE_BL
|
||||||
bool "bouffalo"
|
bool "bouffalo"
|
||||||
config CHERRYUSB_DEVICE_HPM
|
config CHERRYUSB_DEVICE_HPM
|
||||||
@@ -105,9 +109,14 @@ if CHERRYUSB
|
|||||||
prompt "Enable usb dfu device"
|
prompt "Enable usb dfu device"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config CHERRYUSB_DEVICE_ADB
|
||||||
|
bool
|
||||||
|
prompt "Enable usb adb device"
|
||||||
|
default n
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Select usb device template"
|
prompt "Select usb device template"
|
||||||
default CHERRYUSB_DEVICE_TEMPLATE
|
default CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||||
config CHERRYUSB_DEVICE_TEMPLATE_NONE
|
config CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||||
bool "none (Implement it yourself)"
|
bool "none (Implement it yourself)"
|
||||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
|
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
|
||||||
@@ -162,10 +171,12 @@ if CHERRYUSB
|
|||||||
bool "ehci_hpm"
|
bool "ehci_hpm"
|
||||||
config CHERRYUSB_HOST_EHCI_AIC
|
config CHERRYUSB_HOST_EHCI_AIC
|
||||||
bool "ehci_aic"
|
bool "ehci_aic"
|
||||||
config CHERRYUSB_HOST_EHCI_NUVOTON_NUC980
|
config CHERRYUSB_HOST_EHCI_MCX
|
||||||
bool "ehci_nuvoton_nuc980"
|
bool "ehci_mcx"
|
||||||
config CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0
|
config CHERRYUSB_HOST_EHCI_NUC980
|
||||||
bool "ehci_nuvoton_ma35d0"
|
bool "ehci_nuc980"
|
||||||
|
config CHERRYUSB_HOST_EHCI_MA35D0
|
||||||
|
bool "ehci_ma35d0"
|
||||||
config CHERRYUSB_HOST_EHCI_CUSTOM
|
config CHERRYUSB_HOST_EHCI_CUSTOM
|
||||||
bool "ehci_custom"
|
bool "ehci_custom"
|
||||||
config CHERRYUSB_HOST_DWC2_ST
|
config CHERRYUSB_HOST_DWC2_ST
|
||||||
@@ -186,7 +197,9 @@ if CHERRYUSB
|
|||||||
bool "musb_custom"
|
bool "musb_custom"
|
||||||
config CHERRYUSB_HOST_PUSB2
|
config CHERRYUSB_HOST_PUSB2
|
||||||
bool "pusb2"
|
bool "pusb2"
|
||||||
config CHERRYUSB_HOST_XHCI
|
config CHERRYUSB_HOST_XHCI_PHYTIUM
|
||||||
|
bool "xhci_phytium"
|
||||||
|
config CHERRYUSB_HOST_XHCI_CUSTOM
|
||||||
bool "xhci"
|
bool "xhci"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
39
README.md
39
README.md
@@ -17,7 +17,7 @@ In order to make it easier for users to learn USB basics, enumeration, driver lo
|
|||||||
- Class-drivers and porting-drivers are templating and simplification
|
- Class-drivers and porting-drivers are templating and simplification
|
||||||
- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
|
- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
|
||||||
|
|
||||||
### Easy to use USB
|
### Easy to use USB
|
||||||
|
|
||||||
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
|
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
|
||||||
|
|
||||||
@@ -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
|
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
|
||||||
- Subcontracting function is handled in interrupt
|
- Subcontracting function is handled in interrupt
|
||||||
|
|
||||||
## Directoy Structure
|
## Directory Structure
|
||||||
|
|
||||||
| Directory | Description |
|
| Directory | Description |
|
||||||
|:-------------:|:---------------------------:|
|
|:-------------:|:---------------------------:|
|
||||||
@@ -65,15 +65,17 @@ CherryUSB Device Stack has the following functions:
|
|||||||
- Support Device Firmware Upgrade CLASS (DFU)
|
- Support Device Firmware Upgrade CLASS (DFU)
|
||||||
- Support USB MIDI CLASS (MIDI)
|
- Support USB MIDI CLASS (MIDI)
|
||||||
- Support Remote NDIS (RNDIS)
|
- Support Remote NDIS (RNDIS)
|
||||||
- Support WINUSB1.0、WINUSB2.0(with BOS)
|
- Support WINUSB1.0、WINUSB2.0、WEBUSB、BOS
|
||||||
- Support Vendor class
|
- Support Vendor class
|
||||||
|
- Support UF2
|
||||||
|
- Support Android Debug Bridge (Only support shell)
|
||||||
- Support multi device with the same USB IP
|
- Support multi device with the same USB IP
|
||||||
|
|
||||||
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
||||||
|
|
||||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
| 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_cdc.c | 392 | 0 | 0 | 0 |
|
||||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||||
|usbd_hid.c | 364 | 0 | 0 | 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:
|
CherryUSB Host Stack has the following functions:
|
||||||
|
|
||||||
|
- Support low speed, full speed, high speed and super speed devices
|
||||||
- Automatic loading of supported Class drivers
|
- Automatic loading of supported Class drivers
|
||||||
- Support blocking transfers and asynchronous transfers
|
- Support blocking transfers and asynchronous transfers
|
||||||
- Support Composite Device
|
- Support Composite Device
|
||||||
@@ -98,7 +101,7 @@ CherryUSB Host Stack has the following functions:
|
|||||||
- Support USB Audio CLASS (UAC1.0)
|
- Support USB Audio CLASS (UAC1.0)
|
||||||
- Support Remote NDIS (RNDIS)
|
- Support Remote NDIS (RNDIS)
|
||||||
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
|
- Support 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 USB modeswitch
|
||||||
- Support multi host with the same USB IP
|
- 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) |
|
| 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_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_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
|usbh_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 | √ |
|
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||||
|
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||||
| DWC3(synopsys) | DWC3 | 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 |
|
|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 | 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 |
|
|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 |
|
|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 |
|
|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 |
|
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|
|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 |
|
|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 |
|
|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
|
## Commercial Support
|
||||||
|
|
||||||
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
|
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
|
||||||
@@ -198,4 +211,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
|
|||||||
|
|
||||||
Thanks to the following companies for their support (in no particular order).
|
Thanks to the following companies for their support (in no particular order).
|
||||||
|
|
||||||
<img src="docs/assets/bouffalolab.jpg" width="100" height="100"/> <img src="docs/assets/hpmicro.jpg" width="100" height="100" /> <img src="docs/assets/eastsoft.jpg" width="100" height="100" /> <img src="docs/assets/rtthread.jpg" width="100" height="100" /> <img src="docs/assets/sophgo.jpg" width="100" height="100" /> <img src="docs/assets/phytium.jpg" width="100" height="100" /> <img src="docs/assets/thead.jpg" width="100" height="100" /> <img src="docs/assets/nuvoton.jpg" width="100" height="100" /> <img src="docs/assets/artinchip.jpg" width="100" height="100" /> <img src="docs/assets/bekencorp.jpg" width="100" height="100" />
|
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" />
|
||||||
|
|||||||
37
README_zh.md
37
README_zh.md
@@ -65,15 +65,17 @@ CherryUSB Device 协议栈当前实现以下功能:
|
|||||||
- 支持 Device Firmware Upgrade CLASS (DFU)
|
- 支持 Device Firmware Upgrade CLASS (DFU)
|
||||||
- 支持 USB MIDI CLASS (MIDI)
|
- 支持 USB MIDI CLASS (MIDI)
|
||||||
- 支持 Remote NDIS (RNDIS)
|
- 支持 Remote NDIS (RNDIS)
|
||||||
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
|
||||||
- 支持 Vendor 类 class
|
- 支持 Vendor 类 class
|
||||||
|
- 支持 UF2
|
||||||
|
- 支持 Android Debug Bridge (Only support shell)
|
||||||
- 支持相同 USB IP 的多从机
|
- 支持相同 USB IP 的多从机
|
||||||
|
|
||||||
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||||
|
|
||||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
| 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_cdc.c | 392 | 0 | 0 | 0 |
|
||||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||||
@@ -87,6 +89,7 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了
|
|||||||
|
|
||||||
CherryUSB Host 协议栈当前实现以下功能:
|
CherryUSB Host 协议栈当前实现以下功能:
|
||||||
|
|
||||||
|
- 支持 low speed, full speed, high speed 和 super speed 设备
|
||||||
- 自动加载支持的Class 驱动
|
- 自动加载支持的Class 驱动
|
||||||
- 支持阻塞式传输和异步传输
|
- 支持阻塞式传输和异步传输
|
||||||
- 支持复合设备
|
- 支持复合设备
|
||||||
@@ -98,7 +101,7 @@ CherryUSB Host 协议栈当前实现以下功能:
|
|||||||
- Support USB Audio CLASS (UAC1.0)
|
- Support USB Audio CLASS (UAC1.0)
|
||||||
- 支持 Remote NDIS (RNDIS)
|
- 支持 Remote NDIS (RNDIS)
|
||||||
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
|
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
|
||||||
- 支持 Vendor 类 class
|
- 支持 Vendor 类 class (serial, net, wifi)
|
||||||
- 支持 USB modeswitch
|
- 支持 USB modeswitch
|
||||||
- 支持相同 USB IP 的多主机
|
- 支持相同 USB IP 的多主机
|
||||||
|
|
||||||
@@ -108,7 +111,7 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
|||||||
|
|
||||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
| 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_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_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||||
@@ -152,6 +155,7 @@ x 受以下宏影响:
|
|||||||
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||||
|
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||||
| DWC3(synopsys) | DWC3 | 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 |
|
|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 | 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 |
|
|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 |
|
|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 |
|
|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 |
|
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
|NXP | mcx | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with Essemi |
|
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | the same with ST |
|
|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 |
|
|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 |
|
|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 。
|
||||||
|
|
||||||
## 联系
|
## 联系
|
||||||
|
|
||||||
@@ -200,4 +213,4 @@ CherryUSB 微信群:与我联系后邀请加入
|
|||||||
|
|
||||||
感谢以下企业支持(顺序不分先后)。
|
感谢以下企业支持(顺序不分先后)。
|
||||||
|
|
||||||
<img src="docs/assets/bouffalolab.jpg" width="100" height="100"/> <img src="docs/assets/hpmicro.jpg" width="100" height="100" /> <img src="docs/assets/eastsoft.jpg" width="100" height="100" /> <img src="docs/assets/rtthread.jpg" width="100" height="100" /> <img src="docs/assets/sophgo.jpg" width="100" height="100" /> <img src="docs/assets/phytium.jpg" width="100" height="100" /> <img src="docs/assets/thead.jpg" width="100" height="100" /> <img src="docs/assets/nuvoton.jpg" width="100" height="100" /> <img src="docs/assets/artinchip.jpg" width="100" height="100" /> <img src="docs/assets/bekencorp.jpg" width="100" height="100" />
|
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" />
|
||||||
|
|||||||
46
SConscript
46
SConscript
@@ -15,6 +15,8 @@ path += [cwd + '/class/vendor/net']
|
|||||||
path += [cwd + '/class/vendor/serial']
|
path += [cwd + '/class/vendor/serial']
|
||||||
src = []
|
src = []
|
||||||
|
|
||||||
|
LIBS = []
|
||||||
|
LIBPATH = []
|
||||||
CPPDEFINES = []
|
CPPDEFINES = []
|
||||||
|
|
||||||
# USB DEVICE
|
# USB DEVICE
|
||||||
@@ -56,6 +58,9 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
|||||||
src += Glob('port/musb/usb_glue_bk.c')
|
src += Glob('port/musb/usb_glue_bk.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
|
||||||
src += Glob('port/musb/usb_dc_musb.c')
|
src += Glob('port/musb/usb_dc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
|
||||||
|
src += Glob('port/chipidea/usb_dc_chipidea.c')
|
||||||
|
src += Glob('port/chipidea/usb_glue_mcx.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']):
|
||||||
src += Glob('port/bouffalolab/usb_dc_bl.c')
|
src += Glob('port/bouffalolab/usb_dc_bl.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
||||||
@@ -68,9 +73,18 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
|||||||
src += Glob('port/ch32/usb_dc_usbhs.c')
|
src += Glob('port/ch32/usb_dc_usbhs.c')
|
||||||
else:
|
else:
|
||||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||||
|
if GetDepend(['PKG_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(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
|
||||||
src += Glob('class/cdc/usbd_cdc.c')
|
src += Glob('class/cdc/usbd_cdc_acm.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
||||||
src += Glob('class/hid/usbd_hid.c')
|
src += Glob('class/hid/usbd_hid.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
|
||||||
@@ -140,10 +154,14 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
|||||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
src += Glob('port/ehci/usb_glue_aic.c')
|
src += Glob('port/ehci/usb_glue_aic.c')
|
||||||
src += Glob('port/ohci/usb_hc_ohci.c')
|
src += Glob('port/ohci/usb_hc_ohci.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980']):
|
if GetDepend(['PKG_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(['PKG_CHERRYUSB_HOST_EHCI_NUC980']):
|
||||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
src += Glob('port/ehci/usb_glue_nuc980.c')
|
src += Glob('port/ehci/usb_glue_nuc980.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_MA35D0']):
|
||||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||||
src += Glob('port/ehci/usb_glue_ma35d0.c')
|
src += Glob('port/ehci/usb_glue_ma35d0.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
|
||||||
@@ -169,6 +187,26 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
|||||||
src += Glob('port/musb/usb_glue_bk.c')
|
src += Glob('port/musb/usb_glue_bk.c')
|
||||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
|
||||||
src += Glob('port/musb/usb_hc_musb.c')
|
src += Glob('port/musb/usb_hc_musb.c')
|
||||||
|
if GetDepend(['PKG_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(['PKG_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(['PKG_CHERRYUSB_HOST_CDC_ACM']):
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']):
|
||||||
src += Glob('class/cdc/usbh_cdc_acm.c')
|
src += Glob('class/cdc/usbh_cdc_acm.c')
|
||||||
@@ -217,7 +255,7 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
|
|||||||
src += Glob('platform/rtthread/usb_msh.c')
|
src += Glob('platform/rtthread/usb_msh.c')
|
||||||
src += Glob('platform/rtthread/usb_check.c')
|
src += Glob('platform/rtthread/usb_check.c')
|
||||||
|
|
||||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], LIBS = LIBS, LIBPATH=LIBPATH, CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||||
|
|
||||||
Return('group')
|
Return('group')
|
||||||
|
|
||||||
|
|||||||
4
VERSION
4
VERSION
@@ -1,5 +1,5 @@
|
|||||||
VERSION_MAJOR = 1
|
VERSION_MAJOR = 1
|
||||||
VERSION_MINOR = 3
|
VERSION_MINOR = 4
|
||||||
PATCHLEVEL = 1
|
PATCHLEVEL = 0
|
||||||
VERSION_TWEAK = 0
|
VERSION_TWEAK = 0
|
||||||
EXTRAVERSION = 0
|
EXTRAVERSION = 0
|
||||||
|
|||||||
@@ -36,14 +36,16 @@ ${CMAKE_CURRENT_LIST_DIR}/class/audio
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/class/video
|
${CMAKE_CURRENT_LIST_DIR}/class/video
|
||||||
${CMAKE_CURRENT_LIST_DIR}/class/wireless
|
${CMAKE_CURRENT_LIST_DIR}/class/wireless
|
||||||
${CMAKE_CURRENT_LIST_DIR}/class/midi
|
${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/net
|
||||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
|
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_CHERRYUSB_DEVICE)
|
if(CONFIG_CHERRYUSB_DEVICE)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
|
||||||
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
if(CONFIG_CHERRYUSB_DEVICE_CDC_ACM)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_acm.c)
|
||||||
endif()
|
endif()
|
||||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
|
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)
|
if(CONFIG_CHERRYUSB_DEVICE_DFU)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
|
||||||
endif()
|
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(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
|
||||||
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
|
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
|
||||||
@@ -97,6 +102,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
|
|||||||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_bk")
|
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_dc_musb.c)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.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")
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
|
||||||
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
|
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
|
||||||
@@ -121,6 +129,9 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||||||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
|
||||||
endif()
|
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)
|
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
|
||||||
endif()
|
endif()
|
||||||
@@ -142,18 +153,10 @@ if(CONFIG_CHERRYUSB_HOST)
|
|||||||
endif()
|
endif()
|
||||||
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
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}/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()
|
endif()
|
||||||
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
|
||||||
endif()
|
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)
|
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
|
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)
|
if(CONFIG_CHERRYUSB_HOST_PL2303)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
|
||||||
endif()
|
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(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
|
||||||
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
|
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_hc_ehci_iso.c)
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.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)
|
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")
|
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.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_hc_ehci_iso.c)
|
||||||
@@ -260,5 +272,20 @@ if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
|||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
|
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
|
||||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
||||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_yoc.c)
|
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()
|
||||||
|
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_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
|
||||||
endif()
|
endif()
|
||||||
@@ -6,16 +6,10 @@
|
|||||||
#ifndef CHERRYUSB_CONFIG_H
|
#ifndef CHERRYUSB_CONFIG_H
|
||||||
#define CHERRYUSB_CONFIG_H
|
#define CHERRYUSB_CONFIG_H
|
||||||
|
|
||||||
#define CHERRYUSB_VERSION 0x010301
|
|
||||||
#define CHERRYUSB_VERSION_STR "v1.3.1"
|
|
||||||
|
|
||||||
/* ================ USB common Configuration ================ */
|
/* ================ USB common Configuration ================ */
|
||||||
|
|
||||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
|
||||||
#define usb_malloc(size) malloc(size)
|
|
||||||
#define usb_free(ptr) free(ptr)
|
|
||||||
|
|
||||||
#ifndef CONFIG_USB_DBG_LEVEL
|
#ifndef CONFIG_USB_DBG_LEVEL
|
||||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
||||||
#endif
|
#endif
|
||||||
@@ -72,6 +66,10 @@
|
|||||||
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
||||||
#endif
|
#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
|
// #define CONFIG_USBDEV_MSC_THREAD
|
||||||
|
|
||||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||||
@@ -268,7 +266,7 @@
|
|||||||
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
|
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
|
||||||
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
|
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
|
||||||
*/
|
*/
|
||||||
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE) / 4)
|
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
|
||||||
|
|
||||||
/* ---------------- MUSB Configuration ---------------- */
|
/* ---------------- MUSB Configuration ---------------- */
|
||||||
// #define CONFIG_USB_MUSB_SUNXI
|
// #define CONFIG_USB_MUSB_SUNXI
|
||||||
|
|||||||
310
class/adb/usbd_adb.c
Normal file
310
class/adb/usbd_adb.c
Normal file
@@ -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));
|
||||||
|
}
|
||||||
38
class/adb/usbd_adb.h
Normal file
38
class/adb/usbd_adb.h
Normal file
@@ -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);
|
setup->bRequest);
|
||||||
|
|
||||||
uint8_t entity_id;
|
uint8_t entity_id;
|
||||||
uint8_t ep;
|
uint8_t ep = 0;
|
||||||
uint8_t subtype = 0x01;
|
uint8_t subtype = 0x01;
|
||||||
uint8_t control_selector;
|
uint8_t control_selector;
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
@@ -287,7 +287,7 @@ static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
||||||
struct usbd_interface *intf,
|
struct usbd_interface *intf,
|
||||||
uint16_t uac_version,
|
uint16_t uac_version,
|
||||||
struct audio_entity_info *table,
|
struct audio_entity_info *table,
|
||||||
@@ -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)
|
__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)
|
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
|
(void)ch;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
|
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
|
(void)ch;
|
||||||
|
(void)mute;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
|
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
|
(void)ch;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
|
__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)
|
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||||
{
|
{
|
||||||
|
(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)
|
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
|
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
|
||||||
{
|
{
|
||||||
|
(void)audio_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
|
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||||
{
|
{
|
||||||
|
(void)audio_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct usbh_class_driver audio_ctrl_class_driver = {
|
const struct usbh_class_driver audio_ctrl_class_driver = {
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ struct cdc_ncm_ndp16 {
|
|||||||
0x02, /* bInterfaceCount */ \
|
0x02, /* bInterfaceCount */ \
|
||||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||||
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
|
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
|
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||||
0x00, /* iFunction */ \
|
0x00, /* iFunction */ \
|
||||||
0x09, /* bLength */ \
|
0x09, /* bLength */ \
|
||||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||||
@@ -430,7 +430,7 @@ struct cdc_ncm_ndp16 {
|
|||||||
0x01, /* bNumEndpoints */ \
|
0x01, /* bNumEndpoints */ \
|
||||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||||
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
|
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
|
||||||
str_idx, /* iInterface */ \
|
str_idx, /* iInterface */ \
|
||||||
0x05, /* bLength */ \
|
0x05, /* bLength */ \
|
||||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||||
@@ -489,8 +489,8 @@ struct cdc_ncm_ndp16 {
|
|||||||
bFirstInterface, /* bFirstInterface */ \
|
bFirstInterface, /* bFirstInterface */ \
|
||||||
0x02, /* bInterfaceCount */ \
|
0x02, /* bInterfaceCount */ \
|
||||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
0x01, /* bFunctionSubClass */ \
|
||||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
0x03, /* bFunctionProtocol */ \
|
||||||
0x00, /* iFunction */ \
|
0x00, /* iFunction */ \
|
||||||
0x09, /* bLength */ \
|
0x09, /* bLength */ \
|
||||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||||
@@ -498,8 +498,8 @@ struct cdc_ncm_ndp16 {
|
|||||||
0x00, /* bAlternateSetting */ \
|
0x00, /* bAlternateSetting */ \
|
||||||
0x01, /* bNumEndpoints */ \
|
0x01, /* bNumEndpoints */ \
|
||||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
0x01, /* bInterfaceSubClass */ \
|
||||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
0x03, /* bInterfaceProtocol */ \
|
||||||
str_idx, /* iInterface */ \
|
str_idx, /* iInterface */ \
|
||||||
0x05, /* bLength */ \
|
0x05, /* bLength */ \
|
||||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||||
|
|||||||
@@ -1,29 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, sakumisu
|
* Copyright (c) 2024, sakumisu
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef USBD_CDC_H
|
#ifndef USBD_CDC_H
|
||||||
#define USBD_CDC_H
|
#define USBD_CDC_H
|
||||||
|
|
||||||
#include "usb_cdc.h"
|
// legacy for old version
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include "usbd_cdc_acm.h"
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Init cdc acm interface driver */
|
#endif
|
||||||
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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
|
|
||||||
const char *stop_name[] = { "1", "1.5", "2" };
|
const char *stop_name[] = { "1", "1.5", "2" };
|
||||||
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
||||||
@@ -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)
|
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_interface_handler = cdc_acm_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
intf->vendor_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)
|
__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)
|
__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->dwDTERate = 2000000;
|
||||||
line_coding->bDataBits = 8;
|
line_coding->bDataBits = 8;
|
||||||
line_coding->bParityType = 0;
|
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)
|
__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)
|
__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)
|
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)intf;
|
||||||
}
|
}
|
||||||
29
class/cdc/usbd_cdc_acm.h
Normal file
29
class/cdc/usbd_cdc_acm.h
Normal file
@@ -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",
|
"bRequest 0x%02x\r\n",
|
||||||
setup->bRequest);
|
setup->bRequest);
|
||||||
|
|
||||||
|
(void)busid;
|
||||||
|
(void)data;
|
||||||
|
(void)len;
|
||||||
|
|
||||||
g_cmd_intf = LO_BYTE(setup->wIndex);
|
g_cmd_intf = LO_BYTE(setup->wIndex);
|
||||||
|
|
||||||
switch (setup->bRequest) {
|
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 cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
g_current_net_status = 0;
|
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 cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
|
||||||
g_cdc_ecm_rx_data_length += nbytes;
|
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;
|
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);
|
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||||
} else {
|
} 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)
|
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 */
|
/* send zlp */
|
||||||
usbd_ep_start_write(0, ep, NULL, 0);
|
usbd_ep_start_write(0, ep, NULL, 0);
|
||||||
} else {
|
} 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 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) {
|
if (g_current_net_status == 1) {
|
||||||
g_current_net_status = 2;
|
g_current_net_status = 2;
|
||||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
|
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)
|
__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"
|
#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 struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
static uint32_t g_devinuse = 0;
|
||||||
@@ -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->wIndex = cdc_acm_class->intf;
|
||||||
setup->wLength = 7;
|
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)
|
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->wIndex = cdc_acm_class->intf;
|
||||||
setup->wLength = 7;
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
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;
|
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)
|
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
__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)
|
__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 = {
|
const struct usbh_class_driver cdc_acm_class_driver = {
|
||||||
@@ -260,10 +266,10 @@ const struct usbh_class_driver cdc_data_class_driver = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
||||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||||
.class = USB_DEVICE_CLASS_CDC,
|
.class = USB_DEVICE_CLASS_CDC,
|
||||||
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
|
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||||
.protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
|
.protocol = 0x00,
|
||||||
.id_table = NULL,
|
.id_table = NULL,
|
||||||
.class_driver = &cdc_acm_class_driver
|
.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;
|
uint32_t g_cdc_ecm_rx_length;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
(void)argument;
|
||||||
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
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)
|
__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)
|
__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 = {
|
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);
|
uint32_t transfer_size = (16 * 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(void)argument;
|
||||||
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
|
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
|
||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
find_class:
|
||||||
@@ -330,7 +331,7 @@ find_class:
|
|||||||
#else
|
#else
|
||||||
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
|
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
|
||||||
#endif
|
#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) {
|
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)
|
__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)
|
__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 = {
|
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),
|
/* Keyboard output report (1 byte) (HID B.1),
|
||||||
* see USBHID_KBDOUT_* definitions
|
* see HID_KBD_OUTPUT_* definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Mouse input report (HID B.2) */
|
/* Mouse input report (HID B.2) */
|
||||||
struct usb_hid_mouse_report
|
struct usb_hid_mouse_report
|
||||||
{
|
{
|
||||||
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
|
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
|
||||||
uint8_t xdisp; /* X displacement */
|
int8_t xdisp; /* X displacement */
|
||||||
uint8_t ydisp; /* y displacement */
|
int8_t ydisp; /* y displacement */
|
||||||
/* Device specific additional bytes may follow */
|
/* Device specific additional bytes may follow */
|
||||||
#ifdef CONFIG_INPUT_MOUSE_WHEEL
|
|
||||||
uint8_t wdisp; /* Wheel displacement */
|
uint8_t wdisp; /* Wheel displacement */
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Joystick input report (1 bytes) (HID D.1) */
|
/* Joystick input report (1 bytes) (HID D.1) */
|
||||||
struct usb_hid_js_report
|
struct usb_hid_js_report
|
||||||
{
|
{
|
||||||
uint8_t xpos; /* X position */
|
int8_t xpos; /* X position */
|
||||||
uint8_t ypos; /* X position */
|
int8_t ypos; /* X position */
|
||||||
uint8_t buttons; /* See USBHID_JSIN_* definitions */
|
uint8_t buttons; /* See USBHID_JSIN_* definitions */
|
||||||
uint8_t throttle; /* Throttle */
|
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)
|
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_interface_handler = hid_class_interface_request_handler;
|
||||||
intf->class_endpoint_handler = NULL;
|
intf->class_endpoint_handler = NULL;
|
||||||
intf->vendor_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;
|
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)
|
__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;
|
(*data[0]) = 0;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
|
__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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
|
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
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)
|
__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)
|
__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)
|
__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"
|
#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 struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
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->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
|
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
|
||||||
setup->wIndex = hid_class->intf;
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(buffer, g_hid_buf, ret - 8);
|
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||||
return ret;
|
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->wIndex = hid_class->intf;
|
||||||
setup->wLength = 1;
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(buffer, g_hid_buf, 1);
|
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||||
return ret;
|
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)
|
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;
|
struct usb_setup_packet *setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!hid_class || !hid_class->hport) {
|
if (!hid_class || !hid_class->hport) {
|
||||||
return -USB_ERR_INVAL;
|
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->wIndex = 0;
|
||||||
setup->wLength = buflen;
|
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)
|
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
struct usb_endpoint_descriptor *ep_desc;
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
uint8_t cur_iface = 0xff;
|
||||||
|
uint8_t *p;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||||
if (hid_class == NULL) {
|
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;
|
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 */
|
// /* 0x0 = boot protocol, 0x1 = report protocol */
|
||||||
// ret = usbh_hid_set_protocol(hid_class, 0x1);
|
// ret = usbh_hid_set_protocol(hid_class, 0x1);
|
||||||
// if (ret < 0) {
|
// 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)
|
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
|
||||||
{
|
{
|
||||||
|
(void)hid_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
|
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||||
{
|
{
|
||||||
|
(void)hid_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct usbh_class_driver hid_class_driver = {
|
const struct usbh_class_driver hid_class_driver = {
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ struct usbh_hid {
|
|||||||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||||
|
|
||||||
uint8_t report_desc[256];
|
uint8_t report_desc[256];
|
||||||
|
uint16_t report_size;
|
||||||
|
|
||||||
|
uint8_t protocol;
|
||||||
uint8_t intf; /* interface number */
|
uint8_t intf; /* interface number */
|
||||||
uint8_t minor;
|
uint8_t minor;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,12 @@
|
|||||||
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
|
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
|
||||||
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
|
#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 */
|
/* Hub class requests */
|
||||||
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
|
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
|
||||||
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
|
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
|
||||||
@@ -27,23 +33,31 @@
|
|||||||
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
|
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
|
||||||
|
|
||||||
/* Port features */
|
/* Port features */
|
||||||
#define HUB_PORT_FEATURE_CONNECTION (0x00)
|
#define HUB_PORT_FEATURE_CONNECTION (0x00)
|
||||||
#define HUB_PORT_FEATURE_ENABLE (0x01)
|
#define HUB_PORT_FEATURE_ENABLE (0x01)
|
||||||
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
||||||
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
||||||
#define HUB_PORT_FEATURE_RESET (0x04)
|
#define HUB_PORT_FEATURE_RESET (0x04)
|
||||||
#define HUB_PORT_FEATURE_L1 (0x05)
|
#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
|
||||||
#define HUB_PORT_FEATURE_POWER (0x08)
|
|
||||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
|
#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
|
||||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
|
#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_CONNECTION (0x10)
|
||||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
|
#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
|
||||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
|
#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
|
||||||
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
|
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
|
||||||
#define HUB_PORT_FEATURE_C_RESET (0x14)
|
#define HUB_PORT_FEATURE_C_RESET (0x14)
|
||||||
#define HUB_PORT_FEATURE_TEST (0x15)
|
#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
|
||||||
#define HUB_PORT_FEATURE_INDICATOR (0x16)
|
#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
|
||||||
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
|
#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
|
||||||
|
|
||||||
/* Hub status */
|
/* Hub status */
|
||||||
#define HUB_STATUS_LOCALPOWER (1 << 0)
|
#define HUB_STATUS_LOCALPOWER (1 << 0)
|
||||||
@@ -56,23 +70,42 @@
|
|||||||
/* Hub port status */
|
/* Hub port status */
|
||||||
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
|
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
|
||||||
#define HUB_PORT_STATUS_ENABLE (1 << 1)
|
#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_OVERCURRENT (1 << 3)
|
||||||
#define HUB_PORT_STATUS_RESET (1 << 4)
|
#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 */
|
||||||
#define HUB_PORT_STATUS_POWER (1 << 8)
|
|
||||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
|
/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
|
||||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
|
#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
|
||||||
#define HUB_PORT_STATUS_TEST (1 << 11)
|
#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
|
||||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
|
#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_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 */
|
/* Hub port status change */
|
||||||
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
|
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
|
||||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
|
#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
|
||||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
|
#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_OVERCURRENT (1 << 3)
|
||||||
#define HUB_PORT_STATUS_C_RESET (1 << 4)
|
#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 */
|
/* Hub characteristics */
|
||||||
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
|
#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
|
#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 */
|
/* Hub status */
|
||||||
struct hub_status {
|
struct hub_status {
|
||||||
uint16_t wPortStatus;
|
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));
|
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)
|
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
struct usb_setup_packet *setup;
|
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->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
|
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
|
||||||
/* 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->wIndex = 0;
|
||||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
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);
|
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
|
||||||
return ret;
|
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;
|
struct usb_setup_packet *setup;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -96,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
|||||||
setup = hub->parent->setup;
|
setup = hub->parent->setup;
|
||||||
|
|
||||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
setup->wValue = 0;
|
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||||
|
|
||||||
setup->wIndex = 0;
|
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]);
|
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
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
|
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||||
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
|
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
|
||||||
{
|
{
|
||||||
|
(void)length;
|
||||||
|
|
||||||
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
|
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
|
||||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -199,6 +191,29 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
|
|||||||
}
|
}
|
||||||
return 0;
|
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
|
#endif
|
||||||
|
|
||||||
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
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->hub_addr = hport->dev_addr;
|
||||||
hub->parent = hport;
|
hub->parent = hport;
|
||||||
hub->bus = hport->bus;
|
hub->bus = hport->bus;
|
||||||
|
hub->speed = hport->speed;
|
||||||
|
|
||||||
|
hport->self = hub;
|
||||||
hport->config.intf[intf].priv = hub;
|
hport->config.intf[intf].priv = hub;
|
||||||
|
|
||||||
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
|
if (hport->depth > HUB_MAX_DEPTH) {
|
||||||
if (ret < 0) {
|
USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
|
||||||
return ret;
|
return -USB_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
/* 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->nports; port++) {
|
||||||
hub->child[port].port = port + 1;
|
hub->child[port].port = port + 1;
|
||||||
hub->child[port].parent = hub;
|
hub->child[port].parent = hub;
|
||||||
hub->child[port].bus = hport->bus;
|
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;
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||||
if (ep_desc->bEndpointAddress & 0x80) {
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
USBH_EP_INIT(hub->intin, ep_desc);
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hport->speed == USB_SPEED_SUPER) {
|
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||||
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++) {
|
|
||||||
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
|
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
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);
|
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);
|
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
|
||||||
if (ret < 0) {
|
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);
|
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];
|
child = &hub->child[port];
|
||||||
usbh_hubport_release(child);
|
usbh_hubport_release(child);
|
||||||
child->parent = NULL;
|
child->parent = NULL;
|
||||||
@@ -415,7 +461,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
{
|
{
|
||||||
struct usbh_hubport *child;
|
struct usbh_hubport *child;
|
||||||
struct hub_port_status port_status;
|
struct hub_port_status port_status;
|
||||||
uint8_t portchange_index;
|
uint16_t portchange_index;
|
||||||
uint16_t portstatus;
|
uint16_t portstatus;
|
||||||
uint16_t portchange;
|
uint16_t portchange;
|
||||||
uint16_t mask;
|
uint16_t mask;
|
||||||
@@ -429,11 +475,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
portchange_index = hub->int_buffer[0];
|
memcpy(&portchange_index, hub->int_buffer, 2);
|
||||||
hub->int_buffer[0] &= ~portchange_index;
|
|
||||||
usb_osal_leave_critical_section(flags);
|
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);
|
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
||||||
|
|
||||||
if (!(portchange_index & (1 << (port + 1)))) {
|
if (!(portchange_index & (1 << (port + 1)))) {
|
||||||
@@ -539,12 +584,23 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
/*
|
||||||
speed = USB_SPEED_HIGH;
|
* Figure out device speed. This is a bit tricky because
|
||||||
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
* HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
|
||||||
speed = USB_SPEED_LOW;
|
*/
|
||||||
|
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) {
|
||||||
|
speed = USB_SPEED_LOW;
|
||||||
|
} else {
|
||||||
|
speed = USB_SPEED_FULL;
|
||||||
|
}
|
||||||
|
} else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
|
||||||
|
speed = USB_SPEED_SUPER;
|
||||||
} else {
|
} else {
|
||||||
speed = USB_SPEED_FULL;
|
USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
child = &hub->child[port];
|
child = &hub->child[port];
|
||||||
@@ -553,6 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
|||||||
|
|
||||||
memset(child, 0, sizeof(struct usbh_hubport));
|
memset(child, 0, sizeof(struct usbh_hubport));
|
||||||
child->parent = hub;
|
child->parent = hub;
|
||||||
|
child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
|
||||||
child->connected = true;
|
child->connected = true;
|
||||||
child->port = port + 1;
|
child->port = port + 1;
|
||||||
child->speed = speed;
|
child->speed = speed;
|
||||||
@@ -624,7 +681,7 @@ int usbh_hub_initialize(struct usbh_bus *bus)
|
|||||||
hub->is_roothub = true;
|
hub->is_roothub = true;
|
||||||
hub->parent = NULL;
|
hub->parent = NULL;
|
||||||
hub->hub_addr = 1;
|
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->int_buffer = bus->hcd.roothub_intbuf;
|
||||||
hub->bus = bus;
|
hub->bus = bus;
|
||||||
|
|
||||||
@@ -652,7 +709,7 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
|
|||||||
flags = usb_osal_enter_critical_section();
|
flags = usb_osal_enter_critical_section();
|
||||||
|
|
||||||
hub = &bus->hcd.roothub;
|
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];
|
hport = &hub->child[port];
|
||||||
|
|
||||||
usbh_hubport_release(hport);
|
usbh_hubport_release(hport);
|
||||||
|
|||||||
@@ -10,10 +10,6 @@
|
|||||||
|
|
||||||
struct usbh_hub;
|
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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "usb_scsi.h"
|
#include "usb_scsi.h"
|
||||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||||
#include "usb_osal.h"
|
#include "usb_osal.h"
|
||||||
|
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||||
|
#include "chry_ringbuffer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MSD_OUT_EP_IDX 0
|
#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_mq_t usbd_msc_mq;
|
||||||
usb_osal_thread_t usbd_msc_thread;
|
usb_osal_thread_t usbd_msc_thread;
|
||||||
uint32_t nbytes;
|
uint32_t nbytes;
|
||||||
|
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||||
|
chry_ringbuffer_t msc_rb;
|
||||||
|
uint8_t msc_rb_pool[2];
|
||||||
|
uint32_t nbytes;
|
||||||
#endif
|
#endif
|
||||||
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
|
} 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 msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_INIT:
|
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);
|
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
|
||||||
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
|
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");
|
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) {
|
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");
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
case USBD_EVENT_DEINIT:
|
case USBD_EVENT_DEINIT:
|
||||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||||
if (g_usbd_msc[busid].usbd_msc_mq) {
|
if (g_usbd_msc[busid].usbd_msc_mq) {
|
||||||
usb_osal_mq_delete(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)
|
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)) {
|
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||||
return false;
|
return false;
|
||||||
@@ -522,9 +535,12 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
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);
|
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||||
return true;
|
return true;
|
||||||
|
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||||
|
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
|
||||||
|
return true;
|
||||||
#else
|
#else
|
||||||
return SCSI_processRead(busid);
|
return SCSI_processRead(busid);
|
||||||
#endif
|
#endif
|
||||||
@@ -532,6 +548,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)
|
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)) {
|
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||||
return false;
|
return false;
|
||||||
@@ -554,9 +573,12 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
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);
|
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||||
return true;
|
return true;
|
||||||
|
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||||
|
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
|
||||||
|
return true;
|
||||||
#else
|
#else
|
||||||
return SCSI_processRead(busid);
|
return SCSI_processRead(busid);
|
||||||
#endif
|
#endif
|
||||||
@@ -565,6 +587,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)
|
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint32_t data_len = 0;
|
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)) {
|
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||||
return false;
|
return false;
|
||||||
@@ -594,6 +620,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)
|
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint32_t data_len = 0;
|
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)) {
|
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||||
return false;
|
return false;
|
||||||
@@ -803,6 +833,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 mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
|
(void)ep;
|
||||||
|
|
||||||
switch (g_usbd_msc[busid].stage) {
|
switch (g_usbd_msc[busid].stage) {
|
||||||
case MSC_READ_CBW:
|
case MSC_READ_CBW:
|
||||||
if (SCSI_CBWDecode(busid, nbytes) == false) {
|
if (SCSI_CBWDecode(busid, nbytes) == false) {
|
||||||
@@ -815,9 +847,12 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
|||||||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||||
case SCSI_CMD_WRITE10:
|
case SCSI_CMD_WRITE10:
|
||||||
case SCSI_CMD_WRITE12:
|
case SCSI_CMD_WRITE12:
|
||||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||||
g_usbd_msc[busid].nbytes = nbytes;
|
g_usbd_msc[busid].nbytes = nbytes;
|
||||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
|
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
|
#else
|
||||||
if (SCSI_processWrite(busid, nbytes) == false) {
|
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*/
|
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||||
@@ -835,13 +870,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 mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
|
(void)ep;
|
||||||
|
(void)nbytes;
|
||||||
|
|
||||||
switch (g_usbd_msc[busid].stage) {
|
switch (g_usbd_msc[busid].stage) {
|
||||||
case MSC_DATA_IN:
|
case MSC_DATA_IN:
|
||||||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||||
case SCSI_CMD_READ10:
|
case SCSI_CMD_READ10:
|
||||||
case SCSI_CMD_READ12:
|
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);
|
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
|
#else
|
||||||
if (SCSI_processRead(busid) == false) {
|
if (SCSI_processRead(busid) == false) {
|
||||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||||
@@ -870,7 +910,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)
|
static void usbdev_msc_thread(void *argument)
|
||||||
{
|
{
|
||||||
uintptr_t event;
|
uintptr_t event;
|
||||||
@@ -882,7 +922,26 @@ static void usbdev_msc_thread(void *argument)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
continue;
|
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 (event == MSC_DATA_OUT) {
|
||||||
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
|
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*/
|
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||||
@@ -932,7 +991,7 @@ void usbd_msc_set_readonly(uint8_t busid, bool readonly)
|
|||||||
g_usbd_msc[busid].readonly = 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;
|
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);
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#define MSC_INQUIRY_TIMEOUT 500
|
#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 struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
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)
|
static void usbh_msc_csw_dump(struct CSW *csw)
|
||||||
{
|
{
|
||||||
|
(void)csw;
|
||||||
|
|
||||||
USB_LOG_DBG("CSW:\r\n");
|
USB_LOG_DBG("CSW:\r\n");
|
||||||
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
|
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
|
||||||
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
cbw->dSignature = MSC_CBW_Signature;
|
||||||
|
|
||||||
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
|
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
|
||||||
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
|
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)
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
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[0] = SCSI_CMD_REQUESTSENSE;
|
||||||
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
|
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)
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
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[0] = SCSI_CMD_INQUIRY;
|
||||||
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
|
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)
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
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->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
|
||||||
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
|
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)
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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)
|
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;
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
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++) {
|
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;
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
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_BE32(&cbw->CB[2], start_sector);
|
||||||
SET_BE16(&cbw->CB[7], nsectors);
|
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)
|
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;
|
struct CBW *cbw;
|
||||||
|
|
||||||
/* Construct the 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);
|
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||||
cbw->dSignature = MSC_CBW_Signature;
|
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_BE32(&cbw->CB[2], start_sector);
|
||||||
SET_BE16(&cbw->CB[7], nsectors);
|
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)
|
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)
|
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||||
{
|
{
|
||||||
|
(void)msc_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
|
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||||
{
|
{
|
||||||
|
(void)msc_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct usbh_class_driver msc_class_driver = {
|
const struct usbh_class_driver msc_class_driver = {
|
||||||
|
|||||||
5
class/vendor/net/usbh_asix.c
vendored
5
class/vendor/net/usbh_asix.c
vendored
@@ -680,6 +680,7 @@ void usbh_asix_rx_thread(void *argument)
|
|||||||
uint32_t transfer_size = (16 * 1024);
|
uint32_t transfer_size = (16 * 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(void)argument;
|
||||||
USB_LOG_INFO("Create asix rx thread\r\n");
|
USB_LOG_INFO("Create asix rx thread\r\n");
|
||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
find_class:
|
||||||
@@ -742,7 +743,7 @@ find_class:
|
|||||||
#else
|
#else
|
||||||
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
|
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
|
||||||
#endif
|
#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) {
|
while (1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -791,10 +792,12 @@ int usbh_asix_eth_output(uint32_t buflen)
|
|||||||
|
|
||||||
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
|
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
|
||||||
{
|
{
|
||||||
|
(void)asix_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
|
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
|
||||||
{
|
{
|
||||||
|
(void)asix_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t asix_id_table[][2] = {
|
static const uint16_t asix_id_table[][2] = {
|
||||||
|
|||||||
5
class/vendor/net/usbh_rtl8152.c
vendored
5
class/vendor/net/usbh_rtl8152.c
vendored
@@ -2140,6 +2140,7 @@ void usbh_rtl8152_rx_thread(void *argument)
|
|||||||
uint32_t transfer_size = (16 * 1024);
|
uint32_t transfer_size = (16 * 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(void)argument;
|
||||||
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
|
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
|
||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
find_class:
|
||||||
@@ -2210,7 +2211,7 @@ find_class:
|
|||||||
#else
|
#else
|
||||||
if ((g_rtl8152_rx_length + (16 * 1024)) > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
|
if ((g_rtl8152_rx_length + (16 * 1024)) > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
|
||||||
#endif
|
#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) {
|
while (1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2248,10 +2249,12 @@ int usbh_rtl8152_eth_output(uint32_t buflen)
|
|||||||
|
|
||||||
__WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
|
__WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
|
||||||
{
|
{
|
||||||
|
(void)rtl8152_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
|
__WEAK void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
|
||||||
{
|
{
|
||||||
|
(void)rtl8152_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t rtl_id_table[][2] = {
|
static const uint16_t rtl_id_table[][2] = {
|
||||||
|
|||||||
2
class/vendor/serial/usbh_ch34x.c
vendored
2
class/vendor/serial/usbh_ch34x.c
vendored
@@ -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)
|
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
|
||||||
{
|
{
|
||||||
|
(void)ch34x_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
||||||
{
|
{
|
||||||
|
(void)ch34x_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t ch34x_id_table[][2] = {
|
static const uint16_t ch34x_id_table[][2] = {
|
||||||
|
|||||||
4
class/vendor/serial/usbh_cp210x.c
vendored
4
class/vendor/serial/usbh_cp210x.c
vendored
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
|
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 struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
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)
|
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
|
||||||
{
|
{
|
||||||
|
(void)cp210x_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
||||||
{
|
{
|
||||||
|
(void)cp210x_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t cp210x_id_table[][2] = {
|
static const uint16_t cp210x_id_table[][2] = {
|
||||||
|
|||||||
6
class/vendor/serial/usbh_ftdi.c
vendored
6
class/vendor/serial/usbh_ftdi.c
vendored
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
|
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 struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
|
||||||
static uint32_t g_devinuse = 0;
|
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 divisor = FTDI_USB_CLK / baudrate;
|
||||||
int frac_bits = 0;
|
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]) {
|
if ((divisor & 0xF) == frac[i]) {
|
||||||
frac_bits = i;
|
frac_bits = i;
|
||||||
break;
|
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)
|
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
|
||||||
{
|
{
|
||||||
|
(void)ftdi_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
||||||
{
|
{
|
||||||
|
(void)ftdi_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t ftdi_id_table[][2] = {
|
static const uint16_t ftdi_id_table[][2] = {
|
||||||
|
|||||||
4
class/vendor/serial/usbh_pl2303.c
vendored
4
class/vendor/serial/usbh_pl2303.c
vendored
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[64];
|
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_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)
|
#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)
|
__WEAK void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
|
||||||
{
|
{
|
||||||
|
(void)pl2303_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
|
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
|
||||||
{
|
{
|
||||||
|
(void)pl2303_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint16_t pl2303_id_table[][2] = {
|
static const uint16_t pl2303_id_table[][2] = {
|
||||||
|
|||||||
6
class/vendor/wifi/README.md
vendored
Normal file
6
class/vendor/wifi/README.md
vendored
Normal file
@@ -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
|
||||||
512
class/vendor/wifi/usbh_bl616.c
vendored
Normal file
512
class/vendor/wifi/usbh_bl616.c
vendored
Normal file
@@ -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
|
||||||
|
};
|
||||||
220
class/vendor/wifi/usbh_bl616.h
vendored
Normal file
220
class/vendor/wifi/usbh_bl616.h
vendored
Normal file
@@ -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 */
|
||||||
228
class/vendor/xbox/usbh_xbox.c
vendored
Normal file
228
class/vendor/xbox/usbh_xbox.c
vendored
Normal file
@@ -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
|
||||||
|
};
|
||||||
31
class/vendor/xbox/usbh_xbox.h
vendored
Normal file
31
class/vendor/xbox/usbh_xbox.h
vendored
Normal file
@@ -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);
|
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||||
|
|
||||||
|
(void)busid;
|
||||||
|
|
||||||
switch (control_selector) {
|
switch (control_selector) {
|
||||||
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
|
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
|
||||||
switch (setup->bRequest) {
|
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)
|
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
{
|
{
|
||||||
|
(void)hport;
|
||||||
|
(void)intf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||||
{
|
{
|
||||||
|
(void)video_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||||
{
|
{
|
||||||
|
(void)video_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
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)
|
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) {
|
switch (setup->bRequest) {
|
||||||
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||||||
rndis_encapsulated_cmd_handler(*data, setup->wLength);
|
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_msg_t *cmd = (rndis_initialize_msg_t *)data;
|
||||||
rndis_initialize_cmplt_t *resp;
|
rndis_initialize_cmplt_t *resp;
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->RequestId = cmd->RequestId;
|
resp->RequestId = cmd->RequestId;
|
||||||
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
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;
|
rndis_halt_msg_t *resp;
|
||||||
|
|
||||||
|
(void)data;
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->MessageLength = 0;
|
resp->MessageLength = 0;
|
||||||
|
|
||||||
@@ -192,6 +199,8 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
|||||||
uint8_t *infomation_buffer;
|
uint8_t *infomation_buffer;
|
||||||
uint32_t infomation_len = 0;
|
uint32_t infomation_len = 0;
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||||
resp->RequestId = cmd->RequestId;
|
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_set_cmplt_t *resp;
|
||||||
rndis_config_parameter_t *param;
|
rndis_config_parameter_t *param;
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->RequestId = cmd->RequestId;
|
resp->RequestId = cmd->RequestId;
|
||||||
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
|
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_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||||
rndis_reset_cmplt_t *resp;
|
rndis_reset_cmplt_t *resp;
|
||||||
|
|
||||||
|
(void)data;
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||||
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
|
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_msg_t *cmd = (rndis_keepalive_msg_t *)data;
|
||||||
rndis_keepalive_cmplt_t *resp;
|
rndis_keepalive_cmplt_t *resp;
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
|
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
resp->RequestId = cmd->RequestId;
|
resp->RequestId = cmd->RequestId;
|
||||||
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
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)
|
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||||
{
|
{
|
||||||
|
(void)busid;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case USBD_EVENT_RESET:
|
case USBD_EVENT_RESET:
|
||||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
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;
|
rndis_data_packet_t *hdr;
|
||||||
|
|
||||||
|
(void)busid;
|
||||||
|
(void)ep;
|
||||||
|
|
||||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||||
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
||||||
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
|
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)
|
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 */
|
/* send zlp */
|
||||||
usbd_ep_start_write(0, ep, NULL, 0);
|
usbd_ep_start_write(0, ep, NULL, 0);
|
||||||
} else {
|
} 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 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);
|
//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)
|
__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)
|
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
|
||||||
{
|
{
|
||||||
|
(void)bluetooth_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
||||||
{
|
{
|
||||||
|
(void)bluetooth_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct usbh_class_driver bluetooth_class_driver = {
|
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)
|
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||||
{
|
{
|
||||||
|
(void)rndis_class;
|
||||||
// int ret;
|
// int ret;
|
||||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
// 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);
|
uint32_t transfer_size = (16 * 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(void)argument;
|
||||||
|
|
||||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||||
// clang-format off
|
// clang-format off
|
||||||
find_class:
|
find_class:
|
||||||
@@ -531,7 +534,7 @@ find_class:
|
|||||||
#else
|
#else
|
||||||
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||||
#endif
|
#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) {
|
while (1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -581,10 +584,12 @@ int usbh_rndis_eth_output(uint32_t buflen)
|
|||||||
|
|
||||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||||
{
|
{
|
||||||
|
(void)rndis_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||||
{
|
{
|
||||||
|
(void)rndis_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct usbh_class_driver rndis_class_driver = {
|
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);
|
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
|
* @brief Get USB device speed
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -614,7 +614,7 @@ struct usb_webusb_url_descriptor {
|
|||||||
char URL[];
|
char URL[];
|
||||||
} __PACKED;
|
} __PACKED;
|
||||||
|
|
||||||
struct usb_webusb_url_ex_descriptor {
|
struct usb_webusb_descriptor {
|
||||||
uint8_t vendor_code;
|
uint8_t vendor_code;
|
||||||
const uint8_t *string;
|
const uint8_t *string;
|
||||||
uint32_t string_len;
|
uint32_t string_len;
|
||||||
|
|||||||
@@ -82,4 +82,31 @@ void usb_assert(const char *filename, int linenum);
|
|||||||
usb_assert(__FILE__, __LINE__); \
|
usb_assert(__FILE__, __LINE__); \
|
||||||
} while (0)
|
} 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 */
|
#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_msleep(uint32_t delay);
|
||||||
|
|
||||||
|
void *usb_osal_malloc(size_t size);
|
||||||
|
void usb_osal_free(void *ptr);
|
||||||
|
|
||||||
#endif /* USB_OSAL_H */
|
#endif /* USB_OSAL_H */
|
||||||
|
|||||||
21
common/usb_version.h
Normal file
21
common/usb_version.h
Normal file
@@ -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
|
||||||
159
core/usbd_core.c
159
core/usbd_core.c
@@ -45,12 +45,18 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
|
|||||||
struct usb_msosv1_descriptor *msosv1_desc;
|
struct usb_msosv1_descriptor *msosv1_desc;
|
||||||
struct usb_msosv2_descriptor *msosv2_desc;
|
struct usb_msosv2_descriptor *msosv2_desc;
|
||||||
struct usb_bos_descriptor *bos_desc;
|
struct usb_bos_descriptor *bos_desc;
|
||||||
|
struct usb_webusb_descriptor *webusb_url_desc;
|
||||||
#endif
|
#endif
|
||||||
/* Buffer used for storing standard, class and vendor request data */
|
/* Buffer used for storing standard, class and vendor request data */
|
||||||
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
|
||||||
|
|
||||||
/** Currently selected configuration */
|
/** Currently selected configuration */
|
||||||
uint8_t 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
|
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||||
uint8_t speed;
|
uint8_t speed;
|
||||||
#endif
|
#endif
|
||||||
@@ -99,9 +105,9 @@ static bool is_device_configured(uint8_t busid)
|
|||||||
static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("Open ep:0x%02x type:%u mps:%u\r\n",
|
USB_LOG_DBG("Open ep:0x%02x type:%u mps:%u\r\n",
|
||||||
ep->bEndpointAddress,
|
ep->bEndpointAddress,
|
||||||
USB_GET_ENDPOINT_TYPE(ep->bmAttributes),
|
USB_GET_ENDPOINT_TYPE(ep->bmAttributes),
|
||||||
USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
||||||
|
|
||||||
if (ep->bEndpointAddress & 0x80) {
|
if (ep->bEndpointAddress & 0x80) {
|
||||||
g_usbd_core[busid].tx_msg[ep->bEndpointAddress & 0x7f].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
g_usbd_core[busid].tx_msg[ep->bEndpointAddress & 0x7f].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||||
@@ -126,8 +132,8 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto
|
|||||||
static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||||
{
|
{
|
||||||
USB_LOG_DBG("Close ep:0x%02x type:%u\r\n",
|
USB_LOG_DBG("Close ep:0x%02x type:%u\r\n",
|
||||||
ep->bEndpointAddress,
|
ep->bEndpointAddress,
|
||||||
USB_GET_ENDPOINT_TYPE(ep->bmAttributes));
|
USB_GET_ENDPOINT_TYPE(ep->bmAttributes));
|
||||||
|
|
||||||
return usbd_ep_close(busid, ep->bEndpointAddress) == 0 ? true : false;
|
return usbd_ep_close(busid, ep->bEndpointAddress) == 0 ? true : false;
|
||||||
}
|
}
|
||||||
@@ -174,6 +180,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
|
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;
|
break;
|
||||||
case USB_DESCRIPTOR_TYPE_STRING:
|
case USB_DESCRIPTOR_TYPE_STRING:
|
||||||
if (index == USB_OSDESC_STRING_DESC_INDEX) {
|
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]) |
|
*len = (p[CONF_DESC_wTotalLength]) |
|
||||||
(p[CONF_DESC_wTotalLength + 1] << 8);
|
(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 {
|
} else {
|
||||||
/* normally length is at offset 0 */
|
/* normally length is at offset 0 */
|
||||||
*len = p[DESC_bLength];
|
*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 0: self-powered */
|
||||||
/* bit 1: remote wakeup */
|
/* bit 1: remote wakeup */
|
||||||
(*data)[0] = 0x00;
|
(*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;
|
(*data)[1] = 0x00;
|
||||||
*len = 2;
|
*len = 2;
|
||||||
break;
|
break;
|
||||||
@@ -530,8 +548,10 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||||||
case USB_REQUEST_SET_FEATURE:
|
case USB_REQUEST_SET_FEATURE:
|
||||||
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
if (value == USB_FEATURE_REMOTE_WAKEUP) {
|
||||||
if (setup->bRequest == USB_REQUEST_SET_FEATURE) {
|
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);
|
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SET_REMOTE_WAKEUP);
|
||||||
} else {
|
} else {
|
||||||
|
g_usbd_core[busid].remote_wakeup_enabled = false;
|
||||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CLR_REMOTE_WAKEUP);
|
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CLR_REMOTE_WAKEUP);
|
||||||
}
|
}
|
||||||
} else if (value == USB_FEATURE_TEST_MODE) {
|
} 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;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_SET_ADDRESS:
|
case USB_REQUEST_SET_ADDRESS:
|
||||||
|
g_usbd_core[busid].device_address = value;
|
||||||
usbd_set_address(busid, value);
|
usbd_set_address(busid, value);
|
||||||
*len = 0;
|
*len = 0;
|
||||||
break;
|
break;
|
||||||
@@ -556,17 +577,20 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_CONFIGURATION:
|
case USB_REQUEST_GET_CONFIGURATION:
|
||||||
*data = (uint8_t *)&g_usbd_core[busid].configuration;
|
(*data)[0] = g_usbd_core[busid].configuration;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_SET_CONFIGURATION:
|
case USB_REQUEST_SET_CONFIGURATION:
|
||||||
value &= 0xFF;
|
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;
|
ret = false;
|
||||||
} else {
|
} else {
|
||||||
g_usbd_core[busid].configuration = value;
|
g_usbd_core[busid].configuration = value;
|
||||||
|
g_usbd_core[busid].is_suspend = false;
|
||||||
usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
|
usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
|
||||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CONFIGURED);
|
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 type = HI_BYTE(setup->wValue);
|
||||||
uint8_t intf_num = LO_BYTE(setup->wIndex);
|
uint8_t intf_num = LO_BYTE(setup->wIndex);
|
||||||
bool ret = true;
|
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. */
|
/* Only when device is configured, then interface requests can be valid. */
|
||||||
if (!is_device_configured(busid)) {
|
if (!is_device_configured(busid)) {
|
||||||
@@ -614,7 +648,39 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_REQUEST_GET_DESCRIPTOR:
|
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++) {
|
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
|
||||||
struct usbd_interface *intf = g_usbd_core[busid].intf[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;
|
uint8_t ep = (uint8_t)setup->wIndex;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
uint8_t stalled;
|
||||||
|
|
||||||
/* Only when device is configured, then endpoint requests can be valid. */
|
/* Only when device is configured, then endpoint requests can be valid. */
|
||||||
if (!is_device_configured(busid)) {
|
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) {
|
switch (setup->bRequest) {
|
||||||
case USB_REQUEST_GET_STATUS:
|
case USB_REQUEST_GET_STATUS:
|
||||||
(*data)[0] = 0x00;
|
usbd_ep_is_stalled(busid, ep, &stalled);
|
||||||
|
if (stalled) {
|
||||||
|
(*data)[0] = 0x01;
|
||||||
|
} else {
|
||||||
|
(*data)[0] = 0x00;
|
||||||
|
}
|
||||||
(*data)[1] = 0x00;
|
(*data)[1] = 0x00;
|
||||||
*len = 2;
|
*len = 2;
|
||||||
break;
|
break;
|
||||||
@@ -841,10 +913,12 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
|
|||||||
return -1;
|
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) {
|
if (setup->bRequest == g_usbd_core[busid].descriptors->webusb_url_descriptor->vendor_code) {
|
||||||
switch (setup->wIndex) {
|
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;
|
desclen = g_usbd_core[busid].descriptors->webusb_url_descriptor->string_len;
|
||||||
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
|
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
|
||||||
//memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen);
|
//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
|
#endif
|
||||||
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
|
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
|
||||||
struct usbd_interface *intf = g_usbd_core[busid].intf[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)
|
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);
|
g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESUME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_event_suspend_handler(uint8_t busid)
|
void usbd_event_suspend_handler(uint8_t busid)
|
||||||
{
|
{
|
||||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
|
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)
|
void usbd_event_reset_handler(uint8_t busid)
|
||||||
{
|
{
|
||||||
usbd_set_address(busid, 0);
|
usbd_set_address(busid, 0);
|
||||||
|
g_usbd_core[busid].device_address = 0;
|
||||||
g_usbd_core[busid].configuration = 0;
|
g_usbd_core[busid].configuration = 0;
|
||||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||||
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
|
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;
|
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 += nbytes;
|
||||||
g_usbd_core[busid].ep0_data_buf_residue -= 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;
|
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
|
||||||
|
|
||||||
|
(void)ep;
|
||||||
|
|
||||||
if (nbytes > 0) {
|
if (nbytes > 0) {
|
||||||
g_usbd_core[busid].ep0_data_buf += nbytes;
|
g_usbd_core[busid].ep0_data_buf += nbytes;
|
||||||
g_usbd_core[busid].ep0_data_buf_residue -= 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;
|
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
|
#endif
|
||||||
|
|
||||||
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
|
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;
|
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;
|
int ret;
|
||||||
struct usbd_bus *bus;
|
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)
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ extern "C" {
|
|||||||
#include "usb_log.h"
|
#include "usb_log.h"
|
||||||
#include "usb_dc.h"
|
#include "usb_dc.h"
|
||||||
#include "usb_memcpy.h"
|
#include "usb_memcpy.h"
|
||||||
|
#include "usb_version.h"
|
||||||
|
|
||||||
enum usbd_event_type {
|
enum usbd_event_type {
|
||||||
/* USB DCD IRQ */
|
/* USB DCD IRQ */
|
||||||
@@ -71,13 +72,13 @@ struct usb_descriptor {
|
|||||||
const char *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
const char *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
||||||
const struct usb_msosv1_descriptor *msosv1_descriptor;
|
const struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||||
const struct usb_msosv2_descriptor *msosv2_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;
|
const struct usb_bos_descriptor *bos_descriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usbd_bus {
|
struct usbd_bus {
|
||||||
uint8_t busid;
|
uint8_t busid;
|
||||||
uint32_t reg_base;
|
uintptr_t reg_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct usbd_bus g_usbdev_bus[];
|
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_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_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_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
|
#endif
|
||||||
|
|
||||||
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
|
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);
|
uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep);
|
||||||
uint8_t usbd_get_ep_mult(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_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);
|
int usbd_deinitialize(uint8_t busid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
|
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
|
||||||
hport->raw_config_desc = usb_malloc(wTotalLength);
|
hport->raw_config_desc = usb_osal_malloc(wTotalLength + 1);
|
||||||
if (hport->raw_config_desc == NULL) {
|
if (hport->raw_config_desc == NULL) {
|
||||||
ret = -USB_ERR_NOMEM;
|
ret = -USB_ERR_NOMEM;
|
||||||
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
|
||||||
@@ -495,6 +495,8 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
|
|
||||||
config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
|
config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
|
||||||
memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
|
memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
|
||||||
|
hport->raw_config_desc[wTotalLength] = '\0';
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
#ifdef CONFIG_USBHOST_GET_STRING_DESC
|
||||||
uint8_t string_buffer[128];
|
uint8_t string_buffer[128];
|
||||||
|
|
||||||
@@ -549,7 +551,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
setup->wLength = 16;
|
setup->wLength = 16;
|
||||||
|
|
||||||
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
|
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);
|
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -576,7 +578,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
|||||||
|
|
||||||
errout:
|
errout:
|
||||||
if (hport->raw_config_desc) {
|
if (hport->raw_config_desc) {
|
||||||
usb_free(hport->raw_config_desc);
|
usb_osal_free(hport->raw_config_desc);
|
||||||
hport->raw_config_desc = NULL;
|
hport->raw_config_desc = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -600,7 +602,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));
|
memset(bus, 0, sizeof(struct usbh_bus));
|
||||||
bus->busid = busid;
|
bus->busid = busid;
|
||||||
@@ -613,7 +615,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);
|
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;
|
struct usbh_bus *bus;
|
||||||
|
|
||||||
@@ -731,7 +733,7 @@ static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devn
|
|||||||
struct usbh_hub *hub_next;
|
struct usbh_hub *hub_next;
|
||||||
void *priv;
|
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];
|
hport = &hub->child[port];
|
||||||
if (hport->connected) {
|
if (hport->connected) {
|
||||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||||
@@ -760,8 +762,9 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
|
|||||||
{
|
{
|
||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
struct usbh_hub *hub_next;
|
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];
|
hport = &hub->child[port];
|
||||||
if (hport->connected) {
|
if (hport->connected) {
|
||||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||||
@@ -770,11 +773,12 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
|
|||||||
USB_LOG_RAW("\t");
|
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->port,
|
||||||
hport->dev_addr,
|
hport->dev_addr,
|
||||||
itf,
|
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) {
|
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
|
||||||
hub_next = hport->config.intf[itf].priv;
|
hub_next = hport->config.intf[itf].priv;
|
||||||
@@ -794,7 +798,7 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *
|
|||||||
struct usbh_hubport *hport;
|
struct usbh_hubport *hport;
|
||||||
struct usbh_hub *hub_next;
|
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];
|
hport = &hub->child[port];
|
||||||
if (hport->connected) {
|
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",
|
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
|
||||||
@@ -888,7 +892,7 @@ int lsusb(int argc, char **argv)
|
|||||||
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
|
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
|
||||||
bus->busid,
|
bus->busid,
|
||||||
hub->index,
|
hub->index,
|
||||||
hub->hub_desc.bNbrPorts);
|
hub->nports);
|
||||||
usbh_list_all_interface_driver(hub);
|
usbh_list_all_interface_driver(hub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "usb_osal.h"
|
#include "usb_osal.h"
|
||||||
#include "usbh_hub.h"
|
#include "usbh_hub.h"
|
||||||
#include "usb_memcpy.h"
|
#include "usb_memcpy.h"
|
||||||
|
#include "usb_version.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -101,6 +102,9 @@ struct usbh_hubport {
|
|||||||
uint8_t port; /* Hub port index */
|
uint8_t port; /* Hub port index */
|
||||||
uint8_t dev_addr; /* device address */
|
uint8_t dev_addr; /* device address */
|
||||||
uint8_t speed; /* device speed */
|
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 usb_device_descriptor device_desc;
|
||||||
struct usbh_configuration config;
|
struct usbh_configuration config;
|
||||||
const char *iManufacturer;
|
const char *iManufacturer;
|
||||||
@@ -109,6 +113,7 @@ struct usbh_hubport {
|
|||||||
uint8_t *raw_config_desc;
|
uint8_t *raw_config_desc;
|
||||||
struct usb_setup_packet *setup;
|
struct usb_setup_packet *setup;
|
||||||
struct usbh_hub *parent;
|
struct usbh_hub *parent;
|
||||||
|
struct usbh_hub *self; /* if this hubport is a hub */
|
||||||
struct usbh_bus *bus;
|
struct usbh_bus *bus;
|
||||||
struct usb_endpoint_descriptor ep0;
|
struct usb_endpoint_descriptor ep0;
|
||||||
struct usbh_urb ep0_urb;
|
struct usbh_urb ep0_urb;
|
||||||
@@ -120,7 +125,13 @@ struct usbh_hub {
|
|||||||
bool is_roothub;
|
bool is_roothub;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint8_t hub_addr;
|
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 child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||||
struct usbh_hubport *parent;
|
struct usbh_hubport *parent;
|
||||||
struct usbh_bus *bus;
|
struct usbh_bus *bus;
|
||||||
@@ -143,9 +154,9 @@ struct usbh_devaddr_map {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct usbh_hcd {
|
struct usbh_hcd {
|
||||||
uint32_t reg_base;
|
uintptr_t reg_base;
|
||||||
uint8_t hcd_id;
|
uint8_t hcd_id;
|
||||||
uint8_t roothub_intbuf[1];
|
uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
|
||||||
struct usbh_hub roothub;
|
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_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);
|
int usbh_deinitialize(uint8_t busid);
|
||||||
void *usbh_find_class_instance(const char *devname);
|
void *usbh_find_class_instance(const char *devname);
|
||||||
|
|
||||||
|
|||||||
BIN
demo/adb/cherryadb.png
Normal file
BIN
demo/adb/cherryadb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
330
demo/adb/cherrysh_port.c
Normal file
330
demo/adb/cherrysh_port.c
Normal file
@@ -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));
|
||||||
228
demo/adb/usbd_adb_template.c
Normal file
228
demo/adb/usbd_adb_template.c
Normal file
@@ -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 },
|
.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_desc_register(busid, audio_v1_descriptor);
|
||||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
|
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 },
|
.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_desc_register(busid, audio_v1_descriptor);
|
||||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
|
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 },
|
.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_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
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 },
|
.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_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
|
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 },
|
.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_desc_register(busid, audio_v2_descriptor);
|
||||||
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
|
||||||
|
|||||||
463
demo/bootuf2/bootuf2.c
Normal file
463
demo/bootuf2/bootuf2.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
218
demo/bootuf2/bootuf2.h
Normal file
218
demo/bootuf2/bootuf2.h
Normal file
@@ -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 */
|
||||||
25
demo/bootuf2/bootuf2_config.h
Normal file
25
demo/bootuf2/bootuf2_config.h
Normal file
@@ -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
|
||||||
BIN
demo/bootuf2/cherryuf2.png
Normal file
BIN
demo/bootuf2/cherryuf2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
168
demo/bootuf2/msc_bootuf2_template.c
Normal file
168
demo/bootuf2/msc_bootuf2_template.c
Normal file
@@ -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_core.h"
|
||||||
#include "usbd_msc.h"
|
#include "usbd_msc.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
#include "usbd_hid.h"
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
/*!< endpoint address */
|
/*!< endpoint address */
|
||||||
@@ -301,7 +301,7 @@ struct usbd_interface intf1;
|
|||||||
struct usbd_interface intf2;
|
struct usbd_interface intf2;
|
||||||
struct usbd_interface intf3;
|
struct usbd_interface intf3;
|
||||||
|
|
||||||
void cdc_acm_hid_msc_descriptor_init(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);
|
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
#include "usbd_msc.h"
|
#include "usbd_msc.h"
|
||||||
|
|
||||||
/*!< endpoint address */
|
/*!< endpoint address */
|
||||||
@@ -247,7 +247,7 @@ struct usbd_interface intf0;
|
|||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
struct usbd_interface intf2;
|
struct usbd_interface intf2;
|
||||||
|
|
||||||
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
|
void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||||
usbd_desc_register(busid, &cdc_msc_descriptor);
|
usbd_desc_register(busid, &cdc_msc_descriptor);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
|
|
||||||
/*!< endpoint address */
|
/*!< endpoint address */
|
||||||
#define CDC_IN_EP 0x81
|
#define CDC_IN_EP 0x81
|
||||||
@@ -223,7 +223,7 @@ struct usbd_interface intf5;
|
|||||||
struct usbd_interface intf6;
|
struct usbd_interface intf6;
|
||||||
struct usbd_interface intf7;
|
struct usbd_interface intf7;
|
||||||
|
|
||||||
void cdc_acm_multi_init(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);
|
usbd_desc_register(busid, cdc_descriptor);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
|
|
||||||
/*!< endpoint address */
|
/*!< endpoint address */
|
||||||
#define CDC_IN_EP 0x81
|
#define CDC_IN_EP 0x81
|
||||||
@@ -174,7 +174,7 @@ struct usbd_endpoint cdc_in_ep = {
|
|||||||
static struct usbd_interface intf0;
|
static struct usbd_interface intf0;
|
||||||
static struct usbd_interface intf1;
|
static struct usbd_interface intf1;
|
||||||
|
|
||||||
void cdc_acm_init(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 };
|
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 ifconfig enxaabbccddeeff up
|
||||||
* sudo dhcpclient enxaabbccddeeff
|
* 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();
|
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 intf0;
|
||||||
struct usbd_interface intf1;
|
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
|
#ifdef RT_USING_LWIP
|
||||||
rt_usbd_rndis_init();
|
rt_usbd_rndis_init();
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
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_desc_register(busid, dfu_flash_descriptor);
|
||||||
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
|
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ static struct usbd_endpoint custom_out_ep = {
|
|||||||
*/
|
*/
|
||||||
struct usbd_interface intf0;
|
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_desc_register(busid, hid_descriptor);
|
||||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ static struct usbd_endpoint hid_in_ep = {
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
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_desc_register(busid, hid_descriptor);
|
||||||
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/*!< endpoint address */
|
/*!< endpoint address */
|
||||||
#define HID_INT_EP 0x81
|
#define HID_INT_EP 0x81
|
||||||
#define HID_INT_EP_SIZE 4
|
#define HID_INT_EP_SIZE 4
|
||||||
#define HID_INT_EP_INTERVAL 10
|
#define HID_INT_EP_INTERVAL 1
|
||||||
|
|
||||||
#define USBD_VID 0xffff
|
#define USBD_VID 0xffff
|
||||||
#define USBD_PID 0xffff
|
#define USBD_PID 0xffff
|
||||||
@@ -239,7 +239,7 @@ static struct usbd_endpoint hid_in_ep = {
|
|||||||
|
|
||||||
struct usbd_interface intf0;
|
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_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_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;
|
mouse_cfg.y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#define CURSOR_STEP 2U
|
||||||
* @brief hid mouse test
|
#define CURSOR_WIDTH 20U
|
||||||
* @pre none
|
|
||||||
* @param[in] none
|
void draw_circle(uint8_t *buf)
|
||||||
* @retval none
|
{
|
||||||
*/
|
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)
|
void hid_mouse_test(uint8_t busid)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (counter < 1000) {
|
while (counter < 1000) {
|
||||||
/*!< move mouse pointer */
|
draw_circle((uint8_t *)&mouse_cfg);
|
||||||
mouse_cfg.x += 40;
|
|
||||||
mouse_cfg.y += 0;
|
|
||||||
|
|
||||||
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
330
demo/hid_remote_wakeup_template.c
Normal file
330
demo/hid_remote_wakeup_template.c
Normal file
@@ -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
|
.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_desc_register(busid, midi_descriptor);
|
||||||
usbd_add_interface(busid, &intf0);
|
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;
|
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_desc_register(busid, msc_ram_descriptor);
|
||||||
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
|
||||||
|
|
||||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
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;
|
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;
|
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;
|
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||||
|
|
||||||
if (nbytes > 0) {
|
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("0x%02x ", hid_buffer[i]);
|
||||||
}
|
}
|
||||||
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ struct audio_entity_info audio_entity_table[] = {
|
|||||||
.ep = AUDIO_OUT_EP },
|
.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_desc_register(busid, video_audio_hid_descriptor);
|
||||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
void video_init(uint8_t busid, uint32_t reg_base)
|
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(busid, video_descriptor);
|
usbd_desc_register(busid, video_descriptor);
|
||||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
void video_init(uint8_t busid, uint32_t reg_base)
|
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(busid, video_descriptor);
|
usbd_desc_register(busid, video_descriptor);
|
||||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ static struct usbd_endpoint video_in_ep = {
|
|||||||
struct usbd_interface intf0;
|
struct usbd_interface intf0;
|
||||||
struct usbd_interface intf1;
|
struct usbd_interface intf1;
|
||||||
|
|
||||||
void video_init(uint8_t busid, uint32_t reg_base)
|
void video_init(uint8_t busid, uintptr_t reg_base)
|
||||||
{
|
{
|
||||||
usbd_desc_register(busid, video_descriptor);
|
usbd_desc_register(busid, video_descriptor);
|
||||||
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
|
|||||||
382
demo/webusb_hid_template.c
Normal file
382
demo/webusb_hid_template.c
Normal file
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
|
|
||||||
#define WCID_VENDOR_CODE 0x17
|
#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[] = {
|
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
|
||||||
WINUSB_IF0_WCIDProperties,
|
WINUSB_IF0_WCIDProperties,
|
||||||
|
#if DOUBLE_WINUSB == 1
|
||||||
WINUSB_IF1_WCIDProperties,
|
WINUSB_IF1_WCIDProperties,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usb_msosv1_descriptor msosv1_desc = {
|
struct usb_msosv1_descriptor msosv1_desc = {
|
||||||
.string = WCID_StringDescriptor_MSOS,
|
.string = WCID_StringDescriptor_MSOS,
|
||||||
.vendor_code = WCID_VENDOR_CODE,
|
.vendor_code = WCID_VENDOR_CODE,
|
||||||
.compat_id = WINUSB_WCIDDescriptor,
|
.compat_id = WINUSB_WCIDDescriptor,
|
||||||
#if DOUBLE_WINUSB == 0
|
|
||||||
.comp_id_property = &WINUSB_IF0_WCIDProperties,
|
|
||||||
#else
|
|
||||||
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
.comp_id_property = WINUSB_IFx_WCIDProperties,
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WINUSB_IN_EP 0x81
|
#define WINUSB_IN_EP 0x81
|
||||||
@@ -446,7 +444,7 @@ struct usbd_interface intf1;
|
|||||||
|
|
||||||
#endif
|
#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_desc_register(busid, winusb_descriptor);
|
||||||
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc_acm.h"
|
||||||
|
|
||||||
#define WINUSB_IN_EP 0x81
|
#define WINUSB_IN_EP 0x81
|
||||||
#define WINUSB_OUT_EP 0x02
|
#define WINUSB_OUT_EP 0x02
|
||||||
@@ -318,7 +318,7 @@ struct usb_bos_descriptor bos_desc = {
|
|||||||
.string_len = USBD_BOS_WTOTALLENGTH
|
.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_desc_register(busid, winusbv2_descriptor);
|
||||||
usbd_bos_desc_register(busid, &bos_desc);
|
usbd_bos_desc_register(busid, &bos_desc);
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ struct usb_bos_descriptor bos_desc = {
|
|||||||
.string_len = USBD_BOS_WTOTALLENGTH
|
.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_desc_register(busid, winusbv2_descriptor);
|
||||||
usbd_bos_desc_register(busid, &bos_desc);
|
usbd_bos_desc_register(busid, &bos_desc);
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 178 KiB |
BIN
docs/assets/espressif.png
Normal file
BIN
docs/assets/espressif.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/assets/nxp.png
Normal file
BIN
docs/assets/nxp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -1,10 +1,10 @@
|
|||||||
设备协议栈
|
设备协议栈
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
设备协议栈主要负责枚举和驱动加载,枚举这边就不说了,驱动加载,也就是接口驱动加载,主要是依靠 `usbd_add_interface` 函数,记录传入的接口驱动保存到链表中,当主机进行类请求时就可以查找链表进行访问了。
|
设备协议栈主要负责枚举和驱动加载,枚举这边就不说了,驱动加载,也就是接口驱动加载,主要是依靠 `usbd_add_interface` 函数,用于记录传入的接口驱动并保存到接口数组表,当主机进行类请求时就可以查找接口表进行访问了。
|
||||||
在调用 `usbd_desc_register` 以后需要进行接口注册和端点注册,口诀如下:
|
在调用 `usbd_desc_register` 以后需要进行接口注册和端点注册,口诀如下:
|
||||||
|
|
||||||
- 有多少个接口就调用多少次 `usbd_add_interface`,参数填相关 `xxx_init_intf`, 如果没有支持的,手动创建一个填入
|
- 有多少个接口就调用多少次 `usbd_add_interface`,参数填相关 `xxx_init_intf`, 如果没有支持的,手动创建一个 intf 填入
|
||||||
- 有多少个端点就调用多少次 `usbd_add_endpoint`,当中断完成时,会调用到注册的端点回调中。
|
- 有多少个端点就调用多少次 `usbd_add_endpoint`,当中断完成时,会调用到注册的端点回调中。
|
||||||
|
|
||||||
CORE
|
CORE
|
||||||
@@ -38,7 +38,6 @@ CORE
|
|||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
struct usbd_interface {
|
struct usbd_interface {
|
||||||
usb_slist_t list;
|
|
||||||
usbd_request_handler class_interface_handler;
|
usbd_request_handler class_interface_handler;
|
||||||
usbd_request_handler class_endpoint_handler;
|
usbd_request_handler class_endpoint_handler;
|
||||||
usbd_request_handler vendor_handler;
|
usbd_request_handler vendor_handler;
|
||||||
@@ -48,7 +47,6 @@ CORE
|
|||||||
uint8_t intf_num;
|
uint8_t intf_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
- **list** 接口的链表节点
|
|
||||||
- **class_interface_handler** class setup 请求回调函数,接收者为接口
|
- **class_interface_handler** class setup 请求回调函数,接收者为接口
|
||||||
- **class_endpoint_handler** class setup 请求回调函数,接收者为端点
|
- **class_endpoint_handler** class setup 请求回调函数,接收者为端点
|
||||||
- **vendor_handler** vendor setup 请求回调函数
|
- **vendor_handler** vendor setup 请求回调函数
|
||||||
@@ -69,6 +67,9 @@ usbd_desc_register
|
|||||||
|
|
||||||
- **desc** 描述符的句柄
|
- **desc** 描述符的句柄
|
||||||
|
|
||||||
|
.. note:: 当前 API 仅支持一种速度,如果需要更高级的速度切换功能,请开启 CONFIG_USBDEV_ADVANCE_DESC,并且包含了下面所有描述符注册功能
|
||||||
|
|
||||||
|
|
||||||
usbd_msosv1_desc_register
|
usbd_msosv1_desc_register
|
||||||
""""""""""""""""""""""""""""""""""""
|
""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
@@ -284,7 +285,7 @@ usbd_msc_sector_read
|
|||||||
|
|
||||||
- **sector** 扇区偏移
|
- **sector** 扇区偏移
|
||||||
- **buffer** 存储读取的数据的指针
|
- **buffer** 存储读取的数据的指针
|
||||||
- **length** 读取长度,当前为1个扇区的大小
|
- **length** 读取长度
|
||||||
|
|
||||||
|
|
||||||
usbd_msc_sector_write
|
usbd_msc_sector_write
|
||||||
@@ -298,7 +299,7 @@ usbd_msc_sector_write
|
|||||||
|
|
||||||
- **sector** 扇区偏移
|
- **sector** 扇区偏移
|
||||||
- **buffer** 写入数据指针
|
- **buffer** 写入数据指针
|
||||||
- **length** 写入长度,当前为1个扇区的大小
|
- **length** 写入长度
|
||||||
|
|
||||||
UAC
|
UAC
|
||||||
-----------------
|
-----------------
|
||||||
|
|||||||
@@ -49,11 +49,11 @@ CLASS 驱动信息结构体
|
|||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
struct usbh_interface {
|
struct usbh_interface {
|
||||||
struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
|
|
||||||
uint8_t altsetting_num;
|
|
||||||
char devname[CONFIG_USBHOST_DEV_NAMELEN];
|
char devname[CONFIG_USBHOST_DEV_NAMELEN];
|
||||||
struct usbh_class_driver *class_driver;
|
struct usbh_class_driver *class_driver;
|
||||||
void *priv;
|
void *priv;
|
||||||
|
struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
|
||||||
|
uint8_t altsetting_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
配置结构体
|
配置结构体
|
||||||
@@ -76,6 +76,9 @@ hubport 结构体
|
|||||||
uint8_t port; /* Hub port index */
|
uint8_t port; /* Hub port index */
|
||||||
uint8_t dev_addr; /* device address */
|
uint8_t dev_addr; /* device address */
|
||||||
uint8_t speed; /* device speed */
|
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 usb_device_descriptor device_desc;
|
||||||
struct usbh_configuration config;
|
struct usbh_configuration config;
|
||||||
const char *iManufacturer;
|
const char *iManufacturer;
|
||||||
@@ -84,6 +87,8 @@ hubport 结构体
|
|||||||
uint8_t *raw_config_desc;
|
uint8_t *raw_config_desc;
|
||||||
struct usb_setup_packet *setup;
|
struct usb_setup_packet *setup;
|
||||||
struct usbh_hub *parent;
|
struct usbh_hub *parent;
|
||||||
|
struct usbh_hub *self; /* if this hubport is a hub */
|
||||||
|
struct usbh_bus *bus;
|
||||||
struct usb_endpoint_descriptor ep0;
|
struct usb_endpoint_descriptor ep0;
|
||||||
struct usbh_urb ep0_urb;
|
struct usbh_urb ep0_urb;
|
||||||
usb_osal_mutex_t mutex;
|
usb_osal_mutex_t mutex;
|
||||||
@@ -95,17 +100,24 @@ hub 结构体
|
|||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
struct usbh_hub {
|
struct usbh_hub {
|
||||||
usb_slist_t list;
|
|
||||||
bool connected;
|
bool connected;
|
||||||
bool is_roothub;
|
bool is_roothub;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint8_t hub_addr;
|
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 child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||||
struct usbh_hubport *parent;
|
struct usbh_hubport *parent;
|
||||||
|
struct usbh_bus *bus;
|
||||||
struct usb_endpoint_descriptor *intin;
|
struct usb_endpoint_descriptor *intin;
|
||||||
struct usbh_urb intin_urb;
|
struct usbh_urb intin_urb;
|
||||||
uint8_t *int_buffer;
|
uint8_t *int_buffer;
|
||||||
|
struct usb_osal_timer *int_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
usbh_initialize
|
usbh_initialize
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ project = 'CherryUSB'
|
|||||||
copyright = '2024, sakumisu'
|
copyright = '2024, sakumisu'
|
||||||
author = 'sakumisu'
|
author = 'sakumisu'
|
||||||
|
|
||||||
release = '1.3.1'
|
release = '1.4.0'
|
||||||
version = '1.3.1'
|
version = '1.4.0'
|
||||||
|
|
||||||
# -- General configuration
|
# -- General configuration
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
USB 双通道麦克风和扬声器
|
|
||||||
============================
|
|
||||||
|
|
||||||
软件实现
|
|
||||||
------------
|
|
||||||
|
|
||||||
详细代码参考 `demo/audio_v1_mic_speaker_multichan_template.c`
|
|
||||||
|
|
||||||
.. code-block:: C
|
|
||||||
|
|
||||||
usbd_desc_register(audio_descriptor);
|
|
||||||
usbd_add_interface(usbd_audio_alloc_intf());
|
|
||||||
usbd_add_interface(usbd_audio_alloc_intf());
|
|
||||||
usbd_add_interface(usbd_audio_alloc_intf());
|
|
||||||
usbd_add_endpoint(&audio_in_ep);
|
|
||||||
usbd_add_endpoint(&audio_out_ep);
|
|
||||||
|
|
||||||
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
|
||||||
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
|
|
||||||
|
|
||||||
usbd_initialize();
|
|
||||||
|
|
||||||
- 调用 `audio_init` 配置 audio 描述符并初始化 usb 硬件
|
|
||||||
- 因为 麦克风+扬声器+控制需要 3 个接口,所以我们需要调用 `usbd_add_interface` 3 次
|
|
||||||
- 默认描述符中开启了 mute 和 volume 的控制,所以需要注册对应的 entity,使用 `usbd_audio_add_entity`
|
|
||||||
|
|
||||||
.. code-block:: C
|
|
||||||
|
|
||||||
void usbd_audio_open(uint8_t intf)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void usbd_audio_close(uint8_t intf)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
- 当我们打开 PC 的音量图标,或者音乐播放器、麦克风界面时,会调用到这两个接口,用于启动或者停止数据传输
|
|
||||||
|
|
||||||
.. code-block:: C
|
|
||||||
|
|
||||||
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, 2048);
|
|
||||||
|
|
||||||
- 由于 audio 协议中没有应用层相关的协议,传输的只有音频的原始数据,所以直接调用 `usbd_ep_start_write` 即可,发送完成会进入完成中断
|
|
||||||
- 由于扬声器需要使用 out 端点,所以需要在 `usbd_configure_done_callback` 中启动第一次接收,当然如果没有能力接收,可以不启动,在想启动的时候启动
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
USB 虚拟串口(无 UART 功能)
|
|
||||||
============================
|
|
||||||
|
|
||||||
USB 虚拟串口主要是借助 USB CDC ACM 类实现,将其模拟成一个 VCP 设备,当插在电脑上的时候,可以显示成一个串口设备。跟市面上的 USB2TTL模块的区别在于,虚拟串口仅仅只使用到了 USB ,没有与串口(UART外设)进行连动。
|
|
||||||
|
|
||||||
软件实现
|
|
||||||
------------
|
|
||||||
|
|
||||||
详细代码参考 `demo/cdc_acm_template.c`
|
|
||||||
|
|
||||||
.. code-block:: C
|
|
||||||
|
|
||||||
usbd_desc_register(cdc_descriptor);
|
|
||||||
usbd_add_interface(usbd_cdc_acm_alloc_intf());
|
|
||||||
usbd_add_interface(usbd_cdc_acm_alloc_intf());
|
|
||||||
usbd_add_endpoint(&cdc_out_ep);
|
|
||||||
usbd_add_endpoint(&cdc_in_ep);
|
|
||||||
usbd_initialize();
|
|
||||||
|
|
||||||
- 调用 `cdc_acm_init` 配置 cdc acm 描述符并初始化 usb 硬件
|
|
||||||
- 因为 cdc 有 2 个接口,所以我们需要调用 `usbd_add_interface` 2 次
|
|
||||||
|
|
||||||
.. code-block:: C
|
|
||||||
|
|
||||||
void usbd_configure_done_callback(void)
|
|
||||||
{
|
|
||||||
/* setup first out ep read transfer */
|
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
|
|
||||||
{
|
|
||||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
|
||||||
// for (int i = 0; i < 100; i++) {
|
|
||||||
// printf("%02x ", read_buffer[i]);
|
|
||||||
// }
|
|
||||||
// printf("\r\n");
|
|
||||||
/* setup next out ep read transfer */
|
|
||||||
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
|
|
||||||
{
|
|
||||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
|
||||||
|
|
||||||
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
|
|
||||||
/* send zlp */
|
|
||||||
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
|
|
||||||
} else {
|
|
||||||
ep_tx_busy_flag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
|
|
||||||
{
|
|
||||||
if (dtr) {
|
|
||||||
dtr_enable = 1;
|
|
||||||
} else {
|
|
||||||
dtr_enable = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cdc_acm_data_send_with_dtr_test(void)
|
|
||||||
{
|
|
||||||
if (dtr_enable) {
|
|
||||||
memset(&write_buffer[10], 'a', 2038);
|
|
||||||
ep_tx_busy_flag = true;
|
|
||||||
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
|
|
||||||
while (ep_tx_busy_flag) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- `usbd_cdc_acm_set_dtr` 函数是主机发送流控命令时的回调函数,这里我们使用 dtr ,当开启 dtr 时,启动发送
|
|
||||||
- `usbd_configure_done_callback` 是枚举完成的回调函数,因为 cdc acm 有 out 端点,所以我们需要在这里启动第一次数据的接收,当然,如果你现在没有能力接收数据,可以不启动。 **数据长度需要是最大包长的整数倍**。
|
|
||||||
- `usbd_cdc_acm_bulk_out` 是接收完成中断回调,我们在这里面启动下一次接收
|
|
||||||
- `usbd_cdc_acm_bulk_in` 是发送完成中断回调,我们在这里检查发送长度是否是最大包长的整数,如果是,需要发送 zlp 包表示结束
|
|
||||||
- 调用 `usbd_ep_start_write` 进行发送,需要注意,如果返回值小于0,不能执行下面的 while
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user