update(cherryusb): update to v1.4.3

Signed-off-by: sakumisu <1203593632@qq.com>
This commit is contained in:
sakumisu 2025-03-07 14:08:56 +08:00 committed by Rbb666
parent 180fb2bd4c
commit de30bd1105
94 changed files with 8719 additions and 559 deletions

View File

@ -125,7 +125,9 @@ if RT_USING_CHERRYUSB
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
bool "cdc_acm"
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
bool "msc"
bool "msc_ram"
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
bool "msc_blkdev"
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
bool "hid_keyboard"
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE

View File

@ -12,7 +12,7 @@
<a href="./README.md">English</a>
</p>
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
CherryUSB is a tiny and beautiful, high performance and portable USB host and device stack for embedded system with USB IP.
![CherryUSB](CherryUSB.svg)
@ -103,7 +103,7 @@ CherryUSB Host Stack has the following functions
- Automatic loading of supported Class drivers
- Support blocking transfers and asynchronous transfers
- Support Composite Device
- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2 and ehci now)
- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2/ehci/xhci/rp2040)
- Support Communication Device Class (CDC_ACM, CDC_ECM)
- Support Human Interface Device (HID)
- Support Mass Storage Class (MSC)
@ -197,12 +197,12 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
|Raspberry pi | rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Package Support

View File

@ -12,7 +12,7 @@
<a href="./README.md">English</a>
</p>
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的高性能 USB 主从协议栈。
![CherryUSB](CherryUSB.svg)
@ -103,7 +103,7 @@ CherryUSB Host 协议栈当前实现以下功能:
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,当前仅支持 dwc2 和 ehci)
- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,仅支持 dwc2/ehci/xhci/rp2040)
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
- 支持 Human Interface Device (HID)
- 支持 Mass Storage Class (MSC)
@ -198,12 +198,12 @@ CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
|Raspberry pi | rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## 软件包支持

View File

@ -1,18 +1,23 @@
from building import *
cwd = GetCurrentDir()
path = [cwd + '/common']
path = [cwd]
path += [cwd + '/common']
path += [cwd + '/core']
path += [cwd + '/class/hub']
path += [cwd + '/class/cdc']
path += [cwd + '/class/msc']
path += [cwd + '/class/hid']
path += [cwd + '/class/audio']
path += [cwd + '/class/video']
path += [cwd + '/class/wireless']
path += [cwd + '/class/midi']
path += [cwd + '/class/adb']
path += [cwd + '/class/dfu']
path += [cwd + '/class/midi']
path += [cwd + '/class/vendor/net']
path += [cwd + '/class/vendor/serial']
path += [cwd + '/class/vendor/wifi']
src = []
LIBS = []
@ -109,13 +114,15 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
src += Glob('class/cdc/usbd_cdc_ecm.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_NCM']):
src += Glob('class/cdc/usbd_cdc_ncm.c')
if GetDepend(['RT_CHERRYUSB_USING_DFU']):
if GetDepend(['RT_CHERRYUSB_DEVICE_DFU']):
src += Glob('class/dfu/usbd_dfu.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
src += Glob('demo/cdc_acm_template.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
src += Glob('demo/msc_ram_template.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
src += Glob('platform/rtthread/usbd_msc_blkdev.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
src += Glob('demo/hid_mouse_template.c')
if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
@ -147,7 +154,6 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']):
# USB HOST
if GetDepend(['RT_CHERRYUSB_HOST']):
path += [cwd + '/class/hub']
src += Glob('core/usbh_core.c')
src += Glob('class/hub/usbh_hub.c')
src += Glob('osal/usb_osal_rtthread.c')

View File

@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 4
PATCHLEVEL = 2
PATCHLEVEL = 3
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@ -26,6 +26,7 @@
# set(CONFIG_CHERRYUSB_HOST_HCD "ehci_xxx")
list(APPEND cherryusb_incs
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/common
${CMAKE_CURRENT_LIST_DIR}/core
${CMAKE_CURRENT_LIST_DIR}/class/hub
@ -37,6 +38,7 @@ ${CMAKE_CURRENT_LIST_DIR}/class/video
${CMAKE_CURRENT_LIST_DIR}/class/wireless
${CMAKE_CURRENT_LIST_DIR}/class/midi
${CMAKE_CURRENT_LIST_DIR}/class/adb
${CMAKE_CURRENT_LIST_DIR}/class/dfu
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
@ -116,6 +118,8 @@ if(CONFIG_CHERRYUSB_DEVICE)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "aic")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic_ll.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "rp2040")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_dc_rp2040.c)
endif()
endif()
@ -270,6 +274,8 @@ if(CONFIG_CHERRYUSB_HOST)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "rp2040")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
endif()
endif()

View File

@ -17,11 +17,13 @@
/* Enable print with color */
#define CONFIG_USB_PRINTF_COLOR_ENABLE
/* data align size when use dma */
/* data align size when use dma or use dcache */
#ifndef CONFIG_USB_ALIGN_SIZE
#define CONFIG_USB_ALIGN_SIZE 4
#endif
//#define CONFIG_USB_DCACHE_ENABLE
/* attribute data into no cache ram */
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
@ -46,6 +48,20 @@
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
/* enable advance desc register api */
// CONFIG_USBDEV_ADVANCE_DESC
/* move ep0 setup handler from isr to thread */
// #define CONFIG_USBDEV_EP0_THREAD
#ifndef CONFIG_USBDEV_EP0_PRIO
#define CONFIG_USBDEV_EP0_PRIO 4
#endif
#ifndef CONFIG_USBDEV_EP0_STACKSIZE
#define CONFIG_USBDEV_EP0_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
#define CONFIG_USBDEV_MSC_MAX_LUN 1
#endif
@ -276,4 +292,26 @@
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI
/* ================ USB Dcache Configuration ==================*/
#ifdef CONFIG_USB_DCACHE_ENABLE
/* style 1*/
// void usb_dcache_clean(uintptr_t addr, uint32_t size);
// void usb_dcache_invalidate(uintptr_t addr, uint32_t size);
// void usb_dcache_flush(uintptr_t addr, uint32_t size);
/* style 2*/
// #define usb_dcache_clean(addr, size)
// #define usb_dcache_invalidate(addr, size)
// #define usb_dcache_flush(addr, size)
#endif
#ifndef usb_phyaddr2ramaddr
#define usb_phyaddr2ramaddr(addr) (addr)
#endif
#ifndef usb_ramaddr2phyaddr
#define usb_ramaddr2phyaddr(addr) (addr)
#endif
#endif

View File

@ -822,7 +822,66 @@ struct audio_cs_ep_ep_general_descriptor {
0x00, /* wLockDelay */ \
0x00
#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress, ...) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x01, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
0x01, /* bDelay */ \
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bNrChannels, /* bNrChannels */ \
bSubFrameSize, /* bSubFrameSize : Bytes per audio subframe */ \
bBitResolution, /* bBitResolution : bits per sample */ \
(PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
__VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
0x05, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
bInterval, /* bInterval : one packet per frame */ \
0x00, /* bRefresh */ \
bFeedbackEndpointAddress, /* bSynchAddress */ \
0x07, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00, \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bFeedbackEndpointAddress, /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */ \
0x11, /* bmAttributes: TransferType=Isochronous SyncType=None EndpointType=Feedback */ \
WBVAL(4), /* XXXX wMaxPacketSize in Bytes */ \
bInterval, /* bInterval */ \
0x03, /* bRefresh, 8ms */ \
0x00 /* bSynchAddress */
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07 + 0x09)
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
0x09, /* bLength */ \
@ -1281,4 +1340,19 @@ struct audio_v2_control_range3_param_block {
#define AUDIO_SAMPLE_FREQ_4B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), \
(uint8_t)((frq >> 16)), (uint8_t)((frq >> 24))
/* format 10.14 */
#define AUDIO_FREQ_TO_FEEDBACK_FS(freq) ((freq << 10) / 1000)
#define AUDIO_FEEDBACK_TO_BUF_FS(buf, feedback) \
buf[0] = ((feedback << 4) & 0xFFU); \
buf[1] = (((feedback << 4) >> 8U) & 0xFFU); \
buf[2] = (((feedback << 4) >> 16U) & 0xFFU)
/* format 16.16 */
#define AUDIO_FREQ_TO_FEEDBACK_HS(freq) ((freq << 13) / 1000)
#define AUDIO_FEEDBACK_TO_BUF_HS(buf, feedback) \
buf[0] = (((feedback & 0x00001FFFu) << 3) & 0xFFu); \
buf[1] = ((((feedback & 0x00001FFFu) << 3) >> 8) & 0xFFu); \
buf[2] = (((feedback & 0x01FFE000u) >> 13) & 0xFFu); \
buf[3] = (((feedback & 0x01FFE000u) >> 21) & 0xFFu)
#endif /* USB_AUDIO_H */

View File

@ -231,12 +231,12 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
void usbh_cdc_ecm_rx_thread(void *argument)
void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uint32_t g_cdc_ecm_rx_length;
int ret;
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:

View File

@ -41,7 +41,7 @@ void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void);
int usbh_cdc_ecm_eth_output(uint32_t buflen);
void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ecm_rx_thread(void *argument);
void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#ifdef __cplusplus
}

View File

@ -62,12 +62,12 @@ static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
USB_LOG_RAW("wLength: 0x%02x \r\n", param->wLength);
USB_LOG_RAW("bmNtbFormatsSupported: %s \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
USB_LOG_RAW("dwNtbInMaxSize: 0x%04x \r\n", param->dwNtbInMaxSize);
USB_LOG_RAW("dwNtbInMaxSize: 0x%08lx \r\n", param->dwNtbInMaxSize);
USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x \r\n", param->wNdbInPayloadRemainder);
USB_LOG_RAW("wNdbInAlignment: 0x%02x \r\n", param->wNdbInAlignment);
USB_LOG_RAW("dwNtbOutMaxSize: 0x%04x \r\n", param->dwNtbOutMaxSize);
USB_LOG_RAW("dwNtbOutMaxSize: 0x%08lx \r\n", param->dwNtbOutMaxSize);
USB_LOG_RAW("wNdbOutDivisor: 0x%02x \r\n", param->wNdbOutDivisor);
USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x \r\n", param->wNdbOutPayloadRemainder);
USB_LOG_RAW("wNdbOutAlignment: 0x%02x \r\n", param->wNdbOutAlignment);
@ -249,7 +249,7 @@ static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
void usbh_cdc_ncm_rx_thread(void *argument)
void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uint32_t g_cdc_ncm_rx_length;
int ret;
@ -259,7 +259,7 @@ void usbh_cdc_ncm_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
// clang-format off
find_class:

View File

@ -45,7 +45,7 @@ void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void);
int usbh_cdc_ncm_eth_output(uint32_t buflen);
void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ncm_rx_thread(void *argument);
void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#ifdef __cplusplus
}

View File

@ -191,11 +191,11 @@
#define HID_MOUSE_INPUT_REPORT_BUTTON3 (1 << 2)
#define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7)
#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0)
#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1)
#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2)
#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4)
#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0)
#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1)
#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2)
#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4)
/* Joystick input report (4 bytes) (HID D.1) */
#define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0)
@ -241,14 +241,14 @@
#define HID_DESKTOP_USAGE_UNDEFINED 0x00 /* Undefined */
#define HID_DESKTOP_USAGE_POINTER 0x01 /* Pointer */
#define HID_DESKTOP_USAGE_MOUSE 0x02 /* Mouse */
/* 0x03 Reserved */
/* 0x03 Reserved */
#define HID_DESKTOP_USAGE_JOYSTICK 0x04 /* Joystick */
#define HID_DESKTOP_USAGE_GAMEPAD 0x05 /* Game Pad */
#define HID_DESKTOP_USAGE_KEYBOARD 0x06 /* Keyboard */
#define HID_DESKTOP_USAGE_KEYPAD 0x07 /* Keypad */
#define HID_DESKTOP_USAGE_MULTIAXIS 0x08 /* Multi-axis Controller */
#define HID_DESKTOP_USAGE_TABLET 0x09 /* Tablet PC System Controls */
/* 0x0a-2f Reserved */
/* 0x0a-2f Reserved */
#define HID_DESKTOP_USAGE_X 0x30 /* X */
#define HID_DESKTOP_USAGE_Y 0x31 /* Y */
#define HID_DESKTOP_USAGE_Z 0x32 /* Z */
@ -264,7 +264,7 @@
#define HID_DESKTOP_USAGE_MOTION 0x3c /* Motion Wakeup */
#define HID_DESKTOP_USAGE_START 0x3d /* Start */
#define HID_DESKTOP_USAGE_SELECT 0x3e /* Select */
/* 0x3f Reserved */
/* 0x3f Reserved */
#define HID_DESKTOP_USAGE_VX 0x40 /* Vx */
#define HID_DESKTOP_USAGE_VY 0x41 /* Vy */
#define HID_DESKTOP_USAGE_VZ 0x42 /* Vz */
@ -274,7 +274,7 @@
#define HID_DESKTOP_USAGE_VNO 0x46 /* Vno */
#define HID_DESKTOP_USAGE_FEATURE 0x47 /* Feature Notification */
#define HID_DESKTOP_USAGE_RESOLUTION 0x48 /* Resolution Multiplier */
/* 0x49-7f Reserved */
/* 0x49-7f Reserved */
#define HID_DESKTOP_USAGE_CONTROL 0x80 /* System Control */
#define HID_DESKTOP_USAGE_POWERDOWN 0x81 /* System Power Down */
#define HID_DESKTOP_USAGE_SLEEP 0x82 /* System Sleep */
@ -295,7 +295,7 @@
#define HID_DESKTOP_USAGE_DPAD_DOWN 0x91 /* D-pad Down */
#define HID_DESKTOP_USAGE_DPAD_RIGHT 0x92 /* D-pad Right */
#define HID_DESKTOP_USAGE_DPAD_LEFT 0x93 /* D-pad Left */
/* 0x94-9f Reserved */
/* 0x94-9f Reserved */
#define HID_DESKTOP_USAGE_DOCK 0xa0 /* System Dock */
#define HID_DESKTOP_USAGE_UNDOCK 0xa1 /* System Undock */
#define HID_DESKTOP_USAGE_SETUP 0xa2 /* System Setup */
@ -305,7 +305,7 @@
#define HID_DESKTOP_USAGE_APP_DEBUG_BREAK 0xa6 /* Application Debugger Break */
#define HID_DESKTOP_USAGE_MUTE 0xa7 /* System Speaker Mute */
#define HID_DESKTOP_USAGE_HIBERNATE 0xa8 /* System Hibernate */
/* 0xa9-af Reserved */
/* 0xa9-af Reserved */
#define HID_DESKTOP_USAGE_DISPLAY_INVERT 0xb0 /* System Display Invert */
#define HID_DESKTOP_USAGE_DISPALY_INTERNAL 0xb1 /* System Display Internal */
#define HID_DESKTOP_USAGE_DISPLAY_EXTERNAL 0xb2 /* System Display External */
@ -314,7 +314,7 @@
#define HID_DESKTOP_USAGE_DISPLAY_TOGGLE 0xb5 /* System Display Toggle Int/Ext */
#define HID_DESKTOP_USAGE_DISPLAY_SWAP 0xb6 /* System Display Swap */
#define HID_DESKTOP_USAGE_ 0xb7 /* System Display LCD Autoscale */
/* 0xb8-ffff Reserved */
/* 0xb8-ffff Reserved */
/* Keyboard usage IDs (HuT 10) */
#define HID_KBD_USAGE_NONE 0x00 /* Reserved (no event indicated) */
@ -529,16 +529,16 @@
/* HID Report Definitions */
struct usb_hid_class_subdescriptor {
uint8_t bDescriptorType;/* Class descriptor type (See 7.1) */
uint16_t wDescriptorLength;/* Size of the report descriptor */
uint8_t bDescriptorType; /* Class descriptor type (See 7.1) */
uint16_t wDescriptorLength; /* Size of the report descriptor */
} __PACKED;
struct usb_hid_descriptor {
uint8_t bLength; /* Size of the HID descriptor */
uint8_t bDescriptorType;/* HID descriptor type */
uint16_t bcdHID;/* HID class specification release */
uint8_t bCountryCode;/* Country code */
uint8_t bNumDescriptors;/* Number of descriptors (>=1) */
uint8_t bLength; /* Size of the HID descriptor */
uint8_t bDescriptorType; /* HID descriptor type */
uint16_t bcdHID; /* HID class specification release */
uint8_t bCountryCode; /* Country code */
uint8_t bNumDescriptors; /* Number of descriptors (>=1) */
/*
* Specification says at least one Class Descriptor needs to
@ -550,11 +550,10 @@ struct usb_hid_descriptor {
/* Standard Reports *********************************************************/
/* Keyboard input report (8 bytes) (HID B.1) */
struct usb_hid_kbd_report
{
uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
uint8_t reserved;
uint8_t key[6]; /* Keycode 1-6 */
struct usb_hid_kbd_report {
uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
uint8_t reserved;
uint8_t key[6]; /* Keycode 1-6 */
};
/* Keyboard output report (1 byte) (HID B.1),
@ -562,22 +561,109 @@ struct usb_hid_kbd_report
*/
/* Mouse input report (HID B.2) */
struct usb_hid_mouse_report
{
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
int8_t xdisp; /* X displacement */
int8_t ydisp; /* y displacement */
struct usb_hid_mouse_report {
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
int8_t xdisp; /* X displacement */
int8_t ydisp; /* y displacement */
/* Device specific additional bytes may follow */
uint8_t wdisp; /* Wheel displacement */
uint8_t wdisp; /* Wheel displacement */
};
/* Joystick input report (1 bytes) (HID D.1) */
struct usb_hid_js_report
{
int8_t xpos; /* X position */
int8_t ypos; /* X position */
uint8_t buttons; /* See USBHID_JSIN_* definitions */
uint8_t throttle; /* Throttle */
struct usb_hid_js_report {
int8_t xpos; /* X position */
int8_t ypos; /* X position */
uint8_t buttons; /* See USBHID_JSIN_* definitions */
uint8_t throttle; /* Throttle */
};
// clang-format off
#define HID_MOUSE_DESCRIPTOR_LEN (9 + 9 + 7)
#define HID_MOUSE_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
0x09, /* bLength: Interface Descriptor size */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
0x00, /* bAlternateSetting: Alternate setting */ \
0x01, /* bNumEndpoints */ \
0x03, /* bInterfaceClass: HID */ \
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
0x00, /* iInterface: Index of string descriptor */ \
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 */ \
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
0x07, /* bLength: Endpoint Descriptor size */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
int_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
0x03, /* bmAttributes: Interrupt endpoint */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
bInterval /* bInterval: Polling Interval */
#define HID_KEYBOARD_DESCRIPTOR_LEN (9 + 9 + 7)
#define HID_KEYBOARD_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
0x09, /* bLength: Interface Descriptor size */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
0x00, /* bAlternateSetting: Alternate setting */ \
0x01, /* bNumEndpoints */ \
0x03, /* bInterfaceClass: HID */ \
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
0x00, /* iInterface: Index of string descriptor */ \
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 */ \
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
0x07, /* bLength: Endpoint Descriptor size */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
int_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
0x03, /* bmAttributes: Interrupt endpoint */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
bInterval /* bInterval: Polling Interval */
#define HID_CUSTOM_INOUT_DESCRIPTOR_LEN (9 + 9 + 7 + 7)
#define HID_CUSTOM_INOUT_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, in_ep, out_ep,wMaxPacketSize, bInterval) \
0x09, /* bLength: Interface Descriptor size */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
0x00, /* bAlternateSetting: Alternate setting */ \
0x02, /* bNumEndpoints */ \
0x03, /* bInterfaceClass: HID */ \
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
0x00, /* iInterface: Index of string descriptor */ \
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 */ \
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
0x07, /* bLength: Endpoint Descriptor size */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
in_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
0x03, /* bmAttributes: Interrupt endpoint */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
bInterval, /* bInterval: Polling Interval */ \
0x07, /* bLength: Endpoint Descriptor size */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
out_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
0x03, /* bmAttributes: Interrupt endpoint */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
bInterval /* bInterval: Polling Interval */
// clang-format on
#endif /* USB_HID_H */

View File

@ -648,12 +648,12 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
static void usbh_hub_thread(void *argument)
static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
struct usbh_hub *hub;
int ret = 0;
struct usbh_bus *bus = (struct usbh_bus *)argument;
struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
usb_hc_init(bus);
while (1) {

View File

@ -60,7 +60,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbdev_msc_thread(void *argument);
static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#endif
static void usdb_msc_set_max_lun(uint8_t busid)
@ -911,11 +911,11 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
}
#if defined(CONFIG_USBDEV_MSC_THREAD)
static void usbdev_msc_thread(void *argument)
static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uintptr_t event;
int ret;
uint8_t busid = (uint8_t)(uint32_t)argument;
uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
while (1) {
ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);

View File

@ -13,8 +13,11 @@
#define DEV_FORMAT "/dev/sd%c"
#define MSC_INQUIRY_TIMEOUT 500
#ifndef CONFIG_USBHOST_MSC_READY_CHECK_TIMES
#define CONFIG_USBHOST_MSC_READY_CHECK_TIMES 10
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_cbw_csw[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
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];
@ -131,7 +134,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("cbw transfer error\r\n");
USB_LOG_ERR("cbw transfer error: %d\r\n", nbytes);
goto __err_exit;
}
@ -150,7 +153,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
}
if (nbytes < 0) {
USB_LOG_ERR("msc data transfer error\r\n");
USB_LOG_ERR("msc data transfer error: %d\r\n", nbytes);
goto __err_exit;
}
}
@ -159,7 +162,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
memset(csw, 0, USB_SIZEOF_MSC_CSW);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("csw transfer error\r\n");
USB_LOG_ERR("csw transfer error: %d\r\n", nbytes);
goto __err_exit;
}
@ -184,14 +187,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
}
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
@ -199,7 +202,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@ -209,7 +212,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
}
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
@ -217,7 +220,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@ -227,7 +230,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_INQUIRY;
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
}
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
@ -235,7 +238,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@ -244,7 +247,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
}
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
@ -252,18 +255,18 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
memcpy(g_msc_cbw_csw[msc_class->sdchar - 'a'], message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_msc_modeswitch_config *config;
int ret;
struct usbh_msc *msc_class = usbh_msc_class_alloc();
if (msc_class == NULL) {
@ -315,34 +318,6 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
}
}
ret = usbh_msc_scsi_testunitready(msc_class);
if (ret < 0) {
ret = usbh_msc_scsi_requestsense(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
return ret;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
return ret;
}
ret = usbh_msc_scsi_readcapacity10(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
return ret;
}
if (msc_class->blocksize > 0) {
USB_LOG_INFO("Capacity info:\r\n");
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
} else {
USB_LOG_ERR("Invalid block size\r\n");
return -USB_ERR_RANGE;
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
@ -377,12 +352,52 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
int usbh_msc_scsi_init(struct usbh_msc *msc_class)
{
int ret;
uint16_t cnt;
cnt = 0;
while (usbh_msc_scsi_testunitready(msc_class) < 0) {
USB_LOG_WRN("Device not ready, try again...\r\n");
ret = usbh_msc_scsi_requestsense(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
}
cnt++;
if (cnt > CONFIG_USBHOST_MSC_READY_CHECK_TIMES) {
return -USB_ERR_NODEV;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
return ret;
}
ret = usbh_msc_scsi_readcapacity10(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
return ret;
}
if (msc_class->blocksize > 0) {
USB_LOG_INFO("Capacity info:\r\n");
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
} else {
USB_LOG_ERR("Invalid block size\r\n");
return -USB_ERR_RANGE;
}
return 0;
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@ -393,7 +408,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[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)
@ -401,7 +416,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@ -413,7 +428,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)

View File

@ -32,6 +32,7 @@ struct usbh_msc_modeswitch_config {
};
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
int usbh_msc_scsi_init(struct usbh_msc *msc_class);
int usbh_msc_scsi_write10(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);

View File

@ -670,7 +670,7 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class)
return 0;
}
void usbh_asix_rx_thread(void *argument)
void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uint32_t g_asix_rx_length;
int ret;
@ -683,7 +683,7 @@ void usbh_asix_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create asix rx thread\r\n");
// clang-format off
find_class:

View File

@ -168,7 +168,7 @@ void usbh_asix_stop(struct usbh_asix *asix_class);
uint8_t *usbh_asix_get_eth_txbuf(void);
int usbh_asix_eth_output(uint32_t buflen);
void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_asix_rx_thread(void *argument);
void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#ifdef __cplusplus
}

View File

@ -2130,7 +2130,7 @@ static int usbh_rtl8152_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
void usbh_rtl8152_rx_thread(void *argument)
void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uint32_t g_rtl8152_rx_length;
int ret;
@ -2142,7 +2142,7 @@ void usbh_rtl8152_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
// clang-format off
find_class:

View File

@ -59,7 +59,7 @@ void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
uint8_t *usbh_rtl8152_get_eth_txbuf(void);
int usbh_rtl8152_eth_output(uint32_t buflen);
void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_rtl8152_rx_thread(void *argument);
void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#ifdef __cplusplus
}

View File

@ -347,7 +347,7 @@ static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
void usbh_bl616_rx_thread(void *argument)
void usbh_bl616_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
usb_data_t *usb_hdr;
@ -356,7 +356,7 @@ void usbh_bl616_rx_thread(void *argument)
rnm_scan_ind_msg_t *scanmsg;
uint8_t *data;
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create bl616 wifi rx thread\r\n");
while (1) {

View File

@ -205,7 +205,7 @@ void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t
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_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
void usbh_bl616_run(struct usbh_bl616 *bl616_class);
void usbh_bl616_stop(struct usbh_bl616 *bl616_class);

View File

@ -37,14 +37,17 @@ struct usbd_rndis_priv {
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
#endif
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
volatile uint8_t *g_rndis_rx_data_buffer;
volatile uint32_t g_rndis_rx_data_length;
volatile uint32_t g_rndis_rx_total_length;
volatile uint32_t g_rndis_tx_data_length;
/* RNDIS options list */
@ -447,12 +450,14 @@ static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
switch (event) {
case USBD_EVENT_RESET:
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
break;
case USBD_EVENT_CONFIGURED:
g_rndis_rx_data_length = 0;
g_rndis_tx_data_length = 0;
break;
case USBD_EVENT_CONFIGURED:
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
#endif
break;
default:
@ -467,10 +472,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
(void)busid;
(void)ep;
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
hdr = (rndis_data_packet_t *)g_rndis_rx_data_buffer;
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length);
return;
}
@ -503,6 +507,34 @@ void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
//USB_LOG_DBG("len:%d\r\n", nbytes);
}
int usbd_rndis_start_write(uint8_t *buf, uint32_t len)
{
if (!usb_device_is_configured(0)) {
return -USB_ERR_NODEV;
}
if (g_rndis_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
g_rndis_tx_data_length = len;
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, buf, len);
}
int usbd_rndis_start_read(uint8_t *buf, uint32_t len)
{
if (!usb_device_is_configured(0)) {
return -USB_ERR_NODEV;
}
g_rndis_rx_data_buffer = buf;
g_rndis_rx_total_length = len;
g_rndis_rx_data_length = 0;
return usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, buf, len);
}
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
#include <lwip/pbuf.h>
@ -515,15 +547,14 @@ struct pbuf *usbd_rndis_eth_rx(void)
}
p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
if (p == NULL) {
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return NULL;
}
usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
p->len = g_rndis_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
g_rndis_rx_data_length = 0;
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return p;
}
@ -594,6 +625,11 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
return intf;
}
void usbd_rndis_set_connect(bool connect)
{
g_usbd_rndis.link_status = connect ? NDIS_MEDIA_STATE_CONNECTED : NDIS_MEDIA_STATE_DISCONNECTED;
}
__WEAK void usbd_rndis_data_recv_done(uint32_t len)
{
(void)len;
@ -602,4 +638,4 @@ __WEAK void usbd_rndis_data_recv_done(uint32_t len)
__WEAK void usbd_rndis_data_send_done(uint32_t len)
{
(void)len;
}
}

View File

@ -18,8 +18,12 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep, uint8_t mac[6]);
void usbd_rndis_set_connect(bool connect);
void usbd_rndis_data_recv_done(uint32_t len);
void usbd_rndis_data_send_done(uint32_t len);
int usbd_rndis_start_write(uint8_t *buf, uint32_t len);
int usbd_rndis_start_read(uint8_t *buf, uint32_t len);
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
struct pbuf *usbd_rndis_eth_rx(void);

View File

@ -189,7 +189,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
return ret;
}
void usbh_bluetooth_hci_rx_thread(void *argument)
void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
uint32_t ep_mps;
@ -271,7 +271,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
return ret;
}
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
uint32_t ep_mps;
@ -320,7 +320,7 @@ delete :
// clang-format on
}
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
uint32_t ep_mps;

View File

@ -40,10 +40,10 @@ extern "C" {
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
void usbh_bluetooth_hci_rx_thread(void *argument);
void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#else
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#endif
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);

View File

@ -90,8 +90,8 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
rndis_class->max_transfer_size = resp->MaxTransferSize;
USB_LOG_INFO("MaxPacketsPerTransfer:%d\r\n", resp->MaxPacketsPerTransfer);
USB_LOG_INFO("MaxTransferSize:%d\r\n", resp->MaxTransferSize);
USB_LOG_INFO("MaxPacketsPerTransfer:%ld\r\n", resp->MaxPacketsPerTransfer);
USB_LOG_INFO("MaxTransferSize:%ld\r\n", resp->MaxTransferSize);
return ret;
}
@ -278,8 +278,8 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint32_t *oid_support_list;
unsigned int oid = 0;
unsigned int oid_num = 0;
uint32_t oid = 0;
uint32_t oid_num = 0;
uint32_t data_len;
uint8_t tmp_buffer[512];
uint8_t data[32];
@ -319,7 +319,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
oid_num = (data_len / 4);
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%ld\r\n", oid_num);
oid_support_list = (uint32_t *)tmp_buffer;
@ -380,10 +380,10 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
}
break;
default:
USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
USB_LOG_WRN("Ignore rndis query iod:%08lx\r\n", oid);
continue;
}
USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
USB_LOG_INFO("rndis query iod:%08lx success\r\n", oid);
}
uint32_t packet_filter = 0x0f;
@ -414,7 +414,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
usbh_rndis_run(rndis_class);
return ret;
query_errorout:
USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
USB_LOG_ERR("rndis query iod:%08lx error\r\n", oid);
return ret;
}
@ -448,7 +448,7 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
void usbh_rndis_rx_thread(void *argument)
void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uint32_t g_rndis_rx_length;
int ret;
@ -461,7 +461,7 @@ void usbh_rndis_rx_thread(void *argument)
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
USB_LOG_INFO("Create rndis rx thread\r\n");
// clang-format off
@ -501,7 +501,7 @@ find_class:
uint32_t total_len = g_rndis_rx_length;
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
USB_LOG_DBG("rxlen:%ld\r\n", g_rndis_rx_length);
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
@ -523,7 +523,7 @@ find_class:
g_rndis_rx_length = 0;
}
} else {
USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
USB_LOG_ERR("offset:%ld,remain:%ld,total:%ld\r\n", pmg_offset, g_rndis_rx_length, total_len);
g_rndis_rx_length = 0;
USB_LOG_ERR("Error rndis packet message\r\n");
}

View File

@ -46,7 +46,7 @@ void usbh_rndis_stop(struct usbh_rndis *rndis_class);
uint8_t *usbh_rndis_get_eth_txbuf(void);
int usbh_rndis_eth_output(uint32_t buflen);
void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_rndis_rx_thread(void *argument);
void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
#ifdef __cplusplus
}

View File

@ -136,7 +136,7 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
*/
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
/* usb dcd irq callback */
/* usb dcd irq callback, called by user */
/**
* @brief Usb connect irq callback.
@ -194,6 +194,9 @@ void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
#endif
/* called by user */
void USBD_IRQHandler(uint8_t busid);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_DCACHE_H
#define USB_DCACHE_H
#ifdef CONFIG_USB_DCACHE_ENABLE
#if CONFIG_USB_ALIGN_SIZE % 32
#error "CONFIG_USB_ALIGN_SIZE must be multiple of 32"
#endif
#else
#define usb_dcache_clean(addr, size)
#define usb_dcache_invalidate(addr, size)
#define usb_dcache_flush(addr, size)
#endif
#endif /* USB_DCACHE_H */

View File

@ -108,6 +108,9 @@ int usbh_submit_urb(struct usbh_urb *urb);
*/
int usbh_kill_urb(struct usbh_urb *urb);
/* called by user */
void USBH_IRQHandler(uint8_t busid);
#ifdef __cplusplus
}
#endif

View File

@ -86,12 +86,12 @@ void usb_assert(const char *filename, int linenum);
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
{
unsigned char *buf = (unsigned char *)ptr;
uint32_t i, j;
unsigned int i, j;
(void)buf;
for (i = 0; i < buflen; i += 16) {
CONFIG_USB_PRINTF("%08X:", i);
CONFIG_USB_PRINTF("%08x:", i);
for (j = 0; j < 16; j++)
if (i + j < buflen) {

View File

@ -10,13 +10,21 @@
#include <string.h>
#include <stdbool.h>
#ifdef __INCLUDE_NUTTX_CONFIG_H
#define CONFIG_USB_OSAL_THREAD_SET_ARGV int argc, char **argv
#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)strtoul(argv[1], NULL, 16))
#else
#define CONFIG_USB_OSAL_THREAD_SET_ARGV void *argument
#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)argument)
#endif
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
typedef void *usb_osal_thread_t;
typedef void *usb_osal_sem_t;
typedef void *usb_osal_mutex_t;
typedef void *usb_osal_mq_t;
typedef void (*usb_thread_entry_t)(void *argument);
typedef void (*usb_thread_entry_t)(CONFIG_USB_OSAL_THREAD_SET_ARGV);
typedef void (*usb_timer_handler_t)(void *argument);
struct usb_osal_timer {
usb_timer_handler_t handler;

View File

@ -207,4 +207,12 @@
#define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
#ifndef usb_phyaddr2ramaddr
#define usb_phyaddr2ramaddr(addr) (addr)
#endif
#ifndef usb_ramaddr2phyaddr
#define usb_ramaddr2phyaddr(addr) (addr)
#endif
#endif /* USB_UTIL_H */

View File

@ -4,6 +4,17 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#ifdef CONFIG_USBDEV_EP0_THREAD
#include "usb_osal.h"
#define USB_EP0_STATE_SETUP 0
#define USB_EP0_STATE_IN 1
#define USB_EP0_STATE_OUT 2
#endif
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbd_core"
#include "usb_log.h"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
@ -62,6 +73,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
#endif
#ifdef CONFIG_USBDEV_TEST_MODE
bool test_req;
#endif
#ifdef CONFIG_USBDEV_EP0_THREAD
usb_osal_mq_t usbd_ep0_mq;
usb_osal_thread_t usbd_ep0_thread;
#endif
struct usbd_interface *intf[16];
uint8_t intf_altsetting[16];
@ -431,8 +446,8 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t
}
/* skip to next descriptor */
p += p[DESC_bLength];
current_desc_len += p[DESC_bLength];
p += p[DESC_bLength];
if (current_desc_len >= desc_len && desc_len) {
break;
}
@ -497,7 +512,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
if (alt_setting == 0) {
ret = usbd_reset_endpoint(busid, ep_desc);
goto find_end;
} else if (cur_alt_setting == alt_setting) {
ret = usbd_set_endpoint(busid, ep_desc);
} else {
@ -511,14 +525,13 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
}
/* skip to next descriptor */
p += p[DESC_bLength];
current_desc_len += p[DESC_bLength];
p += p[DESC_bLength];
if (current_desc_len >= desc_len && desc_len) {
break;
}
}
find_end:
usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
return ret;
@ -685,8 +698,8 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
}
/* skip to next descriptor */
p += p[DESC_bLength];
current_desc_len += p[DESC_bLength];
p += p[DESC_bLength];
if (current_desc_len >= desc_len && desc_len) {
break;
}
@ -1125,12 +1138,10 @@ void usbd_event_reset_handler(uint8_t busid)
g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESET);
}
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
static void __usbd_event_ep0_setup_complete_handler(uint8_t busid, struct usb_setup_packet *setup)
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
uint8_t *buf;
memcpy(setup, psetup, 8);
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
usbd_print_setup(setup);
#endif
@ -1195,7 +1206,20 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
}
}
void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
memcpy(setup, psetup, 8);
#ifdef CONFIG_USBDEV_EP0_THREAD
usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_SETUP);
#else
__usbd_event_ep0_setup_complete_handler(busid, setup);
#endif
}
static void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
@ -1236,11 +1260,12 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
}
}
void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
static void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
(void)ep;
(void)setup;
if (nbytes > 0) {
g_usbd_core[busid].ep0_data_buf += nbytes;
@ -1249,6 +1274,9 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core[busid].ep0_data_buf_residue);
if (g_usbd_core[busid].ep0_data_buf_residue == 0) {
#ifdef CONFIG_USBDEV_EP0_THREAD
usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_OUT);
#else
/* Received all, send data to handler */
g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data;
if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) {
@ -1258,6 +1286,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
/*Send status to host*/
usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0);
#endif
} else {
/* Start reading the remain data */
usbd_ep_start_read(busid, USB_CONTROL_OUT_EP0, g_usbd_core[busid].ep0_data_buf, g_usbd_core[busid].ep0_data_buf_residue);
@ -1396,6 +1425,47 @@ int usbd_send_remote_wakeup(uint8_t busid)
}
}
#ifdef CONFIG_USBDEV_EP0_THREAD
static void usbdev_ep0_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
uintptr_t event;
int ret;
uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
while (1) {
ret = usb_osal_mq_recv(g_usbd_core[busid].usbd_ep0_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
USB_LOG_DBG("event:%d\r\n", event);
switch (event) {
case USB_EP0_STATE_SETUP:
__usbd_event_ep0_setup_complete_handler(busid, setup);
break;
case USB_EP0_STATE_IN:
// do nothing
break;
case USB_EP0_STATE_OUT:
/* Received all, send data to handler */
g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data;
if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) {
usbd_ep_set_stall(busid, USB_CONTROL_IN_EP0);
continue;
}
/*Send status to host*/
usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0);
break;
default:
break;
}
}
}
#endif
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
{
int ret;
@ -1410,6 +1480,21 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin
bus = &g_usbdev_bus[busid];
bus->reg_base = reg_base;
#ifdef CONFIG_USBDEV_EP0_THREAD
g_usbd_core[busid].usbd_ep0_mq = usb_osal_mq_create(1);
if (g_usbd_core[busid].usbd_ep0_mq == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_mq\r\n");
while (1) {
}
}
g_usbd_core[busid].usbd_ep0_thread = usb_osal_thread_create("usbd_ep0", CONFIG_USBDEV_EP0_STACKSIZE, CONFIG_USBDEV_EP0_PRIO, usbdev_ep0_thread, (void *)(uint32_t)busid);
if (g_usbd_core[busid].usbd_ep0_thread == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_thread\r\n");
while (1) {
}
}
#endif
g_usbd_core[busid].event_handler = event_handler;
ret = usb_dc_init(busid);
usbd_class_event_notify_handler(busid, USBD_EVENT_INIT, NULL);
@ -1429,5 +1514,14 @@ int usbd_deinitialize(uint8_t busid)
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
usb_dc_deinit(busid);
g_usbd_core[busid].intf_offset = 0;
#ifdef CONFIG_USBDEV_EP0_THREAD
if (g_usbd_core[busid].usbd_ep0_mq) {
usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq);
}
if (g_usbd_core[busid].usbd_ep0_thread) {
usb_osal_thread_delete(g_usbd_core[busid].usbd_ep0_thread);
}
#endif
return 0;
}

View File

@ -324,6 +324,17 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport)
}
}
static void usbh_print_setup(struct usb_setup_packet *setup)
{
USB_LOG_DBG("Setup: "
"bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
setup->bmRequestType,
setup->bRequest,
setup->wValue,
setup->wIndex,
setup->wLength);
}
static int usbh_get_default_mps(int speed)
{
switch (speed) {
@ -674,10 +685,16 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
struct usbh_urb *urb;
int ret;
if (!hport || !setup) {
return -USB_ERR_INVAL;
}
urb = &hport->ep0_urb;
usb_osal_mutex_take(hport->mutex);
usbh_print_setup(setup);
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
@ -841,7 +858,11 @@ static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t
if (hub->index == hub_index) {
hport = &hub->child[hub_port - 1];
return hport;
if (hport->connected) {
return hport;
} else {
return NULL;
}
} else {
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
@ -865,6 +886,7 @@ static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t
}
return NULL;
}
void *usbh_find_class_instance(const char *devname)
{
usb_slist_t *bus_list;

View File

@ -21,6 +21,7 @@
#include "usb_osal.h"
#include "usbh_hub.h"
#include "usb_memcpy.h"
#include "usb_dcache.h"
#include "usb_version.h"
#ifdef __cplusplus

View File

@ -108,6 +108,70 @@ struct usb_msosv1_descriptor msosv1_desc = {
.comp_id_property = WINUSB_IFx_WCIDProperties,
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
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)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryADB", /* Product */
"CherryADB2024", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor msc_bootuf2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.msosv1_descriptor = &msosv1_desc
};
#else
/*!< global descriptor */
static const uint8_t adb_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
@ -171,15 +235,16 @@ static const uint8_t adb_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -222,7 +287,14 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base)
}
}
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &adb_descriptor);
#else
usbd_desc_register(busid, adb_descriptor);
#endif
#ifndef CONFIG_USBDEV_ADVANCE_DESC
usbd_msosv1_desc_register(busid, &msosv1_desc);
#endif
usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@ -68,6 +68,73 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ))
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UAC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor audio_v1_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -125,12 +192,12 @@ const uint8_t audio_v1_descriptor[] = {
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'1', 0x00, /* wcChar3 */
'0', 0x00, /* wcChar4 */
'3', 0x00, /* wcChar5 */
'1', 0x00, /* wcChar6 */
'0', 0x00, /* wcChar7 */
'0', 0x00, /* wcChar8 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'0' + IN_CHANNEL_NUM, 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
@ -149,6 +216,7 @@ const uint8_t audio_v1_descriptor[] = {
#endif
0x00
};
#endif
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
@ -214,7 +282,11 @@ struct audio_entity_info audio_entity_table[] = {
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &audio_v1_descriptor);
#else
usbd_desc_register(busid, audio_v1_descriptor);
#endif
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(busid, &audio_in_ep);

View File

@ -6,19 +6,24 @@
#include "usbd_core.h"
#include "usbd_audio.h"
#define USING_FEEDBACK 0
#define USBD_VID 0xffff
#define USBD_PID 0xffff
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#ifdef CONFIG_USB_HS
#define EP_INTERVAL 0x04
#define EP_INTERVAL 0x04
#define FEEDBACK_ENDP_PACKET_SIZE 0x04
#else
#define EP_INTERVAL 0x01
#define EP_INTERVAL 0x01
#define FEEDBACK_ENDP_PACKET_SIZE 0x03
#endif
#define AUDIO_IN_EP 0x81
#define AUDIO_OUT_EP 0x02
#define AUDIO_OUT_FEEDBACK_EP 0x83
#define AUDIO_IN_FU_ID 0x02
#define AUDIO_OUT_FU_ID 0x05
@ -38,6 +43,7 @@
/* 16bit(2 Bytes) 双声道(Mono:2) */
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_MIC_FREQ * AUDIO_MIC_FRAME_SIZE_BYTE * 2) / 1000))
#if USING_FEEDBACK == 0
#define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 + \
AUDIO_AC_DESCRIPTOR_INIT_LEN(2) + \
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
@ -48,6 +54,18 @@
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
AUDIO_AS_DESCRIPTOR_INIT_LEN(1) + \
AUDIO_AS_DESCRIPTOR_INIT_LEN(1))
#else
#define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 + \
AUDIO_AC_DESCRIPTOR_INIT_LEN(2) + \
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
AUDIO_AS_DESCRIPTOR_INIT_LEN(1) + \
AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT_LEN(1))
#endif
#define AUDIO_AC_SIZ (AUDIO_SIZEOF_AC_HEADER_DESC(2) + \
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
@ -57,6 +75,84 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
#if USING_FEEDBACK == 0
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
#else
AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
#endif
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ))
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UAC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor audio_v1_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -67,8 +163,13 @@ const uint8_t audio_v1_descriptor[] = {
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
#if USING_FEEDBACK == 0
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
#else
AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
#endif
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
///////////////////////////////////////
@ -120,13 +221,17 @@ const uint8_t audio_v1_descriptor[] = {
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'1', 0x00, /* wcChar3 */
'0', 0x00, /* wcChar4 */
'3', 0x00, /* wcChar5 */
'1', 0x00, /* wcChar6 */
'0', 0x00, /* wcChar7 */
'0', 0x00, /* wcChar8 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
#if USING_FEEDBACK == 0
'1', 0x00, /* wcChar9 */
#else
'2', 0x00, /* wcChar9 */
#endif
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
@ -144,9 +249,11 @@ const uint8_t audio_v1_descriptor[] = {
#endif
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
@ -183,6 +290,9 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value); /* uac1 can only use 10.14 */
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
printf("OPEN1\r\n");
} else {
tx_flag = 1;
@ -215,6 +325,16 @@ void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
ep_tx_busy_flag = false;
}
#if USING_FEEDBACK == 1
void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
}
#endif
static struct usbd_endpoint audio_in_ep = {
.ep_cb = usbd_audio_in_callback,
.ep_addr = AUDIO_IN_EP
@ -225,6 +345,13 @@ static struct usbd_endpoint audio_out_ep = {
.ep_addr = AUDIO_OUT_EP
};
#if USING_FEEDBACK == 1
static struct usbd_endpoint audio_out_feedback_ep = {
.ep_cb = usbd_audio_iso_out_feedback_callback,
.ep_addr = AUDIO_OUT_FEEDBACK_EP
};
#endif
struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
@ -240,13 +367,19 @@ struct audio_entity_info audio_entity_table[] = {
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &audio_v1_descriptor);
#else
usbd_desc_register(busid, audio_v1_descriptor);
#endif
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_add_endpoint(busid, &audio_out_ep);
#if USING_FEEDBACK == 1
usbd_add_endpoint(busid, &audio_out_feedback_ep);
#endif
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@ -72,6 +72,74 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_INTERM_MIC, 0x01, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, INPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x03, 0x01, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x04, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UAC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor audio_v2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -154,6 +222,7 @@ const uint8_t audio_v2_descriptor[] = {
#endif
0x00
};
#endif
static const uint8_t mic_default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_NUM(1),
@ -162,7 +231,10 @@ static const uint8_t mic_default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_4B(0x00)
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -210,6 +282,7 @@ void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sam
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
ep_tx_busy_flag = false;
}
static struct usbd_endpoint audio_in_ep = {
@ -231,7 +304,11 @@ struct audio_entity_info audio_entity_table[] = {
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &audio_v2_descriptor);
#else
usbd_desc_register(busid, audio_v2_descriptor);
#endif
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
@ -242,5 +319,13 @@ void audio_v2_init(uint8_t busid, uintptr_t reg_base)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
}
}
}

View File

@ -114,6 +114,79 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x05, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UAC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor audio_v2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -201,6 +274,7 @@ uint8_t audio_v2_descriptor[] = {
#endif
0x00
};
#endif
static const uint8_t speaker_default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_NUM(5),
@ -233,6 +307,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -293,20 +368,6 @@ void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sam
}
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
uint16_t packet_size = 0;
if (ep == AUDIO_OUT_EP) {
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
} else if (ep == AUDIO_IN_EP) {
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
}
}
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
@ -348,7 +409,11 @@ struct audio_entity_info audio_entity_table[] = {
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &audio_v2_descriptor);
#else
usbd_desc_register(busid, audio_v2_descriptor);
#endif
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
@ -361,6 +426,14 @@ void audio_v2_init(uint8_t busid, uintptr_t reg_base)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
}
}
if (rx_flag) {
}

View File

@ -6,18 +6,23 @@
#include "usbd_core.h"
#include "usbd_audio.h"
#define USING_FEEDBACK 0
#define USBD_VID 0xffff
#define USBD_PID 0xffff
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#ifdef CONFIG_USB_HS
#define EP_INTERVAL 0x04
#define EP_INTERVAL 0x04
#define FEEDBACK_ENDP_PACKET_SIZE 0x04
#else
#define EP_INTERVAL 0x01
#define EP_INTERVAL 0x01
#define FEEDBACK_ENDP_PACKET_SIZE 0x03
#endif
#define AUDIO_OUT_EP 0x01
#define AUDIO_OUT_EP 0x01
#define AUDIO_OUT_FEEDBACK_EP 0x82
#define AUDIO_OUT_CLOCK_ID 0x01
#define AUDIO_OUT_FU_ID 0x03
@ -58,6 +63,7 @@
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
#if USING_FEEDBACK == 0
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@ -65,6 +71,15 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
#else
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN)
#endif
#define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@ -72,6 +87,78 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
#if USING_FEEDBACK == 0
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
#else
AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
#endif
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UAC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor audio_v2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -80,7 +167,11 @@ const uint8_t audio_v2_descriptor[] = {
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
#if USING_FEEDBACK == 0
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
#else
AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
#endif
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@ -136,7 +227,11 @@ const uint8_t audio_v2_descriptor[] = {
'1', 0x00, /* wcChar6 */
'0', 0x00, /* wcChar7 */
'0', 0x00, /* wcChar8 */
'3', 0x00, /* wcChar9 */
#if USING_FEEDBACK == 0
'3', 0x00, /* wcChar9 */
#else
'4', 0x00, /* wcChar9 */
#endif
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
@ -154,6 +249,7 @@ const uint8_t audio_v2_descriptor[] = {
#endif
0x00
};
#endif
static const uint8_t default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_NUM(5),
@ -175,6 +271,7 @@ static const uint8_t default_sampling_freq_table[] = {
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
volatile bool rx_flag = 0;
@ -208,6 +305,14 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
#ifdef CONFIG_USB_HS
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
#else
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
#endif
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
USB_LOG_RAW("OPEN\r\n");
}
@ -230,11 +335,33 @@ void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
#if USING_FEEDBACK == 1
void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
#ifdef CONFIG_USB_HS
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
#else
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
#endif
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
}
#endif
static struct usbd_endpoint audio_out_ep = {
.ep_cb = usbd_audio_iso_out_callback,
.ep_addr = AUDIO_OUT_EP
};
#if USING_FEEDBACK == 1
static struct usbd_endpoint audio_out_feedback_ep = {
.ep_cb = usbd_audio_iso_out_feedback_callback,
.ep_addr = AUDIO_OUT_FEEDBACK_EP
};
#endif
struct usbd_interface intf0;
struct usbd_interface intf1;
@ -249,11 +376,17 @@ struct audio_entity_info audio_entity_table[] = {
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &audio_v2_descriptor);
#else
usbd_desc_register(busid, audio_v2_descriptor);
#endif
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_out_ep);
#if USING_FEEDBACK == 1
usbd_add_endpoint(busid, &audio_out_feedback_ep);
#endif
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@ -23,6 +23,69 @@
#define MSC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
};
static const uint8_t config_descriptor[] = {
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)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UF2 DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor msc_bootuf2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
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),
@ -100,6 +163,7 @@ const uint8_t msc_bootuf2_descriptor[] = {
#endif
0x00
};
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -151,7 +215,11 @@ static struct usbd_interface intf0;
void msc_bootuf2_init(uint8_t busid, uintptr_t reg_base)
{
boot2uf2_flash_init();
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &msc_bootuf2_descriptor);
#else
usbd_desc_register(busid, msc_bootuf2_descriptor);
#endif
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);

View File

@ -43,6 +43,101 @@
#define MSC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x03, /* 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 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC MSC HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_acm_hid_msc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t cdc_acm_hid_msc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -152,6 +247,7 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
#endif
0x00
};
#endif
/*!< hid mouse report descriptor */
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@ -303,8 +399,11 @@ struct usbd_interface intf3;
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_acm_hid_msc_descriptor);
#else
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);

View File

@ -54,9 +54,9 @@ static const uint8_t device_quality_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
@ -169,9 +169,9 @@ static const uint8_t cdc_msc_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,

View File

@ -37,8 +37,74 @@
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, CDC_MAX_MPS, 0x02)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC MULTI DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_multi_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
static const uint8_t cdc_multi_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
@ -109,15 +175,16 @@ static const uint8_t cdc_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[4][2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048];
@ -225,8 +292,11 @@ struct usbd_interface intf7;
void cdc_acm_multi_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, cdc_descriptor);
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_multi_descriptor);
#else
usbd_desc_register(busid, cdc_multi_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep1);

View File

@ -25,6 +25,69 @@
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
@ -94,15 +157,16 @@ static const uint8_t cdc_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@ -181,7 +245,11 @@ void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
memcpy(&write_buffer[0], data, 10);
memset(&write_buffer[10], 'a', 2038);
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_descriptor);
#else
usbd_desc_register(busid, cdc_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);

View File

@ -34,6 +34,69 @@
/* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
#define CDC_ECM_MAC_STRING_INDEX 4
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ECM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, CDC_ECM_ETH_STATISTICS_BITMAP, CONFIG_CDC_ECM_ETH_MAX_SEGSZE, 0, 0, CDC_ECM_MAC_STRING_INDEX)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC ECM DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_ecm_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_ecm_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
@ -124,15 +187,16 @@ static const uint8_t cdc_ecm_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
@ -277,7 +341,11 @@ void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
{
cdc_ecm_lwip_init();
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_ecm_descriptor);
#else
usbd_desc_register(busid, cdc_ecm_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);

View File

@ -29,8 +29,71 @@
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB RNDIS DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_rndis_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
static const uint8_t cdc_rndis_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
@ -100,15 +163,16 @@ static const uint8_t cdc_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
@ -315,7 +379,11 @@ void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
#else
rndis_lwip_init();
#endif
usbd_desc_register(busid, cdc_descriptor);
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_rndis_descriptor);
#else
usbd_desc_register(busid, cdc_rndis_descriptor);
#endif
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_initialize(busid, reg_base, usbd_event_handler);

View File

@ -15,6 +15,69 @@
#define USB_CONFIG_SIZE (9 + 9 + 9)
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
DFU_DESCRIPTOR_INIT()
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB DFU DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor dfu_flash_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t dfu_flash_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),
@ -141,6 +204,7 @@ const uint8_t dfu_flash_descriptor[] = {
#endif
0x00
};
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -171,7 +235,11 @@ struct usbd_interface intf0;
void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &dfu_flash_descriptor);
#else
usbd_desc_register(busid, dfu_flash_descriptor);
#endif
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@ -39,6 +39,103 @@
/*!< custom hid report descriptor size */
#define HID_CUSTOM_REPORT_DESC_SIZE 38
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
/************** Descriptor of Custom interface *****************/
0x09, /* bLength: Interface Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Custom HID ********************/
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_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Custom in endpoint ********************/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
WBVAL(HIDRAW_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
/******************** Descriptor of Custom out endpoint ********************/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
HIDRAW_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
WBVAL(HIDRAW_OUT_EP_SIZE), /* wMaxPacketSize: 4 Byte max */
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
/* 73 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t hid_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@ -151,6 +248,7 @@ static const uint8_t hid_descriptor[] = {
#endif
0x00
};
#endif
/*!< custom hid report descriptor */
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
@ -274,7 +372,11 @@ struct usbd_interface intf0;
void hid_custom_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &hid_descriptor);
#else
usbd_desc_register(busid, hid_descriptor);
#endif
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &custom_in_ep);
usbd_add_endpoint(busid, &custom_out_ep);

View File

@ -18,6 +18,101 @@
#define USB_HID_CONFIG_DESC_SIZ 34
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 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 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
static 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_BUS_POWERED, USBD_MAX_POWER),
@ -127,6 +222,7 @@ static const uint8_t hid_descriptor[] = {
#endif
0x00
};
#endif
/* USB HID device Configuration Descriptor */
static uint8_t hid_desc[9] __ALIGN_END = {
@ -223,7 +319,11 @@ struct usbd_interface intf0;
void hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &hid_descriptor);
#else
usbd_desc_register(busid, hid_descriptor);
#endif
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);

View File

@ -21,6 +21,101 @@
/*!< report descriptor size */
#define HID_MOUSE_REPORT_DESC_SIZE 74
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 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 */
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 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
const uint8_t hid_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@ -131,6 +226,7 @@ const uint8_t hid_descriptor[] = {
#endif
0x00
};
#endif
/*!< hid mouse report descriptor */
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@ -241,7 +337,11 @@ struct usbd_interface intf0;
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &hid_descriptor);
#else
usbd_desc_register(busid, hid_descriptor);
#endif
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);

View File

@ -21,6 +21,101 @@
/*!< report descriptor size */
#define HID_MOUSE_REPORT_DESC_SIZE 74
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
};
static const uint8_t config_descriptor[] = {
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 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
const uint8_t hid_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
@ -131,6 +226,7 @@ const uint8_t hid_descriptor[] = {
#endif
0x00
};
#endif
/*!< hid mouse report descriptor */
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
@ -241,7 +337,11 @@ static struct usbd_interface intf0;
void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &hid_descriptor);
#else
usbd_desc_register(busid, hid_descriptor);
#endif
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);

View File

@ -22,6 +22,118 @@
#define MIDI_EP_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
// Standard AC Interface Descriptor
0x09,
0x04,
0x00,
0x00,
0x00,
0x01,
0x01,
0x00,
0x00,
// Class-specific AC Interface Descriptor
0x09,
0x24,
0x01,
0x00,
0x01,
0x09,
0x00,
0x01,
0x01,
// MIDIStreaming Interface Descriptors
0x09,
0x04,
0x01,
0x00,
0x02,
0x01,
0x03,
0x00,
0x00,
// Class-Specific MS Interface Header Descriptor
0x07,
0x24,
0x01,
0x00,
0x01,
WBVAL(65),
// MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x01),
// MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x02),
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x03, 0x02),
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
MIDI_JACK_DESCRIPTOR_INIT(0x01),
// OUT endpoint descriptor
0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
0x05, 0x25, 0x01, 0x01, 0x01,
// IN endpoint descriptor
0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
0x05, 0x25, 0x01, 0x01, 0x03
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB MIDI DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor midi_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t midi_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -141,15 +253,16 @@ const uint8_t midi_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[MIDI_EP_MPS];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[MIDI_EP_MPS];
@ -204,7 +317,11 @@ struct usbd_endpoint midi_in_ep = {
void midi_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &midi_descriptor);
#else
usbd_desc_register(busid, midi_descriptor);
#endif
usbd_add_interface(busid, &intf0);
usbd_add_interface(busid, &intf1);
usbd_add_endpoint(busid, &midi_out_ep);

View File

@ -22,6 +22,69 @@
#define MSC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
};
static const uint8_t config_descriptor[] = {
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)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB MSC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor msc_ram_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t msc_ram_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),
@ -99,6 +162,7 @@ const uint8_t msc_ram_descriptor[] = {
#endif
0x00
};
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@ -158,7 +222,11 @@ static struct usbd_interface intf0;
void msc_ram_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &msc_ram_descriptor);
#else
usbd_desc_register(busid, msc_ram_descriptor);
#endif
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#ifdef __RT_THREAD_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_storage_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_1_1, 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 */
'M', 0x00, /* wcChar10 */
'S', 0x00, /* wcChar11 */
'C', 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,
0x00,
0x00,
#endif
0x00
};
struct usbd_interface intf0;
/* assume the block device is 512M */
#define BLOCK_DEV_NAME "sd0"
#define BLOCK_SIZE 512U
#define BLOCK_COUNT 0x1024U * 0x1024U
static rt_device_t blk_dev = RT_NULL;
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;
}
}
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = BLOCK_COUNT;
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
rt_device_read(blk_dev, sector, buffer, length / BLOCK_SIZE);
return 0;
}
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
rt_device_write(blk_dev, sector, buffer, length / BLOCK_SIZE);
return 0;
}
void msc_storage_init(uint8_t busid, uintptr_t reg_base)
{
rt_err_t res;
blk_dev = rt_device_find(BLOCK_DEV_NAME);
RT_ASSERT(blk_dev);
res = rt_device_open(blk_dev, RT_DEVICE_OFLAG_RDWR);
RT_ASSERT(res == RT_EOK);
usbd_desc_register(busid, msc_storage_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);
}
#endif

View File

@ -58,10 +58,10 @@ void usbh_cdc_acm_callback(void *arg, int nbytes)
}
}
static void usbh_cdc_acm_thread(void *argument)
static void usbh_cdc_acm_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)argument;
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
/* test with only one buffer, if you have more cdc acm class, modify by yourself */
#if TEST_USBH_CDC_SPEED
@ -133,10 +133,10 @@ void usbh_hid_callback(void *arg, int nbytes)
}
}
static void usbh_hid_thread(void *argument)
static void usbh_hid_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
struct usbh_hid *hid_class = (struct usbh_hid *)argument;
struct usbh_hid *hid_class = (struct usbh_hid *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
;
/* test with only one buffer, if you have more hid class, modify by yourself */
@ -222,13 +222,18 @@ unmount:
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t partition_table[512];
static void usbh_msc_thread(void *argument)
static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
int ret;
struct usbh_msc *msc_class = (struct usbh_msc *)argument;
struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
/* test with only one buffer, if you have more msc class, modify by yourself */
#if 1
#if TEST_USBH_MSC_FATFS == 0
ret = usbh_msc_scsi_init(msc_class);
if (ret < 0) {
USB_LOG_RAW("scsi_init error,ret:%d\r\n", ret);
goto delete;
}
/* get the partition table */
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
if (ret < 0) {
@ -242,11 +247,10 @@ static void usbh_msc_thread(void *argument)
USB_LOG_RAW("%02x ", partition_table[i]);
}
USB_LOG_RAW("\r\n");
#endif
#if TEST_USBH_MSC_FATFS
#else
usb_msc_fatfs_test();
#endif
// clang-format off
delete:
usb_osal_thread_delete(NULL);

View File

@ -103,6 +103,120 @@
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
//VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
AUDIO_AC_DESCRIPTOR_INIT(0x02, 0x03, AUDIO_AC_SIZ, 0x00, 0x03, 0x04),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
AUDIO_AS_DESCRIPTOR_INIT(0x03, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
AUDIO_AS_DESCRIPTOR_INIT(0x04, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x05, /* 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 */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UVC UAC HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor video_audio_hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t video_audio_hid_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -231,6 +345,7 @@ const uint8_t video_audio_hid_descriptor[] = {
#endif
0x00
};
#endif
static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
@ -422,7 +537,11 @@ struct audio_entity_info audio_entity_table[] = {
void composite_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &video_audio_hid_descriptor);
#else
usbd_desc_register(busid, video_audio_hid_descriptor);
#endif
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, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(busid, &video_in_ep);

View File

@ -50,6 +50,77 @@
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
//VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
VIDEO_VS_FORMAT_H264_DESCRIPTOR_INIT(0x01, 0x01),
VIDEO_VS_FRAME_H264_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UVC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor video_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t video_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -136,6 +207,7 @@ const uint8_t video_descriptor[] = {
#endif
0x00
};
#endif
volatile bool tx_flag = 0;
volatile bool iso_tx_busy = false;
@ -198,7 +270,11 @@ struct usbd_interface intf1;
void video_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &video_descriptor);
#else
usbd_desc_register(busid, video_descriptor);
#endif
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, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(busid, &video_in_ep);

View File

@ -50,6 +50,77 @@
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
//VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UVC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor video_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t video_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -136,6 +207,7 @@ const uint8_t video_descriptor[] = {
#endif
0x00
};
#endif
volatile bool tx_flag = 0;
volatile bool iso_tx_busy = false;
@ -198,7 +270,11 @@ struct usbd_interface intf1;
void video_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &video_descriptor);
#else
usbd_desc_register(busid, video_descriptor);
#endif
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, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(busid, &video_in_ep);

View File

@ -51,6 +51,79 @@
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
//VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(0x01, 0x01, VIDEO_GUID_YUY2),
VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
VIDEO_VS_COLOR_MATCHING_DESCRIPTOR_INIT(),
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB UVC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor video_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
const uint8_t video_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -138,6 +211,7 @@ const uint8_t video_descriptor[] = {
#endif
0x00
};
#endif
volatile bool tx_flag = 0;
volatile bool iso_tx_busy = false;
@ -200,7 +274,11 @@ struct usbd_interface intf1;
void video_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &video_descriptor);
#else
usbd_desc_register(busid, video_descriptor);
#endif
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, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
usbd_add_endpoint(busid, &video_in_ep);

View File

@ -149,6 +149,105 @@ struct usb_bos_descriptor bos_desc = {
.string_len = USBD_BOS_WTOTALLENGTH
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
};
static const uint8_t config_descriptor[] = {
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)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB WEBUSB HID DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor webusb_hid_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.msosv2_descriptor = &msosv2_desc,
.webusb_url_descriptor = &webusb_url_desc,
.bos_descriptor = &bos_desc
};
#else
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),
@ -207,7 +306,7 @@ static const uint8_t webusb_hid_descriptor[] = {
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
0x2C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
@ -219,14 +318,17 @@ static const uint8_t webusb_hid_descriptor[] = {
'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 */
'W', 0x00, /* wcChar10 */
'E', 0x00, /* wcChar11 */
'B', 0x00, /* wcChar12 */
'U', 0x00, /* wcChar13 */
'S', 0x00, /* wcChar14 */
'B', 0x00, /* wcChar15 */
' ', 0x00, /* wcChar16 */
'D', 0x00, /* wcChar17 */
'E', 0x00, /* wcChar18 */
'M', 0x00, /* wcChar19 */
'O', 0x00, /* wcChar20 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
@ -259,6 +361,7 @@ static const uint8_t webusb_hid_descriptor[] = {
#endif
0x00
};
#endif
/* USB HID device Configuration Descriptor */
static uint8_t hid_desc[9] __ALIGN_END = {
@ -355,10 +458,16 @@ static struct usbd_interface intf0;
void webusb_hid_keyboard_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &webusb_hid_descriptor);
#else
usbd_desc_register(busid, webusb_hid_descriptor);
#endif
#ifndef CONFIG_USBDEV_ADVANCE_DESC
usbd_bos_desc_register(busid, &bos_desc);
usbd_msosv2_desc_register(busid, &msosv2_desc);
usbd_webusb_desc_register(busid, &webusb_url_desc);
#endif
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);

View File

@ -188,6 +188,79 @@ struct usb_msosv1_descriptor msosv1_desc = {
#define WINUSB_EP_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x04),
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, 0x02, WINUSB_EP_MPS, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, 0x02, WINUSB_EP_MPS, 0x00),
#if DOUBLE_WINUSB == 1
USB_INTERFACE_DESCRIPTOR_INIT(0x01, 0x00, 0x02, 0xff, 0xff, 0x00, 0x05),
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP2, 0x02, WINUSB_EP_MPS, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP2, 0x02, WINUSB_EP_MPS, 0x00),
#endif
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB WINUSB DEMO", /* Product */
"2022123456", /* Serial Number */
"CherryUSB WINUSB DEMO 1", /* STRING4 */
"CherryUSB WINUSB DEMO 2", /* STRING5 */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 5) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor winusb_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.msosv1_descriptor = &msosv1_desc
};
#else
const uint8_t winusb_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
@ -252,12 +325,12 @@ const uint8_t winusb_descriptor[] = {
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'1', 0x00, /* wcChar3 */
'0', 0x00, /* wcChar4 */
'3', 0x00, /* wcChar5 */
'1', 0x00, /* wcChar6 */
'0', 0x00, /* wcChar7 */
'0', 0x00, /* wcChar8 */
'0', 0x00, /* wcChar9 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
///////////////////////////////////////
/// string4 descriptor
///////////////////////////////////////
@ -322,15 +395,16 @@ const uint8_t winusb_descriptor[] = {
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@ -446,8 +520,14 @@ struct usbd_interface intf1;
void winusb_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &winusb_descriptor);
#else
usbd_desc_register(busid, winusb_descriptor);
#endif
#ifndef CONFIG_USBDEV_ADVANCE_DESC
usbd_msosv1_desc_register(busid, &msosv1_desc);
#endif
usbd_add_interface(busid, &intf0);
usbd_add_endpoint(busid, &winusb_out_ep1);
usbd_add_endpoint(busid, &winusb_in_ep1);

View File

@ -145,6 +145,89 @@ __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
#endif
};
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
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
/* Configuration 0 */
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
/* Interface 0 */
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
/* Endpoint OUT 2 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
/* Endpoint IN 1 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x10,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB WINUSB DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor winusbv2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.msosv2_descriptor = &msosv2_desc,
.bos_descriptor = &bos_desc
};
#else
const uint8_t winusbv2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
/* Configuration 0 */
@ -170,7 +253,9 @@ const uint8_t winusbv2_descriptor[] = {
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
/* String 2 (Product) */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x2C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
@ -194,21 +279,21 @@ const uint8_t winusbv2_descriptor[] = {
'E', 0x00, /* wcChar18 */
'M', 0x00, /* wcChar19 */
'O', 0x00, /* wcChar20 */
/* String 3 (Serial Number) */
0x1A, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'0', 0, // wcChar0
'1', 0, // wcChar1
'2', 0, // wcChar2
'3', 0, // wcChar3
'4', 0, // wcChar4
'5', 0, // wcChar5
'A', 0, // wcChar6
'B', 0, // wcChar7
'C', 0, // wcChar8
'D', 0, // wcChar9
'E', 0, // wcChar10
'F', 0, // wcChar11
///////////////////////////////////////
/// 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 */
0x0a,
@ -225,6 +310,7 @@ const uint8_t winusbv2_descriptor[] = {
/* End */
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@ -248,6 +334,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@ -283,6 +370,30 @@ void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
}
}
void usbd_cdc_acm_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
// printf("%02x ", read_buffer[i]);
// }
// printf("\r\n");
usbd_ep_start_write(busid, CDC_IN_EP, read_buffer, nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
struct usbd_endpoint winusb_out_ep1 = {
.ep_addr = WINUSB_OUT_EP,
.ep_cb = usbd_winusb_out
@ -295,35 +406,29 @@ struct usbd_endpoint winusb_in_ep1 = {
static struct usbd_endpoint cdc_out_ep = {
.ep_addr = CDC_OUT_EP,
.ep_cb = NULL
.ep_cb = usbd_cdc_acm_out
};
static struct usbd_endpoint cdc_in_ep = {
.ep_addr = CDC_IN_EP,
.ep_cb = NULL
.ep_cb = usbd_cdc_acm_in
};
struct usbd_interface winusb_intf;
struct usbd_interface intf1;
struct usbd_interface intf2;
struct usb_msosv2_descriptor msosv2_desc = {
.vendor_code = USBD_WINUSB_VENDOR_CODE,
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
};
struct usb_bos_descriptor bos_desc = {
.string = USBD_BinaryObjectStoreDescriptor,
.string_len = USBD_BOS_WTOTALLENGTH
};
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &winusbv2_descriptor);
#else
usbd_desc_register(busid, winusbv2_descriptor);
#endif
#ifndef CONFIG_USBDEV_ADVANCE_DESC
usbd_bos_desc_register(busid, &bos_desc);
usbd_msosv2_desc_register(busid, &msosv2_desc);
#endif
/*!< winusb */
usbd_add_interface(busid, &winusb_intf);
usbd_add_endpoint(busid, &winusb_out_ep1);
@ -336,4 +441,26 @@ void winusbv2_init(uint8_t busid, uintptr_t reg_base)
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
} else {
dtr_enable = 0;
}
}
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
memset(&write_buffer[10], 'a', 2038);
ep_tx_busy_flag = true;
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
}

View File

@ -151,6 +151,119 @@ __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
#endif
};
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
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
/* Configuration 0 */
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
/* Interface 0 */
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
/* Endpoint OUT 2 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
/* Endpoint IN 1 */
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
0x00,
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x10,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB WINUSB DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor winusbv2_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.msosv2_descriptor = &msosv2_desc,
.bos_descriptor = &bos_desc
};
#else
const uint8_t winusbv2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
/* Configuration 0 */
@ -206,7 +319,9 @@ const uint8_t winusbv2_descriptor[] = {
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
/* String 2 (Product) */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x2C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
@ -230,21 +345,21 @@ const uint8_t winusbv2_descriptor[] = {
'E', 0x00, /* wcChar18 */
'M', 0x00, /* wcChar19 */
'O', 0x00, /* wcChar20 */
/* String 3 (Serial Number) */
0x1A, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'0', 0, // wcChar0
'1', 0, // wcChar1
'2', 0, // wcChar2
'3', 0, // wcChar3
'4', 0, // wcChar4
'5', 0, // wcChar5
'A', 0, // wcChar6
'B', 0, // wcChar7
'C', 0, // wcChar8
'D', 0, // wcChar9
'E', 0, // wcChar10
'F', 0, // wcChar11
///////////////////////////////////////
/// 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 */
0x0a,
@ -261,6 +376,7 @@ const uint8_t winusbv2_descriptor[] = {
/* End */
0x00
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
@ -411,23 +527,17 @@ static struct usbd_endpoint hid_in_ep = {
struct usbd_interface winusb_intf;
struct usbd_interface intf1;
struct usb_msosv2_descriptor msosv2_desc = {
.vendor_code = USBD_WINUSB_VENDOR_CODE,
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
};
struct usb_bos_descriptor bos_desc = {
.string = USBD_BinaryObjectStoreDescriptor,
.string_len = USBD_BOS_WTOTALLENGTH
};
void winusbv2_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &winusbv2_descriptor);
#else
usbd_desc_register(busid, winusbv2_descriptor);
#endif
#ifndef CONFIG_USBDEV_ADVANCE_DESC
usbd_bos_desc_register(busid, &bos_desc);
usbd_msosv2_desc_register(busid, &msosv2_desc);
#endif
/*!< winusb */
usbd_add_interface(busid, &winusb_intf);
usbd_add_endpoint(busid, &winusb_out_ep1);

View File

@ -1,4 +1,4 @@
version: "1.4.2"
version: "1.4.3"
description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
tags:
- usb

View File

@ -26,6 +26,8 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
void usb_osal_thread_delete(usb_osal_thread_t thread)
{
if (thread == NULL) {
rt_thread_t self = rt_thread_self();
rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
return;
}

View File

@ -42,6 +42,12 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t msc_sector[512];
static rt_err_t rt_udisk_init(rt_device_t dev)
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
if (usbh_msc_scsi_init(msc_class) < 0) {
return -RT_ERROR;
}
return RT_EOK;
}
@ -157,39 +163,35 @@ const static struct rt_device_ops udisk_device_ops = {
};
#endif
int udisk_init(struct usbh_msc *msc_class)
static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
{
rt_err_t ret = 0;
rt_uint8_t i;
struct dfs_partition part0;
struct rt_device *dev;
struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
char name[CONFIG_USBHOST_DEV_NAMELEN];
char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
int ret;
snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
ret = dfs_mount(name, mount_point, "elm", 0, 0);
if (ret == 0) {
rt_kprintf("udisk: %s mount successfully\n", name);
} else {
rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
}
usb_osal_thread_delete(NULL);
}
void usbh_msc_run(struct usbh_msc *msc_class)
{
struct rt_device *dev;
char name[CONFIG_USBHOST_DEV_NAMELEN];
dev = rt_malloc(sizeof(struct rt_device));
memset(dev, 0, sizeof(struct rt_device));
snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
ret = usbh_msc_scsi_read10(msc_class, 0, msc_sector, 1);
if (ret != RT_EOK) {
rt_kprintf("usb mass_storage read failed\n");
rt_free(dev);
return ret;
}
for (i = 0; i < 4; i++) {
/* Get the first partition */
ret = dfs_filesystem_get_partition(&part0, msc_sector, i);
if (ret == RT_EOK) {
rt_kprintf("Found partition %d: type = %d, offet=0x%x, size=0x%x\n",
i, part0.type, part0.offset, part0.size);
break;
} else {
break;
}
}
dev->type = RT_Device_Class_Block;
#ifdef RT_USING_DEVICE_OPS
@ -204,19 +206,7 @@ int udisk_init(struct usbh_msc *msc_class)
rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
ret = dfs_mount(name, mount_point, "elm", 0, 0);
if (ret == 0) {
rt_kprintf("udisk: %s mount successfully\n", name);
} else {
rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
}
return ret;
}
void usbh_msc_run(struct usbh_msc *msc_class)
{
udisk_init(msc_class);
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
}
void usbh_msc_stop(struct usbh_msc *msc_class)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2022, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_syscfg.h>
#include "usbd_core.h"
#include "usb_dc_aic_reg.h"
extern irqreturn_t USBD_IRQHandler(int irq, void * data);
uint32_t usbd_clk;
void usb_dc_low_level_init(void)
{
/* set usb0 phy switch: Host/Device */
#ifdef AIC_USING_USB0_DEVICE
syscfg_usb_phy0_sw_host(0);
#endif
/* set pin-mux */
/* enable clock */
hal_clk_enable(CONFIG_USB_AIC_DC_PHY_CLK);
hal_clk_enable(CONFIG_USB_AIC_DC_CLK);
aicos_udelay(300);
hal_reset_assert(CONFIG_USB_AIC_DC_PHY_RESET);
hal_reset_assert(CONFIG_USB_AIC_DC_RESET);
aicos_udelay(300);
hal_reset_deassert(CONFIG_USB_AIC_DC_PHY_RESET);
hal_reset_deassert(CONFIG_USB_AIC_DC_RESET);
aicos_udelay(300);
usbd_clk = hal_clk_get_freq(CONFIG_USB_AIC_DC_CLK);
/* register interrupt callback */
aicos_request_irq(CONFIG_USB_AIC_DC_IRQ_NUM, USBD_IRQHandler,
0, "usb_device", NULL);
aicos_irq_enable(CONFIG_USB_AIC_DC_IRQ_NUM);
}

View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 2022, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __USB_DC_AIC_REG_H__
#define __USB_DC_AIC_REG_H__
#define __IO volatile /*!< Defines 'read / write' permissions */
typedef struct {
__IO uint32_t ahbbasic; /* 0x0000: AHBBASIC */
__IO uint32_t usbdevinit; /* 0x0004: USBDEVINIT */
__IO uint32_t usbphyif; /* 0x0008: USBPHYIF */
__IO uint32_t usbulpiphy; /* 0x000C: USBULPIPHY */
__IO uint32_t usbintsts; /* 0x0010: USBINTSTS */
__IO uint32_t usbintmsk; /* 0x0014: USBINTMSK */
__IO uint32_t rxfifosiz; /* 0x0018: RXFIFOSIZ */
__IO uint32_t rxfifosts_pop; /* 0x001C: RXFIFOSTS pop */
__IO uint32_t nptxfifosiz; /* 0x0020: NPTXFIFOSIZ */
__IO uint32_t nptxfifosts; /* 0x0024: NPTXFIFOSTS */
__IO uint32_t txfifosiz[2]; /* 0x0028 - 0x002C: TXFIFOSIZ() */
__IO uint32_t rxfifosts_dbg; /* 0x0030: RXFIFOSTS_DBG */
uint8_t res0[0x1cc];
__IO uint32_t usbdevconf; /* 0x0200: USBDEVCONF */
__IO uint32_t usbdevfunc; /* 0x0204: USBDEVFUNC */
__IO uint32_t usblinests; /* 0x0208: USBLINESTS */
__IO uint32_t inepintmsk; /* 0x020C: INEPINTMSK */
__IO uint32_t outepintmsk; /* 0x0210: OUTEPINTMSK */
__IO uint32_t usbepint; /* 0x0214: USBEPINT */
__IO uint32_t usbepintmsk; /* 0x0218: USBEPINTMSK */
uint8_t res1[4];
__IO uint32_t inepcfg[5]; /* 0x0220 - 0x0230: INEPCFG() */
uint8_t res2[0xc];
__IO uint32_t outepcfg[5]; /* 0x0240 - 0x0250: OUTEPCFG() */
uint8_t res3[0xc];
__IO uint32_t inepint[5]; /* 0x0260 - 0x0270: INEPINT() */
uint8_t res4[0xc];
__IO uint32_t outepint[5]; /* 0x0280 - 0x0290: OUTEPINT() */
uint8_t res5[0xc];
__IO uint32_t ineptsfsiz[5]; /* 0x02A0 - 0x02B0: INEPTSFSIZ() */
uint8_t res6[0xc];
__IO uint32_t outeptsfsiz[5]; /* 0x02C0 - 0x02D0: OUTEPTSFSIZ() */
uint8_t res7[0x2c];
__IO uint32_t inepdmaaddr[5]; /* 0x0300 - 0x0310: INEPDMAADDR() */
uint8_t res8[0xc];
__IO uint32_t outepdmaaddr[5]; /* 0x0320 - 0x0330: OUTEPDMAADDR() */
uint8_t res9[0xc];
__IO uint32_t ineptxsts[5]; /* 0x0340 - 0x0350: INEPTXSTS() */
uint8_t res10[0xc];
__IO uint32_t dtknqr1; /* 0x0360: DTKNQR1 */
__IO uint32_t dtknqr2; /* 0x0364: DTKNQR2 */
__IO uint32_t dtknqr3; /* 0x0368: DTKNQR3 */
__IO uint32_t dtknqr4; /* 0x036C: DTKNQR4 */
}AIC_UDC_RegDef;
/*===================================================================== */
/*definitions related to CSR setting */
/* AHBBASIC */
#define AHBBASIC_NOTI_ALL_DMA_WRIT (1 << 8)
#define AHBBASIC_REM_MEM_SUPP (1 << 7)
#define AHBBASIC_INV_DESC_ENDIANNESS (1 << 6)
#define AHBBASIC_AHB_SINGLE (1 << 5)
#define AHBBASIC_TXENDDELAY (1 << 3)
#define AHBBASIC_AHBIDLE (1 << 2)
#define AHBBASIC_DMAREQ (1 << 1)
/* USBDEVINIT */
#define USBDEVINIT_HBSTLEN_MASK (0xf << 12)
#define USBDEVINIT_HBSTLEN_SHIFT 12
#define USBDEVINIT_HBSTLEN_SINGLE 0
#define USBDEVINIT_HBSTLEN_INCR 1
#define USBDEVINIT_HBSTLEN_INCR4 3
#define USBDEVINIT_HBSTLEN_INCR8 5
#define USBDEVINIT_HBSTLEN_INCR16 7
#define USBDEVINIT_DMA_EN (1 << 11)
#define USBDEVINIT_NP_TXF_EMP_LVL (1 << 10)
#define USBDEVINIT_GLBL_INTR_EN (1 << 9)
#define USBDEVINIT_CTRL_MASK (USBDEVINIT_NP_TXF_EMP_LVL | \
USBDEVINIT_DMA_EN | \
USBDEVINIT_GLBL_INTR_EN)
#define USBDEVINIT_IN_TKNQ_FLSH (1 << 8)
#define USBDEVINIT_TXFNUM_MASK (0x1f << 3)
#define USBDEVINIT_TXFNUM_SHIFT 3
#define USBDEVINIT_TXFNUM_LIMIT 0x1f
#define USBDEVINIT_TXFNUM(_x) ((_x) << 3)
#define USBDEVINIT_TXFFLSH (1 << 2)
#define USBDEVINIT_RXFFLSH (1 << 1)
#define USBDEVINIT_CSFTRST (1 << 0)
/* USBPHYIF */
#define USBPHYIF_ULPI_CLK_SUSP_M (1 << 19)
#define USBPHYIF_ULPI_AUTO_RES (1 << 18)
#define USBPHYIF_PHY_LP_CLK_SEL (1 << 15)
#define USBPHYIF_USBTRDTIM_MASK (0xf << 10)
#define USBPHYIF_USBTRDTIM_SHIFT 10
#ifndef USBPHYIF_HS_TRDT_VALUE
#define USBPHYIF_HS_TRDT_VALUE 9U
#endif /* USBD_HS_TRDT_VALUE */
#ifndef USBPHYIF_FS_TRDT_VALUE
#define USBPHYIF_FS_TRDT_VALUE 5U
#define USBPHYIF_DEFAULT_TRDT_VALUE 9U
#endif /* USBD_HS_TRDT_VALUE */
#define USBPHYIF_DDRSEL (1 << 7)
#define USBPHYIF_ULPI_UTMI_SEL (1 << 4)
#define USBPHYIF_PHYIF16 (1 << 3)
#define USBPHYIF_PHYIF8 (0 << 3)
#define USBPHYIF_TOUTCAL_MASK (0x7 << 0)
#define USBPHYIF_TOUTCAL_SHIFT 0
#define USBPHYIF_TOUTCAL_LIMIT 0x7
#define USBPHYIF_TOUTCAL(_x) ((_x) << 0)
/* USBINTSTS/USBINTMSK interrupt register */
#define INT_RESUME (1u << 31)
#define INT_INCOMP_ISO_OUT_INT (0x1 << 21)
#define INT_INCOMP_ISO_IN_INT (0x1 << 20)
#define INT_OUT_EP (0x1 << 19)
#define INT_IN_EP (0x1 << 18)
#define INT_ENUMDONE (0x1 << 13)
#define INT_RESET (0x1 << 12)
#define INT_SUSPEND (0x1 << 11)
#define INT_EARLY_SUSPEND (0x1 << 10)
#define INT_GOUTNAKEFF (0x1 << 7)
#define INT_GINNAKEFF (0x1 << 6)
#define INT_NP_TX_FIFO_EMPTY (0x1 << 5)
#define INT_RX_FIFO_NOT_EMPTY (0x1 << 4)
#define INT_SOF (0x1 << 3)
#define FULL_SPEED_CONTROL_PKT_SIZE 8
#define FULL_SPEED_BULK_PKT_SIZE 64
#define HIGH_SPEED_CONTROL_PKT_SIZE 64
#define HIGH_SPEED_BULK_PKT_SIZE 512
#define RX_FIFO_SIZE (1024)
#define NPTX_FIFO_SIZE (1024)
#define PTX_FIFO_SIZE (384)
/* fifo size configure */
#define EPS_NUM 5
#define PERIOD_IN_EP_NUM 2
#define TOTAL_FIFO_SIZE 0x3f6
#define AIC_RX_FIFO_SIZE 0x119
#define AIC_NP_TX_FIFO_SIZE 0x100
#define AIC_PERIOD_TX_FIFO1_SIZE 0x100
#define AIC_PERIOD_TX_FIFO2_SIZE 0xDD
#define DEPCTL_TXFNUM_0 (0x0 << 22)
#define DEPCTL_TXFNUM_1 (0x1 << 22)
#define DEPCTL_TXFNUM_2 (0x2 << 22)
#define DEPCTL_TXFNUM_3 (0x3 << 22)
#define DEPCTL_TXFNUM_4 (0x4 << 22)
/* RXFIFOSTS */
#define RXFIFOSTS_EPNUM_MASK (0xFU << 0)
#define RXFIFOSTS_BCNT_MASK (0x7FFU << 4)
#define RXFIFOSTS_DPID_MASK (0x3U << 15)
#define RXFIFOSTS_PKTSTS_SHIFT (17)
#define RXFIFOSTS_PKTSTS_MASK (0xFU << RXFIFOSTS_PKTSTS_SHIFT)
#define PKTSTS_GLOBAL_OUT_NAK (0x1 << RXFIFOSTS_PKTSTS_SHIFT)
#define PKTSTS_OUT_DATA_PKT_REC (0x2 << RXFIFOSTS_PKTSTS_SHIFT)
#define PKTSTS_OUT_TRANSFER_COMP (0x3 << RXFIFOSTS_PKTSTS_SHIFT)
#define PKTSTS_SETUP_TRANSACTION_COMP (0x4 << RXFIFOSTS_PKTSTS_SHIFT)
#define PKTSTS_SETUP_DATA_PKT_REC (0x6 << RXFIFOSTS_PKTSTS_SHIFT)
#define RXFIFOSTS_FN_MASK (0xFU << 21)
/* USBDEVCONF */
#define DEV_SPEED_HIGH_SPEED_20 (0x0 << 0)
#define DEV_SPEED_FULL_SPEED_20 (0x1 << 0)
#define DEV_SPEED_LOW_SPEED_11 (0x2 << 0)
#define DEV_SPEED_FULL_SPEED_11 (0x3 << 0)
#define EP_MISS_CNT(x) (x << 18)
#define DEVICE_ADDRESS_MASK (0x7F << 4)
#define DEVICE_ADDRESS(x) (x << 4)
#define PERIOD_FRAME_INTERVAL_80 (0 << 11)
#define PERIOD_FRAME_INTERVAL_85 (1 << 11)
#define PERIOD_FRAME_INTERVAL_90 (2 << 11)
#define PERIOD_FRAME_INTERVAL_95 (3 << 11)
/* USBDEVFUNC */
#define NORMAL_OPERATION (0x1 << 0)
#define SOFT_DISCONNECT (0x1 << 1)
#define USBDEVFUNC_SERVICE_INTERVAL_SUPPORTED (1 << 19)
#define USBDEVFUNC_PWRONPRGDONE (1 << 11)
#define USBDEVFUNC_CGOUTNAK (1 << 10)
#define USBDEVFUNC_SGOUTNAK (1 << 9)
#define USBDEVFUNC_CGNPINNAK (1 << 8)
#define USBDEVFUNC_SGNPINNAK (1 << 7)
#define USBDEVFUNC_TSTCTL_MASK (0x7 << 4)
#define USBDEVFUNC_TSTCTL_SHIFT (4)
#define USBDEVFUNC_GOUTNAKSTS (1 << 3)
#define USBDEVFUNC_GNPINNAKSTS (1 << 2)
#define USBDEVFUNC_SFTDISCON (1 << 1)
#define USBDEVFUNC_RMTWKUPSIG (1 << 0)
/* USBLINESTS: Enumeration speed */
#define USB_ENUM_SPEED_SHIFT 1
#define USB_ENUM_SPEED_MASK (0x3 << USB_ENUM_SPEED_SHIFT)
#define USB_ENUM_SPEED_HIGH 0
#define USB_ENUM_SPEED_FULL 1
#define USB_HIGH_30_60MHZ (0x0 << USB_ENUM_SPEED_SHIFT)
#define USB_FULL_30_60MHZ (0x1 << USB_ENUM_SPEED_SHIFT)
#define USB_LOW_6MHZ (0x2 << USB_ENUM_SPEED_SHIFT)
#define USB_FULL_48MHZ (0x3 << USB_ENUM_SPEED_SHIFT)
/* USBEPINT endpoint interrupt register */
#define DAINT_OUT_BIT (16)
#define DAINT_IN_MASK (0xFFFF)
#define DAINT_OUT_MASK (0xFFFFU << DAINT_OUT_BIT)
/* INEPCFG()/OUTEPCFG()
* devicecontrol IN/OUT endpoint 0 control register
*/
#define DEPCTL_EPENA (1u << 31)
#define DEPCTL_EPDIS (0x1 << 30)
#define DEPCTL_SETD1PID (0x1 << 29)
#define DEPCTL_SETD0PID (0x1 << 28)
#define DEPCTL_SNAK (0x1 << 27)
#define DEPCTL_CNAK (0x1 << 26)
#define DEPCTL_TXFIFONUM_SHIFT 22
#define DEPCTL_TXFIFONUM_MASK (0xF << 22)
#define DEPCTL_STALL (0x1 << 21)
#define DEPCTL_TYPE_BIT (18)
#define DEPCTL_TYPE_MASK (0x3 << 18)
#define DEPCTL_CTRL_TYPE (0x0 << 18)
#define DEPCTL_ISO_TYPE (0x1 << 18)
#define DEPCTL_BULK_TYPE (0x2 << 18)
#define DEPCTL_INTR_TYPE (0x3 << 18)
#define DEPCTL_USBACTEP (0x1 << 15)
#define DEPCTL_NEXT_EP_BIT (11)
#define DEPCTL_NEXT_EP_MASK (0xFU << DEPCTL_NEXT_EP_BIT)
#define DEPCTL_MPS_BIT (0)
#define DEPCTL_MPS_MASK (0x7FF)
#define DEPCTL0_MPS_64 (0x0 << 0)
#define DEPCTL0_MPS_32 (0x1 << 0)
#define DEPCTL0_MPS_16 (0x2 << 0)
#define DEPCTL0_MPS_8 (0x3 << 0)
#define DEPCTL_MPS_BULK_512 (512 << 0)
#define DEPCTL_MPS_INT_MPS_16 (16 << 0)
#define DIEPCTL0_NEXT_EP_BIT (11)
/* INEPINT/OUTEPINT device IN/OUT endpoint interrupt register */
#define TXFIFO_EMP_INT (0x1 << 7)
#define INEP_NAKEFF (0x1 << 6)
#define BACK2BACK_SETUP_RECEIVED (0x1 << 6)
#define INTKNEPMIS (0x1 << 5)
#define INTKN_TXFEMP (0x1 << 4)
#define NON_ISO_IN_EP_TIMEOUT (0x1 << 3)
#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1 << 3)
#define AHB_ERROR (0x1 << 2)
#define EPDISBLD (0x1 << 1)
#define TRANSFER_DONE (0x1 << 0)
/* Masks definitions */
#define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\
| INT_RESET | INT_SUSPEND)
#define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE |\
AHB_ERROR | TRANSFER_DONE)
#define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT | AHB_ERROR | TRANSFER_DONE)
#define GAHBCFG_INIT (USBDEVINIT_DMA_EN | USBDEVINIT_GLBL_INTR_EN\
| (USBDEVINIT_HBSTLEN_INCR4 <<\
USBDEVINIT_HBSTLEN_SHIFT))
/* INEPTSFSIZ/OUTEPTSFSIZ */
#define DXEPTSIZ_MULCNT_SHIFT 29
#define DXEPTSIZ_MULCNT_MASK (0x3U << DXEPTSIZ_MULCNT_SHIFT)
#define DXEPTSIZ_PKT_CNT_SHIFT 19
#define DXEPTSIZ_PKT_CNT_MASK (0x3FFU << DXEPTSIZ_PKT_CNT_SHIFT)
#define DXEPTSIZ_XFER_SIZE_SHIFT 0
#define DXEPTSIZ_XFER_SIZE_MASK (0x7FFFFU << DXEPTSIZ_XFER_SIZE_SHIFT)
/* Device Endpoint X Transfer Size Register INEPTSFSIZ() */
#define DIEPT_SIZ_PKT_CNT(x) (x << 19)
#define DIEPT_SIZ_XFER_SIZE(x) (x << 0)
/* Device OUT Endpoint X Transfer Size Register OUTEPTSFSIZ() */
#define DOEPT_SIZ_PKT_CNT(x) (x << 19)
#define DOEPT_SIZ_XFER_SIZE(x) (x << 0)
#define DOEPT_SIZ_XFER_SIZE_MAX_EP0 (0x7F << 0)
#define DOEPT_SIZ_XFER_SIZE_MAX_EP (0x7FFF << 0)
/* Device Endpoint-N Control Register INEPCFG()/OUTEPCFG() */
#define DIEPCTL_TX_FIFO_NUM(x) (x << 22)
#define DIEPCTL_TX_FIFO_NUM_MASK (~DIEPCTL_TX_FIFO_NUM(0xF))
/* Device ALL Endpoints Interrupt Register (USBEPINT) */
#define DAINT_IN_EP_INT(x) (x << 0)
#define DAINT_OUT_EP_INT(x) (x << 16)
#define AIC_EP_FIFO_BASE 0x1000UL
#define AIC_EP_FIFO_SIZE 0x1000UL
/* In EPn Txfifo Status (INEPTXSTS) */
#define INEPTXSTS_IN_EP_TXFIFO_STS (0xFFFFU << 0)
#endif

View File

@ -0,0 +1,525 @@
#include "usbd_core.h"
#include "ch585_usbhs_reg.h"
/**
* @brief Related register macro
*/
#define USB_BASE 0x40009000u
#define CH585_USBHS_DEV ((USBHSD_TypeDef *)USB_BASE)
#ifndef USBD_IRQHandler
#define USBD_IRQHandler USB2_DEVICE_IRQHandler //use actual usb irq name instead
#endif
#define R16_PIN_CONFIG (*((PUINT16V)0x4000101A))
#define R32_PIN_CONFIG (*((PUINT32V)0x40001018)) // RW, I/O pin configuration
#define RB_PIN_USB2_EN 0x20
#define USB_SET_RX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&CH585_USBHS_DEV->UEP1_RX_DMA) + 4 * (ep_idx - 1)) = addr)
#define USB_SET_TX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&CH585_USBHS_DEV->UEP1_TX_DMA) + 4 * (ep_idx - 1)) = addr)
#define USB_SET_MAX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_MAX_LEN) + 4 * ep_idx) = len)
#define USB_SET_TX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx) = len)
#define USB_GET_TX_LEN(ep_idx) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx))
#define USB_SET_TX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_CTRL) + 4 * ep_idx) = val)
#define USB_GET_TX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_CTRL) + 4 * ep_idx))
#define USB_SET_RX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_RX_CTRL) + 4 * ep_idx) = val)
#define USB_GET_RX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_RX_CTRL) + 4 * ep_idx))
#define EPn_SET_TX_NAK(ep_idx) USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_NAK)
#define EPn_SET_TX_VALID(ep_idx) USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK)
#define EPn_SET_RX_NAK(ep_idx) USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK)
#define EPn_SET_RX_VALID(ep_idx) USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK)
#define EPn_GET_RX_LEN(ep_idx) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->USB_EP0_RX_LEN) + 4 * ep_idx))
#define EPn_SET_TX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&CH585_USBHS_DEV->UEP0_TX_LEN) + 4 * ep_idx) = len)
#define EPn_CLEAR_TX_DONE(ep_idx) USB_SET_TX_CTRL(ep_idx, USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_DONE)
#define EPn_CLEAR_RX_DONE(ep_idx) USB_SET_RX_CTRL(ep_idx, USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_DONE)
#define EPn_SET_TX_ISO_VALID(ep_idx)
#define EPn_SET_RX_ISO_VALID(ep_idx)
/* ep nums */
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 8
#endif
/**
* @brief Endpoint information structure
*/
typedef struct _usbd_ep_info {
uint8_t mps; /* Maximum packet length of endpoint */
uint8_t eptype; /* Endpoint Type */
uint8_t ep_enable; /* Endpoint enable */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
} usbd_ep_info;
/* ch58x usb */
static struct _ch58x_core_prvi {
uint8_t address; /* Address */
usbd_ep_info ep_in[CONFIG_USBDEV_EP_NUM];
usbd_ep_info ep_out[CONFIG_USBDEV_EP_NUM];
struct usb_setup_packet setup;
} usb_dc_cfg;
__WEAK void usb_dc_low_level_init(void)
{
}
__WEAK void usb_dc_low_level_deinit(void)
{
}
/**
* @brief USB initialization
* @pre None
* @param[in] None
* @retval >=0 success otherwise failure
*/
int usb_dc_init(uint8_t busid)
{
R8_USBHS_PLL_CTRL = USBHS_PLL_EN;
R16_PIN_CONFIG |= RB_PIN_USB2_EN;
CH585_USBHS_DEV->CONTROL = USBHS_UD_RST_LINK | USBHS_UD_PHY_SUSPENDM;
CH585_USBHS_DEV->INT_EN = USBHS_UDIE_BUS_RST | USBHS_UDIE_SUSPEND | USBHS_UDIE_BUS_SLEEP | USBHS_UDIE_LPM_ACT | USBHS_UDIE_TRANSFER | USBHS_UDIE_LINK_RDY;
/* Enable all end points */
CH585_USBHS_DEV->UEP_TX_EN = 0xffff;
CH585_USBHS_DEV->UEP_RX_EN = 0xffff;
CH585_USBHS_DEV->BASE_MODE = USBHS_UD_SPEED_HIGH;
CH585_USBHS_DEV->CONTROL = USBHS_UD_DEV_EN | USBHS_UD_DMA_EN | USBHS_UD_LPM_EN | USBHS_UD_PHY_SUSPENDM;
CH585_USBHS_DEV->UEP_T_TOG_AUTO = 0xfe;
CH585_USBHS_DEV->UEP_R_TOG_AUTO = 0xfe;
usb_dc_low_level_init();
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
R8_USBHS_PLL_CTRL &= ~USBHS_PLL_EN;
R32_PIN_CONFIG &= ~RB_PIN_USB2_EN;
CH585_USBHS_DEV->CONTROL |= USBHS_UD_RST_SIE;
CH585_USBHS_DEV->CONTROL &= ~USBHS_UD_RST_SIE;
usb_dc_low_level_deinit();
return 0;
}
/**
* @brief Set address
* @pre None
* @param[in] address 8-bit valid address
* @retval >=0 success otherwise failure
*/
int usbd_set_address(uint8_t busid, const uint8_t address)
{
if (address == 0) {
CH585_USBHS_DEV->DEV_AD = (CH585_USBHS_DEV->DEV_AD & 0x80) | address;
}
usb_dc_cfg.address = address;
return 0;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}
uint8_t usbd_get_port_speed(uint8_t busid)
{
return USB_SPEED_HIGH;
}
/**
* @brief Open endpoint
* @pre None
* @param[in] ep_cfg : Endpoint configuration structure pointer
* @retval >=0 success otherwise failure
*/
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
if (epid > (CONFIG_USBDEV_EP_NUM - 1)) {
/**
* If you use ch58x, you can change the CONFIG_USBDEV_EP_NUM set to 8
*/
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
USB_SET_MAX_LEN(epid, mps);
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
usb_dc_cfg.ep_in[epid].ep_enable = true;
usb_dc_cfg.ep_in[epid].mps = mps;
usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
USB_SET_TX_CTRL(epid, USBHS_UEP_T_RES_NAK);
EPn_CLEAR_TX_DONE(epid);
} else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
usb_dc_cfg.ep_out[epid].ep_enable = true;
usb_dc_cfg.ep_out[epid].mps = mps;
usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
USB_SET_RX_CTRL(epid, USBHS_UEP_R_RES_NAK);
}
return 0;
}
/**
* @brief Close endpoint
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_IN(ep)) {
usb_dc_cfg.ep_in[epid].ep_enable = false;
} else if (USB_EP_DIR_IS_OUT(ep)) {
usb_dc_cfg.ep_out[epid].ep_enable = false;
}
return 0;
}
/**
* @brief Endpoint setting stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
if (ep_idx == 0) {
CH585_USBHS_DEV->UEP0_RX_CTRL = USBHS_UEP_R_RES_STALL;
} else {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_STALL);
}
} else {
if (ep_idx == 0) {
CH585_USBHS_DEV->UEP0_TX_CTRL = USBHS_UEP_T_RES_STALL;
} else {
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_STALL);
}
}
return 0;
}
/**
* @brief Endpoint clear stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
USB_SET_RX_CTRL(ep_idx, USBHS_UEP_R_RES_ACK | USBHS_UEP_R_TOG_DATA0);
} else {
USB_SET_TX_CTRL(ep_idx, USBHS_UEP_T_RES_NAK | USBHS_UEP_T_TOG_DATA0);
}
return 0;
}
/**
* @brief Check endpoint status
* @pre None
* @param[in] ep Endpoint address
* @param[out] stalled Outgoing endpoint status
* @retval >=0 success otherwise failure
*/
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
} else {
}
return 0;
}
/**
* @brief Setup in ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with tx dma.
*
* This function is called to write data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is transmitted
* out.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to write
* @param[in] data_len Length of the data requested to write. This may
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
if (ep_idx == 0) {
if (data_len == 0) {
USB_SET_TX_LEN(ep_idx, 0);
} else {
data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
USB_SET_TX_LEN(ep_idx, data_len);
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)data;
}
} else {
if (data_len == 0) {
USB_SET_TX_LEN(ep_idx, 0);
} else {
data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
USB_SET_TX_LEN(ep_idx, data_len);
USB_SET_TX_DMA(ep_idx, (uint32_t)data);
}
}
EPn_SET_TX_VALID(ep_idx);
return 0;
}
/**
* @brief Setup out ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with rx dma.
*
* This function is called to read data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is received
* in.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to read
* @param[in] data_len Max length of the data requested to read.
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
if (ep_idx == 0) {
if (data_len == 0) {
} else {
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)data;
}
} else {
USB_SET_RX_DMA(ep_idx, (uint32_t)data);
}
EPn_SET_RX_VALID(ep_idx);
return 0;
}
static inline void handle_ep0_in(void)
{
switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
case 1:
CH585_USBHS_DEV->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
EPn_SET_TX_NAK(0);
if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
} else {
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
usb_dc_cfg.ep_in[0].xfer_len = 0;
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
}
break;
case 0:
/* Set */
switch (usb_dc_cfg.setup.bRequest) {
case USB_REQUEST_SET_ADDRESS:
/* Fill in the equipment address */
CH585_USBHS_DEV->DEV_AD = usb_dc_cfg.address;
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
EPn_SET_TX_NAK(0);
EPn_SET_RX_VALID(0);
break;
default:
/* Normal out state phase */
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
EPn_SET_TX_NAK(0);
EPn_SET_RX_VALID(0);
break;
}
break;
}
}
static inline void handle_non_ep0_in(uint8_t epid)
{
EPn_SET_TX_NAK(epid);
if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
/* Need start in again */
usb_dc_cfg.ep_in[epid].xfer_buf += usb_dc_cfg.ep_in[epid].mps;
usb_dc_cfg.ep_in[epid].xfer_len -= usb_dc_cfg.ep_in[epid].mps;
usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].mps;
uint32_t write_count = MIN(usb_dc_cfg.ep_in[epid].xfer_len, usb_dc_cfg.ep_in[epid].mps);
USB_SET_TX_LEN(epid, write_count);
USB_SET_TX_DMA(epid, (uint32_t)usb_dc_cfg.ep_in[epid].xfer_buf);
if (usb_dc_cfg.ep_in[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(epid);
} else {
EPn_SET_TX_ISO_VALID(epid);
}
} else {
usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
usb_dc_cfg.ep_in[epid].xfer_len = 0;
usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
}
}
static inline void usb_process_ep_in(uint8_t epid)
{
if (epid == 0) {
handle_ep0_in();
} else {
handle_non_ep0_in(epid);
}
EPn_CLEAR_TX_DONE(epid);
}
static inline void usb_process_ep_out(uint8_t epid)
{
EPn_SET_RX_NAK(epid);
if (epid == 0) {
if (CH585_USBHS_DEV->UEP0_RX_CTRL & USBHS_UEP_R_SETUP_IS) {
CH585_USBHS_DEV->UEP0_RX_CTRL |= USBHS_UEP_R_TOG_DATA1;
CH585_USBHS_DEV->UEP0_TX_CTRL |= USBHS_UEP_T_TOG_DATA1;
if (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT == 0) {
/**
* Ep0 The next in must be the status stage.
* The device must reply to the host data 0 length packet.
* Here, set the transmission length to 0 and the transmission status to ACK,
* and wait for the host to send the in token to retrieve
*/
EPn_SET_TX_LEN(0, 0);
EPn_SET_TX_VALID(0);
}
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&usb_dc_cfg.setup);
} else {
CH585_USBHS_DEV->UEP0_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1;
uint32_t read_count = EPn_GET_RX_LEN(0);
usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
usb_dc_cfg.ep_out[0].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
if (read_count == 0) {
/* Out status, start reading setup */
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
EPn_SET_RX_VALID(0);
}
}
} else {
if (USB_GET_RX_CTRL(epid) & USBHS_UEP_R_TOG_MATCH) {
uint32_t read_count = EPn_GET_RX_LEN(epid);
usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
usb_dc_cfg.ep_out[epid].actual_xfer_len += read_count;
usb_dc_cfg.ep_out[epid].xfer_len -= read_count;
if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(0, ((epid) & 0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
} else {
USB_SET_RX_DMA(epid, (uint32_t)usb_dc_cfg.ep_out[epid].xfer_buf);
if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(epid);
} else {
EPn_SET_RX_ISO_VALID(epid);
}
}
}
}
EPn_CLEAR_RX_DONE(epid);
}
static inline void usb_trans_end_process(void)
{
uint8_t epid = (CH585_USBHS_DEV->INT_ST & USBHS_UDIS_EP_ID_MASK);
switch (CH585_USBHS_DEV->INT_ST & USBHS_UDIS_EP_DIR) {
case USBHS_UDIS_EP_DIR: /* in */
usb_process_ep_in(epid);
break;
case 0: /* setup or out */
usb_process_ep_out(epid);
break;
default:
break;
}
}
/**
* @brief USB interrupt processing function
* @pre None
* @param[in] None
* @retval None
*/
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode"))) void
USBD_IRQHandler(void)
{
volatile uint8_t intflag = 0;
intflag = CH585_USBHS_DEV->INT_FG;
if (intflag & USBHS_UDIF_TRANSFER) {
usb_trans_end_process();
} else if (intflag & USBHS_UDIF_BUS_RST) {
/* Reset */
CH585_USBHS_DEV->DEV_AD = 0;
usbd_event_reset_handler(0);
/* Set ep0 rx vaild to start receive setup packet */
CH585_USBHS_DEV->UEP0_DMA = (uint32_t)&usb_dc_cfg.setup;
// EPn_SET_RX_VALID(0);
R8_U2EP0_TX_CTRL = USBHS_UEP_T_RES_NAK;
R8_U2EP0_RX_CTRL = USBHS_UEP_R_RES_ACK;
CH585_USBHS_DEV->INT_FG = USBHS_UDIF_BUS_RST;
} else if (intflag & USBHS_UDIF_SUSPEND) {
if (CH585_USBHS_DEV->MIS_ST & 0x04) {
/* Suspend */
} else {
/* Wake up */
}
CH585_USBHS_DEV->INT_FG = USBHS_UDIF_SUSPEND;
} else {
CH585_USBHS_DEV->INT_FG = intflag;
}
}

View File

@ -0,0 +1,450 @@
#pragma once
/**********************************/
/*********USB high speed**********/
/**********************************/
typedef volatile unsigned short *PUINT16V;
typedef volatile unsigned long *PUINT32V;
typedef volatile unsigned char *PUINT8V;
/* USB high speed device register */
#define R8_USB2_CTRL (*((PUINT8V)0x40009000)) // RW, USB_high_speed control register
#define USBHS_UD_LPM_EN 0x80 // RW, enable LPM
#define USBHS_UD_DEV_EN 0x20 // RW, enable USB equipment
#define USBHS_UD_DMA_EN 0x10 // RW, enable DMA transmit
#define USBHS_UD_PHY_SUSPENDM 0x08 // RW, suspeng USB PHY
#define USBHS_UD_CLR_ALL 0x04 // RW, clear all interupt flag
#define USBHS_UD_RST_SIE 0x02 // RW, reset USB protocol processor,including end point register
#define USBHS_UD_RST_LINK 0x01 // RW, enable LNK layer reset
#define R8_USB2_BASE_MODE (*((PUINT8V)0x40009001)) // RW, USB_high_speed mode control register
#define USBHS_UD_SPEED_FULL 0x00
#define USBHS_UD_SPEED_HIGH 0x01
#define USBHS_UD_SPEED_LOW 0x02
#define USBHS_UD_SPEED_TYPE 0x03 // RW, speed mode excpeted by the equipment,00:full speed, 01:high speed, 10:low speed
#define R8_USB2_INT_EN (*((PUINT8V)0x40009002)) // RW, USB_high_speed intreurpt enable register
#define USBHS_UDIE_FIFO_OVER 0x80 // RW, enable fifo overflow interupt
#define USBHS_UDIE_LINK_RDY 0x40 // RW, enable USB conect interupt
#define USBHS_UDIE_SOF_ACT 0x20 // RW, enable SOF package received interupt
#define USBHS_UDIE_TRANSFER 0x10 // RW, enable USB transmit end interupt
#define USBHS_UDIE_LPM_ACT 0x08 // RW, enable lpm transmit end interupt
#define USBHS_UDIE_BUS_SLEEP 0x04 // RW, enable usb bus sleep interupt
#define USBHS_UDIE_SUSPEND 0x02 // RW, enable usb bus suspend interupt
#define USBHS_UDIE_BUS_RST 0x01 // RW, enable usb bus reset interupt
#define R8_USB2_DEV_AD (*((PUINT8V)0x40009003)) // RW, USB_high_speed device adress register
#define USBHS_UD_DEV_ADDR 0x7F // RW, adress of usb equipment
#define R8_USB2_WAKE_CTRL (*((PUINT8V)0x40009004)) // RW, USB_high_speed wake up remotely register
#define USBHS_UD_UD_REMOTE_WKUP 0x01 // RW1, wake up remotely and auto reset hardware
#define R8_USB2_TEST_MODE (*((PUINT8V)0x40009005)) // RW, USB_high_speed test mode register
#define USBHS_UD_TEST_EN 0x80 // RW, enable test mode
#define USBHS_UD_TEST_SE0NAK 0x08 // RW, output SE0 when in test mode
#define USBHS_UD_TEST_PKT 0x04 // RW, output one package(including DATA0,data and length of end pont4) when in test mode,not work on virtual equipment
#define USBHS_UD_TEST_K 0x02 // RW, output K when in test mode
#define USBHS_UD_TEST_J 0x01 // RW, output J when in test mode
#define R16_USB2_LPM_DATA (*((PUINT16V)0x40009006)) // RW, USB_high_speed power control register
#define USBHS_UD_LPM_BUSY 0x8000 // RW, power control busy
#define USBHS_UD_LPM_DATA 0x07FF // RO, power control data
#define R8_USB2_INT_FG (*((PUINT8V)0x40009008)) // RW, USB_high_speed interupt flag register
#define USBHS_UDIF_FIFO_OV 0x80 // RW1, clear fifo overflow interupt flag
#define USBHS_UDIF_LINK_RDY 0x40 // RW1, clear USB conect interupt flag
#define USBHS_UDIF_RX_SOF 0x20 // RW1, clear SOF package received interupt flag
#define USBHS_UDIF_TRANSFER 0x10 // RO, USB transmit end interupt flag,cleared by USBHS_UDMS_HS_MOD
#define USBHS_UDIF_LPM_ACT 0x08 // RW1, clear lpm transmit end interupt flag
#define USBHS_UDIF_BUS_SLEEP 0x04 // RW1, clear usb bus sleep interupt flag
#define USBHS_UDIF_SUSPEND 0x02 // RW1, clear usb bus suspend interupt flag
#define USBHS_UDIF_BUS_RST 0x01 // RW1, clear usb bus reset interupt flag
#define R8_USB2_INT_ST (*((PUINT8V)0x40009009)) // RW, USB_high_speed interupt status register
#define USBHS_UDIS_EP_DIR 0x10 // RO, end point tranfer diector of data
#define USBHS_UDIS_EP_ID_MASK 0x07 // RO, number of end point which data transmission occured
#define R8_USB2_MIS_ST (*((PUINT8V)0x4000900A)) // RW, USB_high_speed miscellaneous register
#define USBHS_UDMS_HS_MOD 0x80 // RO, host with high speed
#define USBHS_UDMS_SUSP_REQ 0x10 // RO, requirment of suspending USB
#define USBHS_UDMS_SIE_FREE 0x08 // RO, USB free state
#define USBHS_UDMS_SLEEP 0x04 // RO, USB sleep state
#define USBHS_UDMS_SUSPEND 0x02 // RO, USB in suspend state
#define USBHS_UDMS_READY 0x01 // RO, USB in connected state
#define R16_USB2_FRAME_NO (*((PUINT16V)0x4000900C)) // RW, USB_high_speed frame number register
#define USBHS_UD_MFRAME_NO 0xE000
#define USBHS_UD_FRAME_NO 0x07FF
#define R16_USB2_BUS (*((PUINT16V)0x4000900E)) // RW, USB_high_speed bus status register
#define USBHS_USB_DM_ST 0x08
#define USBHS_USB_DP_ST 0x04
#define USB_WAKEUP 0x01
#define R16_U2EP_TX_EN (*((PUINT16V)0x40009010)) // RW, USB_high_speed end point transmit enable register
/* Bit definition for R16_U2EP_TX_EN & R16_U2EP_RX_EN register */
#define RB_EP0_EN 0x0001
#define RB_EP1_EN 0x0002
#define RB_EP2_EN 0x0004
#define RB_EP3_EN 0x0008
#define RB_EP4_EN 0x0010
#define RB_EP5_EN 0x0020
#define RB_EP6_EN 0x0040
#define RB_EP7_EN 0x0080
#define RB_EP8_EN 0x0100
#define RB_EP9_EN 0x0200
#define RB_EP10_EN 0x0400
#define RB_EP11_EN 0x0800
#define RB_EP12_EN 0x1000
#define RB_EP13_EN 0x2000
#define RB_EP14_EN 0x4000
#define RB_EP15_EN 0x8000
#define R16_U2EP_RX_EN (*((PUINT16V)0x40009012)) // RW, USB_high_speed end point receive enableregister
#define USBHS_UEP_RX_EN 0xFFFF
#define R16_U2EP_T_TOG_AUTO (*((PUINT16V)0x40009014)) // RW, USB_high_speed end point transmit auto toggle enable register
#define USBHS_UEP_T_TOG_AUTO 0xFF
#define R16_U2EP_R_TOG_AUTO (*((PUINT16V)0x40009016)) // RW, USB_high_speed end point receive auto toggle enable register
#define USBHS_UEP_R_TOG_AUTO 0xFF
#define R8_U2EP_T_BURST (*((PUINT8V)0x40009018)) // RW, USB_high_speed end point transmit burst register
#define USBHS_UEP_T_BURST_EN 0xFF
#define R8_U2EP_T_BURST_MODE (*((PUINT8V)0x40009019)) // RW, USB_high_speed end point transmit burst mode register
#define USBHS_UEP_T_BURST_MODE 0xFF
#define R8_U2EP_R_BURST (*((PUINT8V)0x4000901A)) // RW, USB_high_speed end point receive burst register
#define USBHS_UEP_R_BURST_EN 0xFF
#define R8_U2EP_R_RES_MODE (*((PUINT8V)0x4000901B)) // RW, USB_high_speed end point transmit reply mode register
#define USBHS_UEP_R_RES_MODE 0xFF
#define R32_U2EP_AF_MODE (*((PUINT32V)0x4000901C)) // RW, USB_high_speed end point multiplexing register
#define USBHS_UEP_T_AF 0xFE
#define R32_U2EP0_DMA (*((PUINT32V)0x40009020)) // RW, USB_high_speed end point0 begin adress of DMA buffer register
#define UEPn_DMA 0x01FFFF
#define R32_U2EP1_RX_DMA (*((PUINT32V)0x40009024)) // RW, USB_high_speed end point1 begin adress of DMA receive buffer register
#define R32_U2EP2_RX_DMA (*((PUINT32V)0x40009028)) // RW, USB_high_speed end point2 begin adress of DMA receive buffer register
#define R32_U2EP3_RX_DMA (*((PUINT32V)0x4000902C)) // RW, USB_high_speed end point3 begin adress of DMA receive buffer register
#define R32_U2EP4_RX_DMA (*((PUINT32V)0x40009030)) // RW, USB_high_speed end point4 begin adress of DMA receive buffer register
#define R32_U2EP5_RX_DMA (*((PUINT32V)0x40009034)) // RW, USB_high_speed end point5 begin adress of DMA receive buffer register
#define R32_U2EP6_RX_DMA (*((PUINT32V)0x40009038)) // RW, USB_high_speed end point6 begin adress of DMA receive buffer register
#define R32_U2EP7_RX_DMA (*((PUINT32V)0x4000903C)) // RW, USB_high_speed end point7 begin adress of DMA receive buffer register
#define UEPn_RX_DMA 0x01FFFF
#define R32_U2EP1_TX_DMA (*((PUINT32V)0x40009040)) // RW, USB_high_speed end point1 begin adress of DMA transmit buffer register
#define R32_U2EP2_TX_DMA (*((PUINT32V)0x40009044)) // RW, USB_high_speed end point2 begin adress of DMA transmit buffer register
#define R32_U2EP3_TX_DMA (*((PUINT32V)0x40009048)) // RW, USB_high_speed end point3 begin adress of DMA transmit buffer register
#define R32_U2EP4_TX_DMA (*((PUINT32V)0x4000904C)) // RW, USB_high_speed end point4 begin adress of DMA transmit buffer register
#define R32_U2EP5_TX_DMA (*((PUINT32V)0x40009050)) // RW, USB_high_speed end point5 begin adress of DMA transmit buffer register
#define R32_U2EP6_TX_DMA (*((PUINT32V)0x40009054)) // RW, USB_high_speed end point6 begin adress of DMA transmit buffer register
#define R32_U2EP7_TX_DMA (*((PUINT32V)0x40009058)) // RW, USB_high_speed end point7 begin adress of DMA transmit buffer register
#define UEPn_TX_DMA 0x01FFFF
#define R32_U2EP0_MAX_LEN (*((PUINT32V)0x4000905C)) // RW, USB_high_speed end point0 max length package register
#define R32_U2EP1_MAX_LEN (*((PUINT32V)0x40009060)) // RW, USB_high_speed end point1 max length package register
#define R32_U2EP2_MAX_LEN (*((PUINT32V)0x40009064)) // RW, USB_high_speed end point2 max length package register
#define R32_U2EP3_MAX_LEN (*((PUINT32V)0x40009068)) // RW, USB_high_speed end point3 max length package register
#define R32_U2EP4_MAX_LEN (*((PUINT32V)0x4000906C)) // RW, USB_high_speed end point4 max length package register
#define R32_U2EP5_MAX_LEN (*((PUINT32V)0x40009070)) // RW, USB_high_speed end point5 max length package register
#define R32_U2EP6_MAX_LEN (*((PUINT32V)0x40009074)) // RW, USB_high_speed end point6 max length package register
#define R32_U2EP7_MAX_LEN (*((PUINT32V)0x40009078)) // RW, USB_high_speed end point7 max length package register
#define UEPn_MAX_LEN 0x007F
#define R16_U2EP0_RX_LEN (*((PUINT16V)0x4000907C)) // RW, USB_high_speed end point0 length of receive register
#define UEP0_RX_LEN 0x007F
#define R16_U2EP1_RX_LEN (*((PUINT16V)0x40009080)) // RW, USB_high_speed end point1 single received length register
#define R16_U2EP1_R_SIZE (*((PUINT16V)0x40009082)) // RW, USB_high_speed end point1 total received length register
#define R16_U2EP2_RX_LEN (*((PUINT16V)0x40009084)) // RW, USB_high_speed end point2 single received length register
#define R16_U2EP2_R_SIZE (*((PUINT16V)0x40009086)) // RW, USB_high_speed end point2 total received length register
#define R16_U2EP3_RX_LEN (*((PUINT16V)0x40009088)) // RW, USB_high_speed end point3 single received length register
#define R16_U2EP3_R_SIZE (*((PUINT16V)0x4000908A)) // RW, USB_high_speed end point3 total received length register
#define R16_U2EP4_RX_LEN (*((PUINT16V)0x4000908C)) // RW, USB_high_speed end point4 single received length register
#define R16_U2EP4_R_SIZE (*((PUINT16V)0x4000908E)) // RW, USB_high_speed end point4 total received length register
#define R16_U2EP5_RX_LEN (*((PUINT16V)0x40009090)) // RW, USB_high_speed end point5 single received length register
#define R16_U2EP5_R_SIZE (*((PUINT16V)0x40009092)) // RW, USB_high_speed end point5 total received length register
#define R16_U2EP6_RX_LEN (*((PUINT16V)0x40009094)) // RW, USB_high_speed end point6 single received length register
#define R16_U2EP6_R_SIZE (*((PUINT16V)0x40009096)) // RW, USB_high_speed end point6 total received length register
#define R16_U2EP7_RX_LEN (*((PUINT16V)0x40009098)) // RW, USB_high_speed end point7 single received length register
#define R16_U2EP7_R_SIZE (*((PUINT16V)0x4000909A)) // RW, USB_high_speed end point7 total received length register
#define UEPn_RX_LEN 0xFFFF
#define UEPn_R_SIZE 0xFFFF
#define R16_U2EP0_T_LEN (*((PUINT16V)0x4000909C)) // RW, USB_high_speed end point0 length of transmission register
#define UEP0_T_LEN 0x7F
#define R8_U2EP0_TX_CTRL (*((PUINT8V)0x4000909E)) // RW, USB_high_speed end point0 transmit control register
#define R8_U2EP0_RX_CTRL (*((PUINT8V)0x4000909F)) // RW, USB_high_speed end point0 receive control register
#define R16_U2EP1_T_LEN (*((PUINT16V)0x400090A0)) // RW, USB_high_speed end point1 length of transmission register
#define R8_U2EP1_TX_CTRL (*((PUINT8V)0x400090A2)) // RW, USB_high_speed end point1 transmit control register
#define R8_U2EP1_RX_CTRL (*((PUINT8V)0x400090A3)) // RW, USB_high_speed end point1 receive control register
#define R16_U2EP2_T_LEN (*((PUINT16V)0x400090A4)) // RW, USB_high_speed end point2 length of transmission register
#define R8_U2EP2_TX_CTRL (*((PUINT8V)0x400090A6)) // RW, USB_high_speed end point2 transmit control register
#define R8_U2EP2_RX_CTRL (*((PUINT8V)0x400090A7)) // RW, USB_high_speed end point2 receive control register
#define R16_U2EP3_T_LEN (*((PUINT16V)0x400090A8)) // RW, USB_high_speed end point3 length of transmission register
#define R8_U2EP3_TX_CTRL (*((PUINT8V)0x400090AA)) // RW, USB_high_speed end point3 transmit control register
#define R8_U2EP3_RX_CTRL (*((PUINT8V)0x400090AB)) // RW, USB_high_speed end point3 receive control register
#define R16_U2EP4_T_LEN (*((PUINT16V)0x400090AC)) // RW, USB_high_speed end point4 length of transmission register
#define R8_U2EP4_TX_CTRL (*((PUINT8V)0x400090AE)) // RW, USB_high_speed end point4 transmit control register
#define R8_U2EP4_RX_CTRL (*((PUINT8V)0x400090AF)) // RW, USB_high_speed end point4 receive control register
#define R16_U2EP5_T_LEN (*((PUINT16V)0x400090B0)) // RW, USB_high_speed end point5 length of transmission register
#define R8_U2EP5_TX_CTRL (*((PUINT8V)0x400090B2)) // RW, USB_high_speed end point5 transmit control register
#define R8_U2EP5_RX_CTRL (*((PUINT8V)0x400090B3)) // RW, USB_high_speed end point5 receive control register
#define R16_U2EP6_T_LEN (*((PUINT16V)0x400090B4)) // RW, USB_high_speed end point6 length of transmission register
#define R8_U2EP6_TX_CTRL (*((PUINT8V)0x400090B6)) // RW, USB_high_speed end point6 transmit control register
#define R8_U2EP6_RX_CTRL (*((PUINT8V)0x400090B7)) // RW, USB_high_speed end point6 receive control register
#define R16_U2EP7_T_LEN (*((PUINT16V)0x400090B8)) // RW, USB_high_speed end point7 length of transmission register
#define R8_U2EP7_TX_CTRL (*((PUINT8V)0x400090BA)) // RW, USB_high_speed end point7 transmit control register
#define R8_U2EP7_RX_CTRL (*((PUINT8V)0x400090BB)) // RW, USB_high_speed end point7 receive control register
/**R16_UEPn_T_LEN**/
#define UEPn_T_LEN 0xFFFF
/**R8_UEPn_TX_CTRL**/
#define USBHS_UEP_T_DONE 0x80
#define USBHS_UEP_T_NAK_ACT 0x40
#define USBHS_UEP_T_TOG_MASK 0x0C
#define USBHS_UEP_T_TOG_MDATA 0x0C
#define USBHS_UEP_T_TOG_DATA2 0x08
#define USBHS_UEP_T_TOG_DATA1 0x04
#define USBHS_UEP_T_TOG_DATA0 0x00
#define USBHS_UEP_T_RES_MASK 0x03
#define USBHS_UEP_T_RES_ACK 0x02
#define USBHS_UEP_T_RES_STALL 0x01
#define USBHS_UEP_T_RES_NAK 0x00
/**R8_UEPn_RX_CTRL**/
#define USBHS_UEP_R_DONE 0x80
#define USBHS_UEP_R_NAK_ACT 0x40
#define USBHS_UEP_R_NAK_TOG 0x20
#define USBHS_UEP_R_TOG_MATCH 0x10
#define USBHS_UEP_R_SETUP_IS 0x08
#define USBHS_UEP_R_TOG_MASK 0x0C
#define USBHS_UEP_R_TOG_MDATA 0x0C
#define USBHS_UEP_R_TOG_DATA2 0x08
#define USBHS_UEP_R_TOG_DATA1 0x04
#define USBHS_UEP_R_TOG_DATA0 0x00
#define USBHS_UEP_R_RES_MASK 0x03
#define USBHS_UEP_R_RES_ACK 0x02
#define USBHS_UEP_R_RES_STALL 0x01
#define USBHS_UEP_R_RES_NAK 0x00
#define R16_U2EP_T_ISO (*((PUINT16V)0x400090BC)) // RW, USB_high_speed end point transmit sync mode register
#define USBHS_UEP1_T_ISO_EN 0x02
#define USBHS_UEP2_T_ISO_EN 0x04
#define USBHS_UEP3_T_ISO_EN 0x08
#define USBHS_UEP4_T_ISO_EN 0x10
#define USBHS_UEP5_T_ISO_EN 0x20
#define USBHS_UEP6_T_ISO_EN 0x40
#define USBHS_UEP7_T_ISO_EN 0x80
#define R16_U2EP_R_ISO (*((PUINT16V)0x400090BE)) // RW, USB_high_speed end point receive sync mode register
#define USBHS_UEP1_R_ISO_EN 0x02
#define USBHS_UEP2_R_ISO_EN 0x04
#define USBHS_UEP3_R_ISO_EN 0x08
#define USBHS_UEP4_R_ISO_EN 0x10
#define USBHS_UEP5_R_ISO_EN 0x20
#define USBHS_UEP6_R_ISO_EN 0x40
#define USBHS_UEP7_R_ISO_EN 0x80
/* USB high speed host register */
#define R8_U2H_CFG (*((PUINT8V)0x40009100)) // RW, USB_high_speed register
#define USBHS_UH_LPM_EN 0x80
#define USBHS_UH_FORCE_FS 0x40
#define USBHS_UH_SOF_EN 0x20
#define USBHS_UH_DMA_EN 0x10
#define USBHS_UH_PHY_SUSPENDM 0x08
#define USBHS_UH_CLR_ALL 0x04
#define USBHS_RST_SIE 0x02
#define USBHS_RST_LINK 0x01
#define R8_U2H_INT_EN (*((PUINT8V)0x40009102)) // RW, USB_high_speed register
#define USBHS_UHIE_FIFO_OVER 0x80
#define USBHS_UHIE_TX_HALT 0x40
#define USBHS_UHIE_SOF_ACT 0x20
#define USBHS_UHIE_TRANSFER 0x10
#define USBHS_UHIE_RESUME_ACT 0x08
#define USBHS_UHIE_WKUP_ACT 0x04
#define R8_U2H_DEV_AD (*((PUINT8V)0x40009103)) // RW, USB_high_speed register
#define USBHS_UH_DEV_ADDR 0xFF
#define R32_U2H_CONTROL (*((PUINT32V)0x40009104)) // RW, USB_high_speed register
#define USBHS_UH_RX_NO_RES 0x800000
#define USBHS_UH_TX_NO_RES 0x400000
#define USBHS_UH_RX_NO_DATA 0x200000
#define USBHS_UH_TX_NO_DATA 0x100000
#define USBHS_UH_PRE_PID_EN 0x080000
#define USBHS_UH_SPLIT_VALID 0x040000
#define USBHS_UH_LPM_VALID 0x020000
#define USBHS_UH_HOST_ACTION 0x010000
#define USBHS_UH_BUF_MODE 0x0400
#define USBHS_UH_T_TOG_MASK 0x0300
#define USBHS_UH_T_TOG_MDATA 0x0300
#define USBHS_UH_T_TOG_DATA2 0x0200
#define USBHS_UH_T_TOG_DATA1 0x0100
#define USBHS_UH_T_TOG_DATA0 0x0000
#define USBHS_UH_T_ENDP_MASK 0xF0
#define USBHS_UH_T_TOKEN_MASK 0x0F
#define R8_U2H_INT_FLAG (*((PUINT8V)0x40009108)) // RW, USB_high_speed register
#define USBHS_UHIF_FIFO_OVER 0x80
#define USBHS_UHIF_TX_HALT 0x40
#define USBHS_UHIF_SOF_ACT 0x20
#define USBHS_UHIF_TRANSFER 0x10
#define USBHS_UHIF_RESUME_ACT 0x08
#define USBHS_UHIF_WKUP_ACT 0x04
#define R8_U2H_INT_ST (*((PUINT8V)0x40009109)) // RW, USB_high_speed register
#define USBHS_UHIF_PORT_RX_RESUME 0x10
#define USBHS_UH_R_TOKEN_MASK 0x0F
#define R8_U2H_MIS_ST (*((PUINT8V)0x4000910A)) // RW, USB_high_speed register
#define USBHS_UHMS_BUS_SE0 0x80
#define USBHS_UHMS_BUS_J 0x40
#define USBHS_UHMS_LINESTATE 0x30
#define USBHS_UHMS_USB_WAKEUP 0x08
#define USBHS_UHMS_SOF_ACT 0x04
#define USBHS_UHMS_SOF_PRE 0x02
#define USBHS_UHMS_SOF_FREE 0x01
#define R32_U2H_LPM_DATA (*((PUINT32V)0x4000910C)) // RW, USB_high_speed register
#define USBHS_UH_LPM_DATA 0x07FF
#define R32_U2H_SPLIT_DATA (*((PUINT32V)0x40009110)) // RW, USB_high_speed register
#define USBHS_UH_SPLIT_DATA 0x07FFFF
#define R32_U2H_FRAME (*((PUINT32V)0x40009114)) // RW, USB_high_speed register
#define USBHS_UH_SOF_CNT_CLR 0x02000000
#define USBHS_UH_SOF_CNT_EN 0x01000000
#define USBHS_UH_MFRAME_NO 0x070000
#define USBHS_UH_FRAME_NO 0x07FF
#define R32_U2H_TX_LEN (*((PUINT32V)0x40009118)) // RW, USB_high_speed register
#define USBHS_UH_TX_LEN 0x07FF
#define R32_U2H_RX_LEN (*((PUINT32V)0x4000911C)) // RW, USB_high_speed register
#define USBHS_UH_RX_LEN 0x07FF
#define R32_U2H_RX_MAX_LEN (*((PUINT32V)0x40009120)) // RW, USB_high_speed register
#define USBHS_UH_RX_MAX_LEN 0x07FF
#define R32_U2H_RX_DMA (*((PUINT32V)0x40009124)) // RW, USB_high_speed register
#define USBHS_R32_UH_RX_DMA 0x01FFFF
#define R32_U2H_TX_DMA (*((PUINT32V)0x40009128)) // RW, USB_high_speed register
#define USBHS_R32_UH_TX_DMA 0x01FFFF
#define R32_U2H_PORT_CTRL (*((PUINT32V)0x4000912C)) // RW, USB_high_speed register
#define USBHS_UH_BUS_RST_LONG 0x010000
#define USBHS_UH_PORT_SLEEP_BESL 0xF000
#define USBHS_UH_CLR_PORT_SLEEP 0x0100
#define USBHS_UH_CLR_PORT_CONNECT 0x20
#define USBHS_UH_CLR_PORT_EN 0x10
#define USBHS_UH_SET_PORT_SLEEP 0x08
#define USBHS_UH_CLR_PORT_SUSP 0x04
#define USBHS_UH_SET_PORT_SUSP 0x02
#define USBHS_UH_SET_PORT_RESET 0x01
#define R8_U2H_PORT_CFG (*((PUINT8V)0x40009130)) // RW, USB_high_speed register
#define USBHS_UH_PD_EN 0x80
#define USBHS_UH_HOST_EN 0x01
#define R8_U2H_PORT_INT_EN (*((PUINT8V)0x40009132)) // RW, USB_high_speed register
#define USBHS_UHIE_PORT_SLP 0x20
#define USBHS_UHIE_PORT_RESET 0x10
#define USBHS_UHIE_PORT_SUSP 0x04
#define USBHS_UHIE_PORT_EN 0x02
#define USBHS_UHIE_PORT_CONNECT 0x01
#define R8_U2H_PORT_TEST_CT (*((PUINT8V)0x40009133)) // RW, USB_high_speed register
#define USBHS_UH_TEST_FORCE_EN 0x04
#define USBHS_UH_TEST_K 0x02
#define USBHS_UH_TEST_J 0x01
#define R16_U2H_PORT_ST (*((PUINT16V)0x40009134)) // RW, USB_high_speed register
#define USBHS_UHIS_PORT_TEST 0x0800
#define USBHS_UHIS_PORT_SPEED_MASK 0x0600
#define USBHS_UHIS_PORT_HS 0x0400
#define USBHS_UHIS_PORT_LS 0x0200
#define USBHS_UHIS_PORT_FS 0x0000
#define USBHS_UHIS_PORT_SLP 0x20
#define USBHS_UHIS_PORT_RST 0x10
#define USBHS_UHIS_PORT_SUSP 0x04
#define USBHS_UHIS_PORT_EN 0x02
#define USBHS_UHIS_PORT_CONNECT 0x01
#define R8_U2H_PORT_CHG (*((PUINT8V)0x40009136))
#define USBHS_UHIF_PORT_SLP 0x20
#define USBHS_UHIF_PORT_RESET 0x10
#define USBHS_UHIF_PORT_SUSP 0x04
#define USBHS_UHIF_PORT_EN 0x02
#define USBHS_UHIF_PORT_CONNECT 0x01
#define R32_U2H_BC_CTRL (*((PUINT32V)0x4000913C))
#define UDM_VSRC_ACT 0x0400
#define UDM_BC_VSRC 0x0200
#define UDP_BC_VSRC 0x0100
#define BC_AUTO_MODE 0x40
#define UDM_BC_CMPE 0x20
#define UDP_BC_CMPE 0x10
#define UDM_BC_CMPO 0x02
#define UDP_BC_CMPO 0x01
#define R8_USBHS_PLL_CTRL (*((PUINT8V)0x40009200))
#define USBHS_PLL_EN 0x04
#define USBHS_PLL_LOWPOW 0x02
#define USBHS_PLL_CKSEL 0x01
#define __IO volatile /* defines 'read / write' permissions */
typedef struct
{
__IO uint8_t CONTROL; /* 0x40009000 */
__IO uint8_t BASE_MODE; /* 0x40009001 */
__IO uint8_t INT_EN; /* 0x40009002 */
__IO uint8_t DEV_AD; /* 0x40009003 */
__IO uint8_t WAKE_CTRL; /* 0x40009004 远程唤醒寄存器 */
__IO uint8_t TEST_MODE; /* 0x40009005 测试模式寄存器 */
__IO uint16_t LPM_DATA; /* 0x40009006 */
__IO uint8_t INT_FG; /* 0x40009008 */
__IO uint8_t INT_ST; /* 0x40009009 */
__IO uint8_t MIS_ST; /* 0x4000900a */
__IO uint8_t RESERVE0; /* 0x4000900b */
__IO uint16_t FRAME_NO; /* 0x4000900c */
__IO uint16_t USB_BUS; /* 0x4000900e */
__IO uint16_t UEP_TX_EN; /* 0x40009010 */
__IO uint16_t UEP_RX_EN; /* 0x40009012 */
__IO uint16_t UEP_T_TOG_AUTO; /* 0x40009014 */
__IO uint16_t UEP_R_TOG_AUTO; /* 0x40009016 */
__IO uint8_t UEP_T_BURST; /* 0x40009018 */
__IO uint8_t UEP_T_BURST_MODE; /* 0x40009019 */
__IO uint8_t UEP_R_BURST; /* 0x4000901a */
__IO uint8_t UEP_R_RES_MODE; /* 0x4000901b */
__IO uint32_t UEP_AF_MODE; /* 0x4000901c */
__IO uint32_t UEP0_DMA; /* 0x40009020 */
__IO uint32_t UEP1_RX_DMA; /* 0x40009024 */
__IO uint32_t UEP2_RX_DMA; /* 0x40009028 */
__IO uint32_t UEP3_RX_DMA; /* 0x4000902c */
__IO uint32_t UEP4_RX_DMA; /* 0x40009030 */
__IO uint32_t UEP5_RX_DMA; /* 0x40009034 */
__IO uint32_t UEP6_RX_DMA; /* 0x40009038 */
__IO uint32_t UEP7_RX_DMA; /* 0x4000903c */
__IO uint32_t UEP1_TX_DMA; /* 0x40009040 */
__IO uint32_t UEP2_TX_DMA; /* 0x40009044 */
__IO uint32_t UEP3_TX_DMA; /* 0x40009048 */
__IO uint32_t UEP4_TX_DMA; /* 0x4000904c */
__IO uint32_t UEP5_TX_DMA; /* 0x40009050 */
__IO uint32_t UEP6_TX_DMA; /* 0x40009054 */
__IO uint32_t UEP7_TX_DMA; /* 0x40009058 */
__IO uint32_t UEP0_MAX_LEN; /* 0x4000905c */
__IO uint32_t UEP1_MAX_LEN; /* 0x40009060 */
__IO uint32_t UEP2_MAX_LEN; /* 0x40009064 */
__IO uint32_t UEP3_MAX_LEN; /* 0x40009068 */
__IO uint32_t UEP4_MAX_LEN; /* 0x4000906c */
__IO uint32_t UEP5_MAX_LEN; /* 0x40009070 */
__IO uint32_t UEP6_MAX_LEN; /* 0x40009074 */
__IO uint32_t UEP7_MAX_LEN; /* 0x40009078 */
__IO uint16_t USB_EP0_RX_LEN; /* 0x4000907c */
__IO uint16_t RESERVE1; /* 0x4000907e */
__IO uint16_t UEP1_RX_LEN; /* 0x40009080 */
__IO uint16_t UEP1_R_SIZE; /* 0x40009082 */
__IO uint16_t UEP2_RX_LEN; /* 0x40009084 */
__IO uint16_t UEP2_R_SIZE; /* 0x40009086 */
__IO uint16_t UEP3_RX_LEN; /* 0x40009088 */
__IO uint16_t UEP3_R_SIZE; /* 0x4000908a */
__IO uint16_t UEP4_RX_LEN; /* 0x4000908c */
__IO uint16_t UEP4_R_SIZE; /* 0x4000908e */
__IO uint16_t UEP5_RX_LEN; /* 0x40009090 */
__IO uint16_t UEP5_R_SIZE; /* 0x40009092 */
__IO uint16_t UEP6_RX_LEN; /* 0x40009094 */
__IO uint16_t UEP6_R_SIZE; /* 0x40009096 */
__IO uint16_t UEP7_RX_LEN; /* 0x40009098 */
__IO uint16_t UEP7_R_SIZE; /* 0x4000909a */
__IO uint16_t UEP0_TX_LEN; /* 0x4000909c */
__IO uint8_t UEP0_TX_CTRL; /* 0x4000909e */
__IO uint8_t UEP0_RX_CTRL; /* 0x4000909f */
__IO uint16_t UEP1_TX_LEN; /* 0x400090a0 */
__IO uint8_t UEP1_TX_CTRL; /* 0x400090a2 */
__IO uint8_t UEP1_RX_CTRL; /* 0x400090a3 */
__IO uint16_t UEP2_TX_LEN; /* 0x400090a4 */
__IO uint8_t UEP2_TX_CTRL; /* 0x400090a6 */
__IO uint8_t UEP2_RX_CTRL; /* 0x400090a7 */
__IO uint16_t UEP3_TX_LEN; /* 0x400090a8 */
__IO uint8_t UEP3_TX_CTRL; /* 0x400090aa */
__IO uint8_t UEP3_RX_CTRL; /* 0x400090ab */
__IO uint16_t UEP4_TX_LEN; /* 0x400090ac */
__IO uint8_t UEP4_TX_CTRL; /* 0x400090ae */
__IO uint8_t UEP4_RX_CTRL; /* 0x400090af */
__IO uint16_t UEP5_TX_LEN; /* 0x400090b0 */
__IO uint8_t UEP5_TX_CTRL; /* 0x400090b2 */
__IO uint8_t UEP5_RX_CTRL; /* 0x400090b3 */
__IO uint16_t UEP6_TX_LEN; /* 0x400090b4 */
__IO uint8_t UEP6_TX_CTRL; /* 0x400090b6 */
__IO uint8_t UEP6_RX_CTRL; /* 0x400090b7 */
__IO uint16_t UEP7_TX_LEN; /* 0x400090b8 */
__IO uint8_t UEP7_TX_CTRL; /* 0x400090ba */
__IO uint8_t UEP7_RX_CTRL; /* 0x400090bb */
__IO uint16_t UEP_TX_ISO; /* 0x400090bc */
__IO uint16_t UEP_RX_ISO; /* 0x400090be */
} USBHSD_TypeDef;

View File

@ -0,0 +1,639 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usb_ch58x_usbfs_reg.h"
/**
* @brief Related register macro
*/
#define USB0_BASE 0x40008000u
#define USB1_BASE 0x40008400u
#ifndef USBD
#define USBD USB0_BASE
#endif
#define CH58x_USBFS_DEV ((USB_FS_TypeDef *)USBD)
#ifndef USBD_IRQHandler
#define USBD_IRQHandler USB_IRQHandler //use actual usb irq name instead
#endif
/*!< 8-bit value of endpoint control register */
#define EPn_CTRL(epid) \
*(volatile uint8_t *)(&(CH58x_USBFS_DEV->UEP0_CTRL) + epid * 4 + (epid / 5) * 48)
/*!< The length register value of the endpoint send buffer */
#define EPn_TX_LEN(epid) \
*(volatile uint8_t *)(&(CH58x_USBFS_DEV->UEP0_T_LEN) + epid * 4 + (epid / 5) * 48)
/*!< Read setup packet to use in ep0 in */
#define GET_SETUP_PACKET(data_add) \
*(struct usb_setup_packet *)data_add
/*!< Set epid ep tx valid // Not an isochronous endpoint */
#define EPn_SET_TX_VALID(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
/*!< Set epid ep rx valid // Not an isochronous endpoint */
#define EPn_SET_RX_VALID(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_ACK;
/*!< Set epid ep tx valid // Isochronous endpoint */
#define EPn_SET_TX_ISO_VALID(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_TOUT;
/*!< Set epid ep rx valid // Isochronous endpoint */
#define EPn_SET_RX_ISO_VALID(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_TOUT;
/*!< Set epid ep tx nak */
#define EPn_SET_TX_NAK(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
/*!< Set epid ep rx nak */
#define EPn_SET_RX_NAK(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_NAK;
/*!< Set epid ep tx stall */
#define EPn_SET_TX_STALL(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_T_RES) | UEP_T_RES_STALL
/*!< Set epid ep rx stall */
#define EPn_SET_RX_STALL(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~MASK_UEP_R_RES) | UEP_R_RES_STALL
/*!< Clear epid ep tx stall */
#define EPn_CLR_TX_STALL(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK
/*!< Clear epid ep rx stall */
#define EPn_CLR_RX_STALL(epid) \
EPn_CTRL(epid) = (EPn_CTRL(epid) & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK
/*!< Set epid ep tx len */
#define EPn_SET_TX_LEN(epid, len) \
EPn_TX_LEN(epid) = len
/*!< Get epid ep rx len */
#define EPn_GET_RX_LEN(epid) \
CH58x_USBFS_DEV->USB_RX_LEN
/*!< ep nums */
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 5
#endif
/*!< ep mps */
#define EP_MPS 64
/*!< set ep4 in mps 64 */
#define EP4_IN_MPS EP_MPS
/*!< set ep4 out mps 64 */
#define EP4_OUT_MPS EP_MPS
/*!< User defined assignment endpoint RAM */
__attribute__((aligned(4))) uint8_t ep0_data_buff[64 + EP4_OUT_MPS + EP4_IN_MPS]; /*!< ep0(64)+ep4_out(64)+ep4_in(64) */
__attribute__((aligned(4))) uint8_t ep1_data_buff[64 + 64]; /*!< ep1_out(64)+ep1_in(64) */
__attribute__((aligned(4))) uint8_t ep2_data_buff[64 + 64]; /*!< ep2_out(64)+ep2_in(64) */
__attribute__((aligned(4))) uint8_t ep3_data_buff[64 + 64]; /*!< ep3_out(64)+ep3_in(64) */
#if (CONFIG_USBDEV_EP_NUM == 8)
/**
* This dcd porting can be used on ch581, ch582, ch583,
* and also on ch571, ch572, and ch573. Note that only five endpoints are available for ch571, ch572, and ch573.
*/
__attribute__((aligned(4))) uint8_t ep5_data_buff[64 + 64]; /*!< ep5_out(64)+ep5_in(64) */
__attribute__((aligned(4))) uint8_t ep6_data_buff[64 + 64]; /*!< ep6_out(64)+ep6_in(64) */
__attribute__((aligned(4))) uint8_t ep7_data_buff[64 + 64]; /*!< ep7_out(64)+ep7_in(64) */
#endif
/**
* @brief Endpoint information structure
*/
typedef struct _usbd_ep_info {
uint8_t mps; /*!< Maximum packet length of endpoint */
uint8_t eptype; /*!< Endpoint Type */
uint8_t *ep_ram_addr; /*!< Endpoint buffer address */
uint8_t ep_enable; /* Endpoint enable */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
} usbd_ep_info;
/*!< ch58x usb */
static struct _ch58x_core_prvi {
uint8_t address; /*!< Address */
usbd_ep_info ep_in[CONFIG_USBDEV_EP_NUM];
usbd_ep_info ep_out[CONFIG_USBDEV_EP_NUM];
struct usb_setup_packet setup;
} usb_dc_cfg;
__WEAK void usb_dc_low_level_init(void)
{
}
__WEAK void usb_dc_low_level_deinit(void)
{
}
/**
* @brief USB initialization
* @pre None
* @param[in] None
* @retval >=0 success otherwise failure
*/
int usb_dc_init(uint8_t busid)
{
usb_dc_cfg.ep_in[0].ep_ram_addr = ep0_data_buff;
usb_dc_cfg.ep_out[0].ep_ram_addr = ep0_data_buff;
usb_dc_cfg.ep_in[1].ep_ram_addr = ep1_data_buff + 64;
usb_dc_cfg.ep_out[1].ep_ram_addr = ep1_data_buff;
usb_dc_cfg.ep_in[2].ep_ram_addr = ep2_data_buff + 64;
usb_dc_cfg.ep_out[2].ep_ram_addr = ep2_data_buff;
usb_dc_cfg.ep_in[3].ep_ram_addr = ep3_data_buff + 64;
usb_dc_cfg.ep_out[3].ep_ram_addr = ep3_data_buff;
usb_dc_cfg.ep_in[4].ep_ram_addr = ep0_data_buff + 64 + EP4_OUT_MPS;
usb_dc_cfg.ep_out[4].ep_ram_addr = ep0_data_buff + 64;
#if (CONFIG_USBDEV_EP_NUM == 8)
usb_dc_cfg.ep_in[5].ep_ram_addr = ep5_data_buff + 64;
usb_dc_cfg.ep_out[5].ep_ram_addr = ep5_data_buff;
usb_dc_cfg.ep_in[6].ep_ram_addr = ep6_data_buff + 64;
usb_dc_cfg.ep_out[6].ep_ram_addr = ep6_data_buff;
usb_dc_cfg.ep_in[7].ep_ram_addr = ep7_data_buff + 64;
usb_dc_cfg.ep_out[7].ep_ram_addr = ep7_data_buff;
#endif
/*!< Set the mode first and cancel RB_UC_CLR_ALL */
CH58x_USBFS_DEV->USB_CTRL = 0x00;
CH58x_USBFS_DEV->UEP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | RB_UEP1_RX_EN | RB_UEP1_TX_EN; /*!< EP4 OUT+IN EP1 OUT+IN */
CH58x_USBFS_DEV->UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | RB_UEP3_RX_EN | RB_UEP3_TX_EN; /*!< EP2 OUT+IN EP3 OUT+IN */
#if (CONFIG_USBDEV_EP_NUM == 8)
CH58x_USBFS_DEV->UEP567_MOD = RB_UEP5_RX_EN | RB_UEP5_TX_EN | RB_UEP6_RX_EN | RB_UEP6_TX_EN | RB_UEP7_RX_EN | RB_UEP7_TX_EN; /*!< EP5 EP6 EP7 OUT+IN */
#endif
CH58x_USBFS_DEV->UEP0_DMA = (uint16_t)(uint32_t)ep0_data_buff;
CH58x_USBFS_DEV->UEP1_DMA = (uint16_t)(uint32_t)ep1_data_buff;
CH58x_USBFS_DEV->UEP2_DMA = (uint16_t)(uint32_t)ep2_data_buff;
CH58x_USBFS_DEV->UEP3_DMA = (uint16_t)(uint32_t)ep3_data_buff;
#if (CONFIG_USBDEV_EP_NUM == 8)
CH58x_USBFS_DEV->UEP5_DMA = (uint16_t)(uint32_t)ep5_data_buff;
CH58x_USBFS_DEV->UEP6_DMA = (uint16_t)(uint32_t)ep6_data_buff;
CH58x_USBFS_DEV->UEP7_DMA = (uint16_t)(uint32_t)ep7_data_buff;
#endif
CH58x_USBFS_DEV->UEP0_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK;
CH58x_USBFS_DEV->UEP1_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
CH58x_USBFS_DEV->UEP2_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
CH58x_USBFS_DEV->UEP3_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
CH58x_USBFS_DEV->UEP4_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK;
#if (CONFIG_USBDEV_EP_NUM == 8)
CH58x_USBFS_DEV->UEP5_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
CH58x_USBFS_DEV->UEP6_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
CH58x_USBFS_DEV->UEP7_CTRL = UEP_R_RES_NAK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
#endif
CH58x_USBFS_DEV->USB_DEV_AD = 0x00;
/*!< Start the USB device and DMA, and automatically return to NAK before the interrupt flag is cleared during the interrupt */
CH58x_USBFS_DEV->USB_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN;
if ((uint32_t) & (CH58x_USBFS_DEV->USB_CTRL) == (uint32_t)USB0_BASE) {
/*!< USB0 */
R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB_DP_PU;
} else if ((uint32_t) & (CH58x_USBFS_DEV->USB_CTRL) == (uint32_t)USB1_BASE) {
/*!< USB1 */
R16_PIN_ANALOG_IE |= RB_PIN_USB2_IE | RB_PIN_USB2_DP_PU;
}
CH58x_USBFS_DEV->USB_INT_FG = 0xff; /*!< Clear interrupt flag */
CH58x_USBFS_DEV->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; /*!< Allow USB port */
CH58x_USBFS_DEV->USB_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER;
usb_dc_low_level_init();
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
return 0;
}
/**
* @brief Set address
* @pre None
* @param[in] address 8-bit valid address
* @retval >=0 success otherwise failure
*/
int usbd_set_address(uint8_t busid, const uint8_t address)
{
if (address == 0) {
CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & 0x80) | address;
}
usb_dc_cfg.address = address;
return 0;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}
uint8_t usbd_get_port_speed(uint8_t busid)
{
return USB_SPEED_FULL;
}
/**
* @brief Open endpoint
* @pre None
* @param[in] ep_cfg : Endpoint configuration structure pointer
* @retval >=0 success otherwise failure
*/
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep->bEndpointAddress);
if (epid > (CONFIG_USBDEV_EP_NUM - 1)) {
/**
* If you use ch58x, you can change the CONFIG_USBDEV_EP_NUM set to 8
*/
USB_LOG_ERR("Ep addr %02x overflow\r\n", ep->bEndpointAddress);
return -1;
}
/*!< ep max packet length */
uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
/*!< update ep max packet length */
if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = true;
usb_dc_cfg.ep_in[epid].mps = mps;
usb_dc_cfg.ep_in[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
} else if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = true;
usb_dc_cfg.ep_out[epid].mps = mps;
usb_dc_cfg.ep_out[epid].eptype = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
}
return 0;
}
/**
* @brief Close endpoint
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_IN(ep)) {
/*!< in */
usb_dc_cfg.ep_in[epid].ep_enable = false;
} else if (USB_EP_DIR_IS_OUT(ep)) {
/*!< out */
usb_dc_cfg.ep_out[epid].ep_enable = false;
}
return 0;
}
/**
* @brief Endpoint setting stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
/*!< ep id */
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_SET_RX_STALL(epid);
} else {
EPn_SET_TX_STALL(epid);
}
return 0;
}
/**
* @brief Endpoint clear stall
* @pre None
* @param[in] ep Endpoint address
* @retval >=0 success otherwise failure
*/
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t epid = USB_EP_GET_IDX(ep);
if (USB_EP_DIR_IS_OUT(ep)) {
EPn_CLR_RX_STALL(epid);
} else {
EPn_CLR_TX_STALL(epid);
}
return 0;
}
/**
* @brief Check endpoint status
* @pre None
* @param[in] ep Endpoint address
* @param[out] stalled Outgoing endpoint status
* @retval >=0 success otherwise failure
*/
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
} else {
}
return 0;
}
/**
* @brief Setup in ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with tx dma.
*
* This function is called to write data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is transmitted
* out.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to write
* @param[in] data_len Length of the data requested to write. This may
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_in[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
/*!< write 0 len data */
EPn_SET_TX_LEN(ep_idx, 0);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
/*!< return */
return 0;
} else {
/*!< Not zlp */
data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
/*!< write buff */
memcpy(usb_dc_cfg.ep_in[ep_idx].ep_ram_addr, data, data_len);
/*!< write real_wt_nums len data */
EPn_SET_TX_LEN(ep_idx, data_len);
/*!< enable tx */
if (usb_dc_cfg.ep_in[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(ep_idx);
} else {
EPn_SET_TX_ISO_VALID(ep_idx);
}
}
return 0;
}
/**
* @brief Setup out ep transfer setting and start transfer.
*
* This function is asynchronous.
* This function is similar to uart with rx dma.
*
* This function is called to read data to the specified endpoint. The
* supplied usbd_endpoint_callback function will be called when data is received
* in.
*
* @param[in] ep Endpoint address corresponding to the one
* listed in the device configuration table
* @param[in] data Pointer to data to read
* @param[in] data_len Max length of the data requested to read.
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!usb_dc_cfg.ep_out[ep_idx].ep_enable) {
return -2;
}
if ((uint32_t)data & 0x03) {
return -3;
}
usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
} else {
data_len = MIN(data_len, usb_dc_cfg.ep_out[ep_idx].mps);
}
if (usb_dc_cfg.ep_out[ep_idx].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(ep_idx);
} else {
EPn_SET_RX_ISO_VALID(ep_idx);
}
return 0;
}
/**
* @brief USB interrupt processing function
* @pre None
* @param[in] None
* @retval None
*/
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode"))) void
USBD_IRQHandler(void)
{
volatile uint8_t intflag = 0;
intflag = CH58x_USBFS_DEV->USB_INT_FG;
if (intflag & RB_UIF_TRANSFER) {
if ((CH58x_USBFS_DEV->USB_INT_ST & MASK_UIS_TOKEN) != MASK_UIS_TOKEN) {
uint8_t epid = ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0x0f);
switch ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0xf0) {
case UIS_TOKEN_IN:
if (epid == 0) {
/**
* IN The host takes away the data that has been stored in FIFO
*/
switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
case 1:
/*!< Get */
CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_T_TOG;
/**
* Here is to take away the last data, and the IN interrupt will be triggered only after it is successfully taken away.
* Therefore, the status of the in endpoint is set to NAK here. If there is data transmission,
* the endpoint status will be set to ack again in the in handler of EP0.
*/
EPn_SET_TX_NAK(0);
/*!< IN */
if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
} else {
usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
usb_dc_cfg.ep_in[0].xfer_len = 0;
usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
}
break;
case 0:
/*!< Set */
switch (usb_dc_cfg.setup.bRequest) {
case USB_REQUEST_SET_ADDRESS:
/*!< Fill in the equipment address */
CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & RB_UDA_GP_BIT) | usb_dc_cfg.address;
/**
* In the state phase after setting the address, the host has sent an in token packet of data1 to take the packet of 0 length,
* Ch58x USB IP needs to manually set the status of the in endpoint to NAK
*/
EPn_SET_TX_NAK(0);
EPn_SET_RX_VALID(0);
break;
default:
/*!< Normal out state phase */
/**
* The host has sent an in token packet of data1 and taken the packet of 0 length.
* Here, you only need to set the status of the in endpoint to NAK and out endpoint ACK
*/
EPn_SET_TX_NAK(0);
EPn_SET_RX_VALID(0);
break;
}
break;
}
} else {
if (epid == 4) {
CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_T_TOG;
}
EPn_SET_TX_NAK(epid);
if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
/*!< Need start in again */
usb_dc_cfg.ep_in[epid].xfer_buf += usb_dc_cfg.ep_in[epid].mps;
usb_dc_cfg.ep_in[epid].xfer_len -= usb_dc_cfg.ep_in[epid].mps;
usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].mps;
if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].mps);
EPn_SET_TX_LEN(epid, usb_dc_cfg.ep_in[epid].mps);
} else {
memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].xfer_len);
EPn_SET_TX_LEN(epid, usb_dc_cfg.ep_in[epid].xfer_len);
}
if (usb_dc_cfg.ep_in[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_TX_VALID(epid);
} else {
EPn_SET_TX_ISO_VALID(epid);
}
} else {
usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
usb_dc_cfg.ep_in[epid].xfer_len = 0;
usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
}
}
break;
case UIS_TOKEN_OUT:
EPn_SET_RX_NAK(epid);
if (epid == 0) {
/*!< ep0 out */
CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_R_TOG;
uint32_t read_count = EPn_GET_RX_LEN(0);
memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
usb_dc_cfg.ep_out[0].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
if (read_count == 0) {
/*!< Out status, start reading setup */
EPn_SET_RX_VALID(0);
}
} else {
if ((CH58x_USBFS_DEV->USB_INT_ST) & RB_UIS_TOG_OK) {
if (epid == 4) {
CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_R_TOG;
}
uint32_t read_count = EPn_GET_RX_LEN(epid);
memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
usb_dc_cfg.ep_out[epid].actual_xfer_len += read_count;
usb_dc_cfg.ep_out[epid].xfer_len -= read_count;
if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
usbd_event_ep_out_complete_handler(0, ((epid)&0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
} else {
if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
EPn_SET_RX_VALID(epid);
} else {
EPn_SET_RX_ISO_VALID(epid);
}
}
}
}
break;
default:
break;
}
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
}
if (CH58x_USBFS_DEV->USB_INT_ST & RB_UIS_SETUP_ACT) {
/*!< Setup */
/**
* Setup the device must respond with ACK, and the next data phase is DATA1
* If it is sent, the data1 packet will be sent.
* If it is received, the data1 packet is expected to be received.
* If it is in, the host will send the data1 out packet to complete the status phase after the in completes.
* If it is out, the host will send the data1 in packet to complete the status phase after the out completes.
*/
CH58x_USBFS_DEV->UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_T_RES_NAK;
/*!< get setup packet */
usb_dc_cfg.setup = GET_SETUP_PACKET(usb_dc_cfg.ep_out[0].ep_ram_addr);
if (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT == 0) {
/**
* Ep0 The next in must be the status stage.
* The device must reply to the host data 0 length packet.
* Here, set the transmission length to 0 and the transmission status to ACK,
* and wait for the host to send the in token to retrieve
*/
EPn_SET_TX_LEN(0, 0);
EPn_SET_TX_VALID(0);
}
EPn_SET_RX_NAK(0);
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&(usb_dc_cfg.setup));
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
}
} else if (intflag & RB_UIF_BUS_RST) {
/*!< Reset */
CH58x_USBFS_DEV->USB_DEV_AD = 0;
usbd_event_reset_handler(0);
/*!< Set ep0 rx vaild to start receive setup packet */
EPn_SET_RX_VALID(0);
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_BUS_RST;
} else if (intflag & RB_UIF_SUSPEND) {
if (CH58x_USBFS_DEV->USB_MIS_ST & RB_UMS_SUSPEND) {
/*!< Suspend */
} else {
/*!< Wake up */
}
CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_SUSPEND;
} else {
CH58x_USBFS_DEV->USB_INT_FG = intflag;
}
}

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#define __IO volatile
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RB_UC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
#define RB_UC_LOW_SPEED 0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps
#define RB_UC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable
#define RB_UC_SYS_CTRL1 0x20 // USB system control high bit
#define RB_UC_SYS_CTRL0 0x10 // USB system control low bit
#define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control
#define RB_UC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid
#define RB_UC_RESET_SIE 0x04 // force reset USB SIE, need software clear
#define RB_UC_CLR_ALL 0x02 // force clear FIFO and count of USB
#define RB_UC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB
#define RB_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define RB_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define RB_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define RB_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
#define RB_UD_GP_BIT 0x02 // general purpose bit
#define RB_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
#define RB_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define RB_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define RB_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define RB_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
#define RB_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
#define RB_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
#define RB_UIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode
#define RB_UIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
#define RB_UIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
#define RB_UIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode
#define RB_UIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event
#define RB_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
#define RB_UIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
#define RB_UIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
#define RB_UDA_GP_BIT 0x80 // general purpose bit
#define MASK_USB_ADDR 0x7F // bit mask for USB device address
#define RB_UMS_SOF_PRES 0x80 // RO, indicate host SOF timer presage status
#define RB_UMS_SOF_ACT 0x40 // RO, indicate host SOF timer action status for USB host
#define RB_UMS_SIE_FREE 0x20 // RO, indicate USB SIE free status
#define RB_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty)
#define RB_UMS_BUS_RESET 0x08 // RO, indicate USB bus reset status
#define RB_UMS_SUSPEND 0x04 // RO, indicate USB suspend status
#define RB_UMS_DM_LEVEL 0x02 // RO, indicate UDM level saved at device attached to USB host
#define RB_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host
#define RB_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
#define RB_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define RB_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
#define RB_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
#define RB_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
#define RB_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
#define RB_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
#define RB_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
#define RB_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
#define RB_UIS_SETUP_ACT 0x80 // RO, indicate SETUP token & 8 bytes setup request received for USB device mode
#define RB_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define RB_UIS_TOKEN1 0x20 // RO, current token PID code bit 1 received for USB device mode
#define RB_UIS_TOKEN0 0x10 // RO, current token PID code bit 0 received for USB device mode
#define MASK_UIS_TOKEN 0x30 // RO, bit mask of current token PID code received for USB device mode
#define UIS_TOKEN_OUT 0x00
#define UIS_TOKEN_SOF 0x10
#define UIS_TOKEN_IN 0x20
#define UIS_TOKEN_SETUP 0x30
#define MASK_UIS_ENDP 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
#define MASK_UIS_H_RES 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
#define R8_USB_RX_LEN (*((uint8_t *)0x40008008)) // USB receiving length
#define RB_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
#define RB_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
#define RB_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
#define RB_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
#define RB_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
#define RB_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
#define RB_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
#define RB_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
#define RB_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
#define RB_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
#define RB_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
#define RB_UEP7_RX_EN 0x20 // enable USB endpoint 7 receiving (OUT)
#define RB_UEP7_TX_EN 0x10 // enable USB endpoint 7 transmittal (IN)
#define RB_UEP6_RX_EN 0x08 // enable USB endpoint 6 receiving (OUT)
#define RB_UEP6_TX_EN 0x04 // enable USB endpoint 6 transmittal (IN)
#define RB_UEP5_RX_EN 0x02 // enable USB endpoint 5 receiving (OUT)
#define RB_UEP5_TX_EN 0x01 // enable USB endpoint 5 transmittal (IN)
#define RB_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
#define RB_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
#define RB_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
#define RB_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
#define RB_UEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
#define RB_UEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
#define RB_UEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
#define RB_UEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT)
#define RB_UEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT)
#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT)
#define UEP_R_RES_ACK 0x00
#define UEP_R_RES_TOUT 0x04
#define UEP_R_RES_NAK 0x08
#define UEP_R_RES_STALL 0x0C
#define RB_UEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
#define RB_UEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
#define UEP_T_RES_ACK 0x00
#define UEP_T_RES_TOUT 0x01
#define UEP_T_RES_NAK 0x02
#define UEP_T_RES_STALL 0x03
#define RB_UH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
#define RB_UH_SOF_EN 0x40 // USB host automatic SOF enable
#define R8_UH_EP_PID R8_UEP2_T_LEN // host endpoint and PID
#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer
#define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer
#define R8_UH_RX_CTRL R8_UEP2_CTRL // host receiver endpoint control
#define RB_UH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
#define RB_UH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define RB_UH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
#define R8_UH_TX_LEN R8_UEP3_T_LEN // host transmittal endpoint transmittal length
#define RB_UH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
#define RB_UH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define RB_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
#define R16_PIN_ANALOG_IE (*((uint16_t *)0x4000101A)) // RW, analog pin enable and digital input disable
#define RB_PIN_USB_IE 0x80 // RW, USB analog I/O enable: 0=analog I/O disable, 1=analog I/O enable
#define RB_PIN_USB_DP_PU 0x40 // RW, USB UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode
#define RB_PIN_USB2_IE 0x20 // RW, USB2 analog I/O enable: 0=analog I/O disable, 1=analog I/O enable
#define RB_PIN_USB2_DP_PU 0x10 // RW, USB2 UDP internal pullup resistance enable: 0=enable/disable by RB_UC_DEV_PU_EN, 1=enable pullup, replace RB_UC_DEV_PU_EN under sleep mode
/*!< USB Regs */
typedef struct
{
__IO uint8_t USB_CTRL; /*!< 0x40008000 */
union {
__IO uint8_t UDEV_CTRL; /*!< 0x40008001 */
__IO uint8_t UHOST_CTRL; /*!< 0x40008001 */
};
__IO uint8_t USB_INT_EN; /*!< 0x40008002 */
__IO uint8_t USB_DEV_AD; /*!< 0x40008003 */
__IO uint8_t USB_STATUS0; /*!< 0x40008004 */
__IO uint8_t USB_MIS_ST; /*!< 0x40008005 */
__IO uint8_t USB_INT_FG; /*!< 0x40008006 */
__IO uint8_t USB_INT_ST; /*!< 0x40008007 */
__IO uint8_t USB_RX_LEN; /*!< 0x40008008 */
__IO uint8_t Reserve1; /*!< 0x40008009 */
__IO uint8_t Reserve2; /*!< 0x4000800a */
__IO uint8_t Reserve3; /*!< 0x4000800b */
__IO uint8_t UEP4_1_MOD; /*!< 0x4000800c */
union {
__IO uint8_t UEP2_3_MOD; /*!< 0x4000800d */
__IO uint8_t UH_EP_MOD; /*!< 0x4000800d */
};
__IO uint8_t UEP567_MOD; /*!< 0x4000800e */
__IO uint8_t Reserve4; /*!< 0x4000800f */
__IO uint16_t UEP0_DMA; /*!< 0x40008010 */
__IO uint16_t Reserve5; /*!< 0x40008012 */
__IO uint16_t UEP1_DMA; /*!< 0x40008014 */
__IO uint16_t Reserve6; /*!< 0x40008016 */
union {
__IO uint16_t UEP2_DMA; /*!< 0x40008018 */
__IO uint16_t UH_RX_DMA; /*!< 0x40008018 */
};
__IO uint16_t Reserve7; /*!< 0x4000801a */
union {
__IO uint16_t UEP3_DMA; /*!< 0x4000801c */
__IO uint16_t UH_TX_DMA; /*!< 0x4000801c */
};
__IO uint16_t Reserve8; /*!< 0x4000801e */
__IO uint8_t UEP0_T_LEN; /*!< 0x40008020 */
__IO uint8_t Reserve9; /*!< 0x40008021 */
__IO uint8_t UEP0_CTRL; /*!< 0x40008022 */
__IO uint8_t Reserve10; /*!< 0x40008023 */
__IO uint8_t UEP1_T_LEN; /*!< 0x40008024 */
__IO uint8_t Reserve11; /*!< 0x40008025 */
union {
__IO uint8_t UEP1_CTRL; /*!< 0x40008026 */
__IO uint8_t UH_SETUP; /*!< 0x40008026 */
};
__IO uint8_t Reserve12; /*!< 0x40008027 */
union {
__IO uint8_t UEP2_T_LEN; /*!< 0x40008028 */
__IO uint8_t UH_EP_PID; /*!< 0x40008028 */
};
__IO uint8_t Reserve13; /*!< 0x40008029 */
union {
__IO uint8_t UEP2_CTRL; /*!< 0x4000802a */
__IO uint8_t UH_RX_CTRL; /*!< 0x4000802a */
};
__IO uint8_t Reserve14; /*!< 0x4000802b */
union {
__IO uint8_t UEP3_T_LEN; /*!< 0x4000802c */
__IO uint8_t UH_TX_LEN; /*!< 0x4000802c */
};
__IO uint8_t Reserve15; /*!< 0x4000802d */
union {
__IO uint8_t UEP3_CTRL; /*!< 0x4000802e */
__IO uint8_t UH_TX_CTRL; /*!< 0x4000802e */
};
__IO uint8_t Reserve16; /*!< 0x4000802f */
__IO uint8_t UEP4_T_LEN; /*!< 0x40008030 */
__IO uint8_t Reserve17; /*!< 0x40008031 */
__IO uint8_t UEP4_CTRL; /*!< 0x40008032 */
__IO uint8_t Reserve18[33]; /*!< 0x40008033 */
__IO uint16_t UEP5_DMA; /*!< 0x40008054 */
__IO uint16_t Reserve19; /*!< 0x40008056 */
__IO uint16_t UEP6_DMA; /*!< 0x40008058 */
__IO uint16_t Reserve20; /*!< 0x4000805a */
__IO uint16_t UEP7_DMA; /*!< 0x4000805c */
__IO uint8_t Reserve21[6]; /*!< 0x4000805e */
__IO uint8_t UEP5_T_LEN; /*!< 0x40008064 */
__IO uint8_t Reserve22; /*!< 0x40008065 */
__IO uint8_t UEP5_CTRL; /*!< 0x40008066 */
__IO uint8_t Reserve23; /*!< 0x40008067 */
__IO uint8_t UEP6_T_LEN; /*!< 0x40008068 */
__IO uint8_t Reserve24; /*!< 0x40008069 */
__IO uint8_t UEP6_CTRL; /*!< 0x4000806a */
__IO uint8_t Reserve25; /*!< 0x4000806b */
__IO uint8_t UEP7_T_LEN; /*!< 0x4000806c */
__IO uint8_t Reserve26; /*!< 0x4000806d */
__IO uint8_t UEP7_CTRL; /*!< 0x4000806e */
} USB_FS_TypeDef;
#ifdef __cplusplus
}
#endif

View File

@ -27,7 +27,7 @@ CONFIG_USBDEV_EP_NUM 必须为4 或者 6并删除 usb_dc_dwc2.c 中 while(1){
- GD32F30X_CL
- GD32F405、GD32F407
- GD32F450
- GD32F350、GD32F450
## HC32
@ -35,7 +35,7 @@ CONFIG_USBDEV_EP_NUM 必须为4 或者 6并删除 usb_dc_dwc2.c 中 while(1){
## Espressif
- ESP32S2、ESP32S3
- ESP32S2、ESP32S3、ESP32P4
## Sophgo

View File

@ -9,6 +9,7 @@
#include "esp_private/usb_phy.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "usbd_core.h"
#include "usbh_core.h"

View File

@ -194,8 +194,6 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
USB_OTG_GLB->GCCFG = (1 << 23);
usb_hsphy_init(25000000U);
return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/
#elif __has_include("stm32h7rsxx.h")
return (1 << 21);
#else
return 0;
#endif

View File

@ -41,6 +41,7 @@ struct dwc2_chan {
uint32_t xferlen;
uint8_t chidx;
bool inuse;
bool dir_in;
usb_osal_sem_t waitsem;
struct usbh_urb *urb;
uint32_t iso_frame_idx;
@ -256,16 +257,26 @@ static void dwc2_chan_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr
}
/* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/
static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint8_t ep_addr, uint8_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid)
{
__IO uint32_t tmpreg;
uint8_t is_oddframe;
struct dwc2_chan *chan;
chan = &g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[ch_num];
/* Initialize the HCTSIZn register */
USB_OTG_HC(ch_num)->HCTSIZ = (size & USB_OTG_HCTSIZ_XFRSIZ) |
(((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
(((uint32_t)pid << 29) & USB_OTG_HCTSIZ_DPID);
if (!(ep_addr & 0x80)) {
chan->dir_in = false;
usb_dcache_clean((uintptr_t)buf, USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE));
} else {
chan->dir_in = true;
}
/* xfer_buff MUST be 32-bits aligned */
USB_OTG_HC(ch_num)->HCDMA = (uint32_t)buf;
@ -400,17 +411,17 @@ static void dwc2_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct us
{
chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
dwc2_chan_transfer(bus, chidx, 0x00, (uint8_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
} else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */
{
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_transfer(bus, chidx, 0x80, buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */
{
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
dwc2_chan_transfer(bus, chidx, 0x00, buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */
{
chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
@ -432,9 +443,10 @@ static void dwc2_bulk_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct
chan->num_packets = dwc2_calculate_packet_num(buflen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle == 0 ? HC_PID_DATA0 : HC_PID_DATA1);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, buffer, chan->xferlen, chan->num_packets, urb->data_toggle == 0 ? HC_PID_DATA0 : HC_PID_DATA1);
}
#if 0
static void dwc2_iso_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet)
{
struct dwc2_chan *chan;
@ -443,8 +455,9 @@ static void dwc2_iso_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_u
chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0);
}
#endif
__WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
{
@ -754,6 +767,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
return -USB_ERR_INVAL;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if (((uintptr_t)urb->setup % CONFIG_USB_ALIGN_SIZE) || ((uintptr_t)urb->transfer_buffer % CONFIG_USB_ALIGN_SIZE)) {
USB_LOG_ERR("urb buffer is not align with %d\r\n", CONFIG_USB_ALIGN_SIZE);
while (1) {
}
}
#endif
bus = urb->hport->bus;
if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !urb->hport->connected) {
@ -907,7 +927,7 @@ static void dwc2_inchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
urb->errorcode = 0;
uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */
uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
//uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19); /* how many packets have used */
urb->actual_length += count;
@ -919,6 +939,10 @@ static void dwc2_inchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
urb->data_toggle = 1;
}
if (chan->dir_in) {
usb_dcache_invalidate((uintptr_t)urb->transfer_buffer, USB_ALIGN_UP(count, CONFIG_USB_ALIGN_SIZE));
}
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
if (chan->ep0_state == DWC2_EP0_STATE_INDATA) {
chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS;

View File

@ -12,7 +12,7 @@
### AllwinnerTech
- F133
- F133/T113
### Nuvoton

View File

@ -0,0 +1,219 @@
/*
* Copyright (c) 2025, YC113
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usb_hc_ehci.h"
#include "usb_hc_ohci.h"
#include "interrupt.h"
#include "drv_reg_base.h"
#include "drv_clock.h"
#if !defined(CONFIG_USB_EHCI_WITH_OHCI)
#error "t113 must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device"
#endif
#if CONFIG_USBHOST_MAX_BUS != 2
#error "t113 has 2 usb host controller"
#endif
#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400
#error "t113 CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400"
#endif
#if defined(CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE)
#error "t113 usb ehci register need reserved"
#endif
#if !defined(CONFIG_USB_EHCI_CONFIGFLAG)
#error "t113 usb ehci has configflag register"
#endif
#if defined(CONFIG_USB_EHCI_ISO)
#error "t113 usb ehci no iso register"
#endif
void usb_select_phyTohci(void)
{
*(volatile rt_uint32_t *)(USB0_OTG_BASE_ADDR + 0x420) &= ~(1 << 0);
}
void usb_gate_open(rt_uint8_t busid)
{
rt_uint32_t addr;
/* otg bus reset and gate open */
if (busid == 0)
usb_select_phyTohci();
/* reset phy */
addr = (rt_uint32_t)&CCU->usb0_clk + busid * 4;
*(volatile rt_uint32_t *)addr &= ~(1 << 30);
sdelay(10);
*(volatile rt_uint32_t *)addr |= 1 << 30;
sdelay(10);
/* ehci bus reset */
CCU->usb_bgr &= ~((1 << 20) << busid);
sdelay(10);
CCU->usb_bgr |= (1 << 20) << busid;
sdelay(10);
/* ehci gate open */
CCU->usb_bgr |= (1 << 4) << busid;
/* ohci bus reset */
CCU->usb_bgr &= ~((1 << 16) << busid);
sdelay(10);
CCU->usb_bgr |= (1 << 16) << busid;
sdelay(10);
/* ohci gate open */
CCU->usb_bgr |= 1 << busid;
sdelay(10);
/* clock enable */
*(volatile rt_uint32_t *)addr &= ~(3 << 24);
*(volatile rt_uint32_t *)addr |= (1 << 31) | (1 << 24);
USB_LOG_DBG("usb%d gate : %X, clock : %X\n", busid, CCU->usb_bgr, *(volatile rt_uint32_t *)addr);
}
void usb_clean_siddp(struct usbh_bus *bus)
{
*(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810) &= ~(1 << 3);
}
static void usb_new_phyx_tp_write(struct usbh_bus *bus, int addr, int data, int len)
{
rt_uint32_t base = bus->hcd.reg_base;
for (int i = 0; i < len; i++) {
*(volatile rt_uint8_t *)(base + 0x810) |= 1 << 1;
*(volatile rt_uint8_t *)(base + 0x810 + 1) = addr + i;
*(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 0);
*(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 7);
*(volatile rt_uint8_t *)(base + 0x810) |= (data & 0x1) << 7;
*(volatile rt_uint8_t *)(base + 0x810) |= 1 << 0;
*(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 0);
*(volatile rt_uint8_t *)(base + 0x810) &= ~(1 << 1);
data >>= 1;
}
}
void usb_new_phy_init(struct usbh_bus *bus)
{
rt_int32_t value = 0;
rt_uint32_t efuse_val = 0x1E5080F;
usb_new_phyx_tp_write(bus, 0x1C, 0x0, 0x03);
/* vref mode */
usb_new_phyx_tp_write(bus, 0x60, 0x0, 0x01);
value = (efuse_val & 0x3C0000) >> 18;
usb_new_phyx_tp_write(bus, 0x44, value, 0x04);
value = (efuse_val & 0x1C00000) >> 22;
usb_new_phyx_tp_write(bus, 0x36, value, 0x03);
}
void usb_hci_set_passby(struct usbh_bus *bus)
{
/* AHB Master interface INCR16 enable */
/* AHB Master interface INCR8 enable */
/* AHB Master interface burst type INCR4 enable */
/* AHB Master interface INCRX align enable */
/* ULPI bypass enable */
*(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x800) |= (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 0);
}
void t113_ehci_isr(int vector, void *arg)
{
struct usbh_bus *bus = (struct usbh_bus *)arg;
USB_LOG_DBG("t113_ehci_isr");
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(bus->hcd.hcd_id);
}
void t113_ohci_isr(int vector, void *arg)
{
struct usbh_bus *bus = (struct usbh_bus *)arg;
USB_LOG_DBG("t113_ohci_isr");
extern void OHCI_IRQHandler(uint8_t busid);
OHCI_IRQHandler(bus->hcd.hcd_id);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
int vector;
RT_ASSERT(bus->busid <= 1);
usb_gate_open(bus->busid);
usb_clean_siddp(bus);
usb_hci_set_passby(bus);
/* register EHCI interrupt callback */
vector = T113_IRQ_USB0_EHCI + (bus->busid > 0 ? 3 : 0);
rt_hw_interrupt_install(vector, t113_ehci_isr, bus, RT_NULL);
rt_hw_interrupt_umask(vector);
/* register OHCI interrupt callback */
rt_hw_interrupt_install(vector + 1, t113_ohci_isr, bus, RT_NULL);
rt_hw_interrupt_umask(vector + 1);
USB_LOG_DBG("usb%d vector : %d, phy : %X\n", bus->busid, vector, *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810));
USB_LOG_DBG("usb%d hc low level init success\n", bus->busid);
}
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
{
/* Defined by individual manufacturers */
uint32_t regval;
regval = EHCI_HCOR->portsc[port - 1];
if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE)
return USB_SPEED_LOW;
if (regval & EHCI_PORTSC_PE)
return USB_SPEED_HIGH;
else
return USB_SPEED_FULL;
}
int __usbh_init(void)
{
#ifdef T113_USING_USB0_HOST
/* USB0 MSC test OK */
usbh_initialize(0, USB0_BASE_ADDR);
#endif
#ifdef T113_USING_USB1_HOST
/* USB1 MSC test OK */
usbh_initialize(1, USB1_BASE_ADDR);
#endif
return 0;
}
#ifdef PKG_CHERRYUSB_HOST
#include <rtthread.h>
#include <rtdevice.h>
INIT_ENV_EXPORT(__usbh_init);
#endif

View File

@ -76,10 +76,36 @@ static void ehci_qh_free(struct usbh_bus *bus, struct ehci_qh_hw *qh)
}
}
#ifdef CONFIG_USB_DCACHE_ENABLE
static inline void usb_ehci_qh_qtd_flush(struct ehci_qh_hw *qh)
{
struct ehci_qtd_hw *qtd;
qtd = EHCI_ADDR2QTD(qh->first_qtd);
while (qtd) {
usb_dcache_clean((uintptr_t)&qtd->hw, USB_ALIGN_UP(SIZEOF_EHCI_QTD, CONFIG_USB_EHCI_ALIGN_SIZE));
if (!qtd->dir_in) {
usb_dcache_clean(qtd->bufaddr, USB_ALIGN_UP(qtd->length, CONFIG_USB_ALIGN_SIZE));
}
qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
}
usb_dcache_clean((uintptr_t)&qh->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
}
#else
#define usb_ehci_qh_qtd_flush(qh)
#endif
static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
{
n->hw.hlp = head->hw.hlp;
usb_ehci_qh_qtd_flush(n);
head->hw.hlp = QH_HLP_QH(n);
usb_dcache_clean((uintptr_t)&head->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
}
static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
@ -92,6 +118,7 @@ static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
if (tmp) {
tmp->hw.hlp = n->hw.hlp;
usb_dcache_clean((uintptr_t)&tmp->hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
}
}
@ -254,7 +281,9 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl
qtd->hw.token = token;
ehci_qtd_bpl_fill(qtd, bufaddr, buflen);
ehci_qtd_bpl_fill(qtd, usb_phyaddr2ramaddr(bufaddr), buflen);
qtd->dir_in = ((token & QTD_TOKEN_PID_MASK) == QTD_TOKEN_PID_IN) ? true : false;
qtd->bufaddr = bufaddr;
qtd->length = buflen;
}
@ -591,6 +620,9 @@ static void ehci_qh_scan_qtds(struct usbh_bus *bus, struct ehci_qh_hw *qhead, st
qtd = EHCI_ADDR2QTD(qh->first_qtd);
while (qtd) {
if (qtd->dir_in) {
usb_dcache_invalidate(qtd->bufaddr, USB_ALIGN_UP(qtd->length - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT), CONFIG_USB_ALIGN_SIZE));
}
qtd->urb->actual_length += (qtd->length - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
qh->first_qtd = qtd->hw.next_qtd;
@ -611,6 +643,7 @@ static void ehci_check_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct
}
while (qtd) {
usb_dcache_invalidate((uintptr_t)&qtd->hw, USB_ALIGN_UP(SIZEOF_EHCI_QTD, CONFIG_USB_EHCI_ALIGN_SIZE));
token = qtd->hw.token;
if (token & QTD_TOKEN_STATUS_ERRORS) {
@ -766,6 +799,10 @@ int usb_hc_init(struct usbh_bus *bus)
g_framelist[bus->hcd.hcd_id][i] = QH_HLP_QH(&g_periodic_qh_head[bus->hcd.hcd_id]);
}
usb_dcache_clean((uintptr_t)&g_async_qh_head[bus->hcd.hcd_id].hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
usb_dcache_clean((uintptr_t)&g_periodic_qh_head[bus->hcd.hcd_id].hw, USB_ALIGN_UP(SIZEOF_EHCI_QH, CONFIG_USB_EHCI_ALIGN_SIZE));
usb_dcache_clean((uintptr_t)g_framelist[bus->hcd.hcd_id], sizeof(uint32_t) * CONFIG_USB_EHCI_FRAME_LIST_SIZE);
usb_hc_low_level_init(bus);
USB_LOG_INFO("EHCI HCIVERSION:0x%04x\r\n", (unsigned int)EHCI_HCCR->hciversion);
@ -1138,6 +1175,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
return -USB_ERR_INVAL;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if (((uintptr_t)urb->setup % CONFIG_USB_ALIGN_SIZE) || ((uintptr_t)urb->transfer_buffer % CONFIG_USB_ALIGN_SIZE)) {
USB_LOG_ERR("urb buffer is not align with %d\r\n", CONFIG_USB_ALIGN_SIZE);
while (1) {
}
}
#endif
bus = urb->hport->bus;
/* find active hubport in roothub */

View File

@ -30,14 +30,19 @@
#ifndef CONFIG_USB_EHCI_ISO_NUM
#define CONFIG_USB_EHCI_ISO_NUM 4
#endif
#ifndef CONFIG_USB_EHCI_ALIGN_SIZE
#define CONFIG_USB_EHCI_ALIGN_SIZE 64
#endif
extern uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port);
struct ehci_qtd_hw {
struct ehci_qtd hw;
struct usbh_urb *urb;
bool dir_in;
uintptr_t bufaddr;
uint32_t length;
} __attribute__((aligned(32)));
} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
struct ehci_qh_hw {
struct ehci_qh hw;
@ -46,7 +51,7 @@ struct ehci_qh_hw {
struct usbh_urb *urb;
usb_osal_sem_t waitsem;
uint8_t remove_in_iaad;
} __attribute__((aligned(32)));
} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
struct ehci_itd_hw {
struct ehci_itd hw;
@ -55,7 +60,8 @@ struct ehci_itd_hw {
uint8_t mf_unmask;
uint8_t mf_valid;
uint32_t pkt_idx[8];
} __attribute__((aligned(32)));
bool dir_in;
} __attribute__((aligned(CONFIG_USB_EHCI_ALIGN_SIZE)));
struct ehci_iso_hw
{

View File

@ -23,10 +23,7 @@
## GD32
- GD32F10X_MD、GD32F10X_HD、GD32F10X_XD
- GD32F30X_HD、GD32F30X_XD
- GD32F350
- GD32F407
- GD32F10X
## CH32

View File

@ -869,12 +869,7 @@ void handle_ep0(struct usbh_bus *bus)
break;
case USB_EP0_STATE_IN_DATA:
if (ep0_status & USB_CSRL0_RXRDY) {
size = urb->transfer_buffer_length;
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
}
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
size = HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET);
musb_read_packet(bus, 0, urb->transfer_buffer, size);
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_RXRDY;
urb->transfer_buffer += size;
@ -933,6 +928,7 @@ void USBH_IRQHandler(uint8_t busid)
uint8_t ep_idx;
uint8_t old_ep_idx;
struct usbh_bus *bus;
uint32_t size;
bus = &g_usbhost_bus[busid];
@ -1024,7 +1020,7 @@ void USBH_IRQHandler(uint8_t busid)
urb->errorcode = 0;
musb_urb_waitup(urb);
} else {
musb_write_packet(bus, ep_idx, urb->transfer_buffer, size);
musb_write_packet(bus, ep_idx, urb->transfer_buffer, MIN(urb->transfer_buffer_length, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)));
HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY;
}
}
@ -1056,11 +1052,7 @@ void USBH_IRQHandler(uint8_t busid)
urb->errorcode = -USB_ERR_STALL;
musb_urb_waitup(urb);
} else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {
uint32_t size = urb->transfer_buffer_length;
if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
}
size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET));
size = HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET);
musb_read_packet(bus, ep_idx, urb->transfer_buffer, size);

View File

@ -22,14 +22,18 @@
#ifndef CONFIG_USB_OHCI_TD_NUM
#define CONFIG_USB_OHCI_TD_NUM 3
#endif
#ifndef CONFIG_USB_OHCI_ALIGN_SIZE
#define CONFIG_USB_OHCI_ALIGN_SIZE 64
#endif
struct ohci_ed_hw;
struct ohci_td_hw {
struct ohci_gtd hw;
struct usbh_urb *urb;
bool dir_in;
uint32_t buf_start;
uint32_t length;
} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
} __attribute__((aligned(CONFIG_USB_OHCI_ALIGN_SIZE))); /* min is 16bytes, we use CONFIG_USB_OHCI_ALIGN_SIZE for cacheline */
struct ohci_ed_hw {
struct ohci_ed hw;
@ -37,7 +41,7 @@ struct ohci_ed_hw {
uint32_t td_count;
uint8_t ed_type;
usb_osal_sem_t waitsem;
} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
} __attribute__((aligned(CONFIG_USB_OHCI_ALIGN_SIZE))); /* min is 16bytes, we use CONFIG_USB_OHCI_ALIGN_SIZE for cacheline */
struct ohci_hcd {
bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM];

View File

@ -0,0 +1,5 @@
# Note
## Support Chip List
- RP2040/RP2350

View File

@ -0,0 +1,588 @@
/*
* Copyright (c) 2022, HaiMianBBao
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "hardware/resets.h"
#include "hardware/irq.h"
#include "hardware/structs/usb.h"
#if CHERRYUSB_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
#include "pico/fix/rp2040_usb_device_enumeration.h"
#endif
#define usb_hw_set hw_set_alias(usb_hw)
#define usb_hw_clear hw_clear_alias(usb_hw)
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 16
#endif
#ifndef FORCE_VBUS_DETECT
#define FORCE_VBUS_DETECT 1
#endif
/* Endpoint state */
struct rp2040_ep_state {
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_type; /* Endpoint type */
uint8_t ep_stalled; /* Endpoint stall flag */
uint8_t ep_enable; /* Endpoint enable */
uint8_t ep_addr; /* Endpoint address */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
volatile uint32_t *endpoint_control; /*!< Endpoint control register */
volatile uint32_t *buffer_control; /*!< Buffer control register */
uint8_t *data_buffer; /*!< Buffer pointer in usb dpram */
uint8_t next_pid; /*!< Toggle after each packet (unless replying to a SETUP) */
};
/* Driver state */
struct rp2040_udc {
volatile uint8_t dev_addr;
struct rp2040_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct rp2040_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
struct usb_setup_packet setup; /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
} g_rp2040_udc;
void rp2040_usbd_irq(void);
/**
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
*
* @param buf
* @return uint32_t
*/
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
{
return (uint32_t)buf ^ (uint32_t)usb_dpram;
}
/**
* @brief Set up the endpoint control register for an endpoint (if applicable. Not valid for EP0).
*
* @param ep
*/
void usb_setup_endpoint(const struct rp2040_ep_state *ep)
{
// EP0 doesn't have one so return if that is the case
if (!ep->endpoint_control) {
return;
}
// Get the data buffer as an offset of the USB controller's DPRAM
uint32_t dpram_offset = usb_buffer_offset(ep->data_buffer);
uint32_t reg = EP_CTRL_ENABLE_BITS |
EP_CTRL_INTERRUPT_PER_BUFFER |
(ep->ep_type << EP_CTRL_BUFFER_TYPE_LSB) |
dpram_offset;
*ep->endpoint_control = reg;
}
/**
* @brief Starts a transfer on a given endpoint.
*
* @param ep, the endpoint configuration.
* @param buf, the data buffer to send. Only applicable if the endpoint is TX
* @param len, the length of the data in buf (this example limits max len to one packet - 64 bytes)
*/
static void usb_start_transfer(struct rp2040_ep_state *ep, uint8_t *buf, uint16_t len)
{
/*!< Prepare buffer control register value */
uint32_t val = len | USB_BUF_CTRL_AVAIL;
if (len < ep->ep_mps) {
val |= USB_BUF_CTRL_LAST;
}
if (USB_EP_DIR_IS_IN(ep->ep_addr)) {
/*!< Need to copy the data from the user buffer to the usb memory */
if (buf != NULL) {
memcpy((void *)ep->data_buffer, (void *)buf, len);
}
/*!< Mark as full */
val |= USB_BUF_CTRL_FULL;
}
/*!< Set pid and flip for next transfer */
val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
ep->next_pid ^= 1u;
*ep->buffer_control = val;
}
int usb_dc_init(uint8_t busid)
{
uint8_t *next_buffer_ptr;
memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
g_rp2040_udc.in_ep[0].endpoint_control = NULL;
g_rp2040_udc.in_ep[0].data_buffer = &usb_dpram->ep0_buf_a[0];
g_rp2040_udc.out_ep[0].endpoint_control = NULL;
g_rp2040_udc.out_ep[0].data_buffer = &usb_dpram->ep0_buf_a[0];
for (uint32_t i = 0; i < CONFIG_USBDEV_EP_NUM; i++) {
g_rp2040_udc.in_ep[i].buffer_control = &usb_dpram->ep_buf_ctrl[i].in;
g_rp2040_udc.out_ep[i].buffer_control = &usb_dpram->ep_buf_ctrl[i].out;
if (i != 0) {
g_rp2040_udc.in_ep[i].endpoint_control = &usb_dpram->ep_ctrl[i - 1].in;
g_rp2040_udc.out_ep[i].endpoint_control = &usb_dpram->ep_ctrl[i - 1].out;
}
}
next_buffer_ptr = &usb_dpram->epx_data[0];
for (uint32_t i = 1; i < CONFIG_USBDEV_EP_NUM; i++) {
g_rp2040_udc.in_ep[i].data_buffer = next_buffer_ptr;
if (i == 1) {
next_buffer_ptr += 1024; /* for iso video */
} else {
next_buffer_ptr += 64;
}
g_rp2040_udc.out_ep[i].data_buffer = next_buffer_ptr;
next_buffer_ptr += 64;
}
// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbd_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
// Reset usb controller
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
/*!< Clear any previous state just in case */
memset(usb_hw, 0, sizeof(*usb_hw));
memset(usb_dpram, 0, sizeof(*usb_dpram));
/*!< Mux the controller to the onboard usb phy */
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
#if FORCE_VBUS_DETECT
// Force VBUS detect so the device thinks it is plugged into a host
usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
#endif
// Enable the USB controller in device mode.
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
// Enable an interrupt per EP0 transaction
usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; // <2>
// Enable interrupts for when a buffer is done, when the bus is reset,
// and when a setup packet is received
usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
(FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
// Enable USB interrupt at processor
irq_set_enabled(USBCTRL_IRQ, true);
usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
irq_set_enabled(USBCTRL_IRQ, false);
// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
return 0;
}
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
g_rp2040_udc.dev_addr = addr;
return 0;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}
uint8_t usbd_get_port_speed(uint8_t busid)
{
return USB_SPEED_FULL;
}
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
g_rp2040_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_rp2040_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_rp2040_udc.out_ep[ep_idx].ep_addr = ep->bEndpointAddress;
g_rp2040_udc.out_ep[ep_idx].ep_enable = true;
/*!< Clear control reg */
*(g_rp2040_udc.out_ep[ep_idx].buffer_control) = 0;
usb_setup_endpoint(&g_rp2040_udc.out_ep[ep_idx]);
} else {
g_rp2040_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_rp2040_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_rp2040_udc.in_ep[ep_idx].ep_addr = ep->bEndpointAddress;
g_rp2040_udc.in_ep[ep_idx].ep_enable = true;
/*!< Clear control reg */
*(g_rp2040_udc.in_ep[ep_idx].buffer_control) = 0;
usb_setup_endpoint(&g_rp2040_udc.in_ep[ep_idx]);
}
return 0;
}
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
if (USB_EP_DIR_IS_IN(ep)) {
} else if (USB_EP_DIR_IS_OUT(ep)) {
}
return 0;
}
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
if (USB_EP_GET_IDX(ep) == 0) {
/**
* A stall on EP0 has to be armed so it can be cleared on the next setup packet
*/
usb_hw_set->ep_stall_arm = (USB_EP_DIR_IS_IN(ep)) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
}
if (USB_EP_DIR_IS_OUT(ep)) {
*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
} else {
*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = USB_BUF_CTRL_STALL;
}
return 0;
}
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (ep_idx != 0) {
if (USB_EP_DIR_IS_OUT(ep)) {
g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) = ~USB_BUF_CTRL_STALL;
} else {
g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].next_pid = 0;
*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) = ~USB_BUF_CTRL_STALL;
}
}
return 0;
}
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
if (USB_EP_DIR_IS_OUT(ep)) {
if (*(g_rp2040_udc.out_ep[USB_EP_GET_IDX(ep)].buffer_control) & USB_BUF_CTRL_STALL) {
*stalled = 1;
} else {
*stalled = 0;
}
} else {
if (*(g_rp2040_udc.in_ep[USB_EP_GET_IDX(ep)].buffer_control) & USB_BUF_CTRL_STALL) {
*stalled = 1;
} else {
*stalled = 0;
}
}
return 0;
}
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!g_rp2040_udc.in_ep[ep_idx].ep_enable) {
return -2;
}
g_rp2040_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_rp2040_udc.in_ep[ep_idx].xfer_len = data_len;
g_rp2040_udc.in_ep[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], NULL, 0);
} else {
data_len = MIN(data_len, g_rp2040_udc.in_ep[ep_idx].ep_mps);
usb_start_transfer(&g_rp2040_udc.in_ep[ep_idx], g_rp2040_udc.in_ep[ep_idx].xfer_buf, data_len);
}
return 0;
}
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
if (!g_rp2040_udc.out_ep[ep_idx].ep_enable) {
return -2;
}
g_rp2040_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_rp2040_udc.out_ep[ep_idx].xfer_len = data_len;
g_rp2040_udc.out_ep[ep_idx].actual_xfer_len = 0;
if (data_len == 0) {
usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], NULL, 0);
} else {
/*!< Not zlp */
data_len = MIN(data_len, g_rp2040_udc.out_ep[ep_idx].ep_mps);
usb_start_transfer(&g_rp2040_udc.out_ep[ep_idx], g_rp2040_udc.out_ep[ep_idx].xfer_buf, data_len);
}
return 0;
}
/**
* @brief Notify an endpoint that a transfer has completed.
*
* @param ep, the endpoint to notify.
*/
static void usb_handle_ep_buff_done(struct rp2040_ep_state *ep)
{
uint32_t buffer_control = *ep->buffer_control;
/*!< Get the transfer length for this endpoint */
uint16_t read_count = buffer_control & USB_BUF_CTRL_LEN_MASK;
/*!< Call that endpoints buffer done handler */
if (ep->ep_addr == 0x80) {
/*!< EP0 In */
/**
* Determine the current setup direction
*/
switch (g_rp2040_udc.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
case 1:
/*!< Get */
if (g_rp2040_udc.in_ep[0].xfer_len > g_rp2040_udc.in_ep[0].ep_mps) {
g_rp2040_udc.in_ep[0].xfer_len -= g_rp2040_udc.in_ep[0].ep_mps;
g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].ep_mps;
usbd_event_ep_in_complete_handler(0, 0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
} else {
g_rp2040_udc.in_ep[0].actual_xfer_len += g_rp2040_udc.in_ep[0].xfer_len;
g_rp2040_udc.in_ep[0].xfer_len = 0;
/**
* EP0 In complete and host will send a out token to get 0 length packet
* In the next usbd_event_ep_in_complete_handler, stack will start read 0 length packet
* and host must send data1 packet.We resest the ep0 next_pid = 1 in setup interrupt head.
*/
usbd_event_ep_in_complete_handler(0, 0 | 0x80, g_rp2040_udc.in_ep[0].actual_xfer_len);
}
break;
case 0:
/*!< Set */
if (g_rp2040_udc.dev_addr > 0) {
usb_hw->dev_addr_ctrl = g_rp2040_udc.dev_addr;
g_rp2040_udc.dev_addr = 0;
} else {
/*!< Normal status stage // Setup out...out in */
/**
* Perpar for next setup
*/
}
break;
}
} else if (ep->ep_addr == 0x00) {
/*!< EP0 Out */
memcpy(g_rp2040_udc.out_ep[0].xfer_buf, g_rp2040_udc.out_ep[0].data_buffer, read_count);
if (read_count == 0) {
/*!< Normal status stage // Setup in...in out */
/**
* Perpar for next setup
*/
}
g_rp2040_udc.out_ep[0].actual_xfer_len += read_count;
g_rp2040_udc.out_ep[0].xfer_len -= read_count;
usbd_event_ep_out_complete_handler(0, 0x00, g_rp2040_udc.out_ep[0].actual_xfer_len);
} else {
/*!< Others ep */
uint16_t data_len = 0;
if (USB_EP_DIR_IS_OUT(ep->ep_addr)) {
/*!< flip the pid */
memcpy(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].data_buffer, read_count);
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_buf += read_count;
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += read_count;
g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len -= read_count;
if (read_count < g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps || g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len == 0) {
/*!< Out complete */
usbd_event_ep_out_complete_handler(0, ep->ep_addr, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
} else {
/*!< Need read again */
data_len = MIN(g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f].ep_mps);
usb_start_transfer(&g_rp2040_udc.out_ep[(ep->ep_addr) & 0x0f], NULL, data_len);
}
} else {
if (g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len > g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps) {
/*!< Need tx again */
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len -= g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps;
data_len = MIN(g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].ep_mps);
usb_start_transfer(&g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f], g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_buf, data_len);
} else {
/*!< In complete */
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len += g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len;
g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].xfer_len = 0;
usbd_event_ep_in_complete_handler(0, ep->ep_addr, g_rp2040_udc.in_ep[(ep->ep_addr) & 0x0f].actual_xfer_len);
}
}
}
}
/**
* @brief Find the endpoint configuration for a specified endpoint number and
* direction and notify it that a transfer has completed.
*
* @param ep_num
* @param in
*/
static void usb_handle_buff_done(uint8_t ep_num, bool in)
{
uint8_t ep_addr = ep_num | (in ? USB_EP_DIR_IN : 0);
if (USB_EP_DIR_IS_OUT(ep_addr)) {
usb_handle_ep_buff_done(&g_rp2040_udc.out_ep[ep_num]);
} else {
usb_handle_ep_buff_done(&g_rp2040_udc.in_ep[ep_num]);
}
}
/**
* @brief Handle a "buffer status" irq. This means that one or more
* buffers have been sent / received. Notify each endpoint where this
* is the case.
*/
static void usb_handle_buff_status(void)
{
uint32_t remaining_buffers = usb_hw->buf_status;
uint32_t bit = 1u;
for (uint8_t i = 0; remaining_buffers && i < USB_NUM_ENDPOINTS * 2; i++) {
if (remaining_buffers & bit) {
/*!< clear this in advance */
usb_hw_clear->buf_status = bit;
/*!< IN transfer for even i, OUT transfer for odd i */
usb_handle_buff_done(i >> 1u, !(i & 1u));
remaining_buffers &= ~bit;
}
bit <<= 1u;
}
}
void USBD_IRQHandler(uint8_t busid)
{
uint32_t const status = usb_hw->ints;
uint32_t handled = 0;
if (status & USB_INTS_BUFF_STATUS_BITS) {
handled |= USB_INTS_BUFF_STATUS_BITS;
usb_handle_buff_status();
}
if (status & USB_INTS_SETUP_REQ_BITS) {
handled |= USB_INTS_SETUP_REQ_BITS;
memcpy((uint8_t *)&g_rp2040_udc.setup, (uint8_t const *)&usb_dpram->setup_packet, 8);
/**
* reset pid to both 1 (data and ack)
*/
g_rp2040_udc.in_ep[0].next_pid = 1;
g_rp2040_udc.out_ep[0].next_pid = 1;
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_rp2040_udc.setup);
usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
}
#if FORCE_VBUS_DETECT == 0
/**
* Since we force VBUS detect On, device will always think it is connected and
* couldn't distinguish between disconnect and suspend
*/
if (status & USB_INTS_DEV_CONN_DIS_BITS) {
handled |= USB_INTS_DEV_CONN_DIS_BITS;
if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) {
/*!< Connected: nothing to do */
usbd_event_connect_handler(0);
} else {
/*!< Disconnected */
usbd_event_disconnect_handler(0);
}
usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
}
#endif
/**
* SE0 for 2.5 us or more (will last at least 10ms)
*/
if (status & USB_INTS_BUS_RESET_BITS) {
handled |= USB_INTS_BUS_RESET_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
usb_hw->dev_addr_ctrl = 0;
for (uint8_t i = 0; i < CONFIG_USBDEV_EP_NUM - 1; i++) {
/*!< Start at ep1 */
usb_dpram->ep_ctrl[i].in = 0;
usb_dpram->ep_ctrl[i].out = 0;
}
usbd_event_reset_handler(0);
#if CHERRYUSB_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
/**
* Only run enumeration walk-around if pull up is enabled
*/
if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS)
rp2040_usb_device_enumeration_fix();
#endif
}
/**
* Note from pico datasheet 4.1.2.6.4 (v1.2)
* If you enable the suspend interrupt, it is likely you will see a suspend interrupt when
* the device is first connected but the bus is idle. The bus can be idle for a few ms before
* the host begins sending start of frame packets. You will also see a suspend interrupt
* when the device is disconnected if you do not have a VBUS detect circuit connected. This is
* because without VBUS detection, it is impossible to tell the difference between
* being disconnected and suspended.
*/
if (status & USB_INTS_DEV_SUSPEND_BITS) {
handled |= USB_INTS_DEV_SUSPEND_BITS;
/*!< Suspend */
usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
usbd_event_suspend_handler(0);
}
if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) {
handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
/*!< Resume */
usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
usbd_event_resume_handler(0);
}
if (status ^ handled) {
USB_LOG_INFO("Unhandled IRQ 0x%x\n", (uint32_t)(status ^ handled));
}
}
void rp2040_usbd_irq(void)
{
USBD_IRQHandler(0);
}

View File

@ -0,0 +1,824 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
#include "hardware/resets.h"
#include "hardware/irq.h"
#include "hardware/structs/usb.h"
#define usb_hw_set hw_set_alias(usb_hw)
#define usb_hw_clear hw_clear_alias(usb_hw)
#define SIE_CTRL_COMMON (USB_SIE_CTRL_SOF_EN_BITS | \
USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | \
USB_SIE_CTRL_PULLDOWN_EN_BITS | \
USB_SIE_CTRL_EP0_INT_1BUF_BITS)
typedef enum {
USB_EP0_STATE_SETUP = 0x0, /**< SETUP DATA */
USB_EP0_STATE_IN_DATA, /**< IN DATA */
USB_EP0_STATE_IN_STATUS, /**< IN status*/
USB_EP0_STATE_OUT_DATA, /**< OUT DATA */
USB_EP0_STATE_OUT_STATUS, /**< OUT status */
} ep0_state_t;
struct rp2040_pipe {
uint8_t chidx;
bool inuse;
volatile uint8_t ep0_state;
volatile uint32_t *endpoint_control; /*!< Endpoint control register */
volatile uint32_t *buffer_control; /*!< Buffer control register */
uint8_t *data_buffer; /*!< Buffer pointer in usb dpram */
uint32_t buffer_size; /*!< Buffer size */
usb_osal_sem_t waitsem;
struct usbh_urb *urb;
};
struct rp2040_hcd {
volatile bool port_csc;
volatile bool port_pec;
volatile bool port_pe;
usb_osal_mutex_t ep0_mutex;
struct rp2040_pipe pipe_pool[1 + CONFIG_USBHOST_PIPE_NUM];
} g_rp2040_hcd[CONFIG_USBHOST_MAX_BUS];
void rp2040_usbh_irq(void);
static int rp2040_pipe_alloc(struct usbh_bus *bus)
{
size_t flags;
int chidx;
flags = usb_osal_enter_critical_section();
for (chidx = 1; chidx <= CONFIG_USBHOST_PIPE_NUM; chidx++) {
if (!g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse) {
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx].inuse = true;
usb_osal_leave_critical_section(flags);
return chidx;
}
}
usb_osal_leave_critical_section(flags);
return -1;
}
static void rp2040_pipe_free(struct rp2040_pipe *pipe)
{
size_t flags;
flags = usb_osal_enter_critical_section();
pipe->inuse = false;
usb_osal_leave_critical_section(flags);
}
/**
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
*
* @param buf
* @return uint32_t
*/
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
{
return (uint32_t)buf ^ (uint32_t)usbh_dpram;
}
static inline uint8_t usbh_get_port_speed(void)
{
return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB;
}
static inline void rp2040_init_endpoint(struct usbh_bus *bus,
uint8_t chidx,
uint8_t dev_addr,
uint8_t ep_addr,
uint8_t ep_type,
uint8_t ep_interval,
uint8_t speed)
{
struct rp2040_pipe *pipe;
uint32_t regval;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
// Get the data buffer as an offset of the USB controller's DPRAM
uint32_t dpram_offset = usb_buffer_offset(pipe->data_buffer);
regval = EP_CTRL_ENABLE_BITS |
EP_CTRL_INTERRUPT_PER_BUFFER |
(ep_type << EP_CTRL_BUFFER_TYPE_LSB) |
dpram_offset;
if (ep_interval) {
regval |= (uint32_t)((ep_interval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
}
*pipe->endpoint_control = regval;
if (chidx != 0) {
regval = (uint32_t)(dev_addr | ((ep_addr & 0x0f) << USB_ADDR_ENDP1_ENDPOINT_LSB));
if (!(ep_addr & 0x80)) {
regval |= USB_ADDR_ENDP1_INTEP_DIR_BITS;
}
// ls device plugged to hub
if ((usbh_get_port_speed() == USB_SPEED_FULL) && (speed == USB_SPEED_LOW)) {
regval |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS;
}
usb_hw->int_ep_addr_ctrl[(chidx - 1)] = regval;
// Finally, enable interrupt that endpoint
usb_hw_set->int_ep_ctrl = 1 << chidx;
} else {
usb_hw->dev_addr_ctrl = dev_addr;
}
}
static inline uint32_t usb_buf_ctrl_fill(struct usbh_bus *bus, uint8_t chidx, uint8_t ep_addr, uint8_t buf_id)
{
struct rp2040_pipe *pipe;
struct usbh_urb *urb;
uint32_t len;
uint32_t buf_ctrl;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
urb = pipe->urb;
len = MIN(urb->transfer_buffer_length, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize));
urb->transfer_buffer_length -= len;
buf_ctrl = len | USB_BUF_CTRL_AVAIL;
buf_ctrl |= urb->data_toggle ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
if (USB_EP_DIR_IS_OUT(ep_addr)) {
/*!< Need to copy the data from the user buffer to the usb memory */
if (urb->transfer_buffer != NULL) {
memcpy((void *)pipe->data_buffer + buf_id * 64, (void *)urb->transfer_buffer, len);
urb->transfer_buffer += len;
}
/*!< Mark as full */
buf_ctrl |= USB_BUF_CTRL_FULL;
}
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if (urb->transfer_buffer_length == 0) {
buf_ctrl |= USB_BUF_CTRL_LAST;
}
} else {
//TODO: handle isochronous transfer
}
if (buf_id)
buf_ctrl = buf_ctrl << 16;
return buf_ctrl;
}
/**
* @brief Starts a transfer on a given endpoint.
*
* @param ep, the endpoint configuration.
* @param buf, the data buffer to send. Only applicable if the endpoint is TX
* @param len, the length of the data in buf (this example limits max len to one packet - 64 bytes)
*/
static void usb_start_transfer(struct usbh_bus *bus, uint8_t chidx, uint8_t ep_addr)
{
struct rp2040_pipe *pipe;
struct usbh_urb *urb;
uint32_t buf_ctrl;
uint32_t ep_ctrl;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
urb = pipe->urb;
ep_ctrl = *pipe->endpoint_control;
buf_ctrl = usb_buf_ctrl_fill(bus, chidx, ep_addr, 0);
if (urb->transfer_buffer_length && (ep_addr & 0x0f) == 0x00) {
urb->data_toggle ^= 1;
buf_ctrl |= usb_buf_ctrl_fill(bus, chidx, ep_addr, 1);
// Set endpoint control double buffered bit if needed
ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER;
ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER;
} else {
// Single buffered since 1 is enough
ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
}
*pipe->endpoint_control = ep_ctrl;
*pipe->buffer_control = buf_ctrl;
}
static inline void rp2040_control_transfer_start(bool dir_in, bool isetup, uint8_t speed)
{
uint32_t regval;
regval = SIE_CTRL_COMMON | USB_SIE_CTRL_START_TRANS_BITS;
if ((usbh_get_port_speed() == USB_SPEED_FULL) && (speed == USB_SPEED_LOW)) {
regval |= USB_SIE_CTRL_PREAMBLE_EN_BITS;
}
if (isetup) {
regval |= USB_SIE_CTRL_SEND_SETUP_BITS;
} else {
if (dir_in) {
regval |= USB_SIE_CTRL_RECEIVE_DATA_BITS;
} else {
regval |= USB_SIE_CTRL_SEND_DATA_BITS;
}
}
usb_hw->sie_ctrl = regval & ~USB_SIE_CTRL_START_TRANS_BITS;
busy_wait_at_least_cycles(12);
usb_hw->sie_ctrl = regval;
}
static void rp2040_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
{
struct rp2040_pipe *pipe;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
if (pipe->ep0_state == USB_EP0_STATE_SETUP) /* fill setup */
{
pipe->urb->data_toggle = 1;
memcpy((uint8_t *)usbh_dpram->setup_packet, (uint8_t *)setup, 8);
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
rp2040_control_transfer_start(false, true, urb->hport->speed);
} else if (pipe->ep0_state == USB_EP0_STATE_IN_DATA) /* fill in data */
{
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
usb_start_transfer(bus, chidx, 0x80);
rp2040_control_transfer_start(true, false, urb->hport->speed);
} else if (pipe->ep0_state == USB_EP0_STATE_OUT_DATA) /* fill out data */
{
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
usb_start_transfer(bus, chidx, 0x00);
rp2040_control_transfer_start(false, false, urb->hport->speed);
} else if (pipe->ep0_state == USB_EP0_STATE_IN_STATUS) /* fill in status */
{
urb->data_toggle = 1;
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
usb_start_transfer(bus, chidx, 0x80);
rp2040_control_transfer_start(true, false, urb->hport->speed);
} else if (pipe->ep0_state == USB_EP0_STATE_OUT_STATUS) /* fill out status */
{
urb->data_toggle = 1;
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, 0, urb->hport->speed);
usb_start_transfer(bus, chidx, 0x00);
rp2040_control_transfer_start(false, false, urb->hport->speed);
}
}
static void rp2040_bulk_int_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
{
rp2040_init_endpoint(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), urb->ep->bInterval, urb->hport->speed);
usb_start_transfer(bus, chidx, urb->ep->bEndpointAddress);
}
int usb_hc_init(struct usbh_bus *bus)
{
uint8_t *next_buffer_ptr;
memset(&g_rp2040_hcd[bus->hcd.hcd_id], 0, sizeof(struct rp2040_hcd));
for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem = usb_osal_sem_create(0);
if (g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem == NULL) {
USB_LOG_ERR("Failed to create waitsem\r\n");
return -USB_ERR_NOMEM;
}
}
g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex = usb_osal_mutex_create();
if (g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex == NULL) {
USB_LOG_ERR("Failed to create ep0_mutex\r\n");
return -USB_ERR_NOMEM;
}
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].endpoint_control = &usbh_dpram->epx_ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_control = &usbh_dpram->epx_buf_ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].data_buffer = &usbh_dpram->epx_data[0];
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_size = (64 * 2);
next_buffer_ptr = &usb_dpram->epx_data[64 * 2];
for (uint8_t i = 1; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].chidx = i;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].endpoint_control = &usbh_dpram->int_ep_ctrl[i - 1].ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_control = &usbh_dpram->int_ep_buffer_ctrl[i - 1].ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].data_buffer = next_buffer_ptr;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_size = (64 * 2);
next_buffer_ptr += (64 * 2);
}
// Reset usb controller
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbh_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
/*!< Clear any previous state just in case */
memset(usb_hw, 0, sizeof(*usb_hw));
memset(usbh_dpram, 0, sizeof(*usbh_dpram));
/*!< Mux the controller to the onboard usb phy */
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
// Force VBUS detect so the device thinks it is plugged into a host
usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
// Enable the USB controller in device mode.
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;
usb_hw->sie_ctrl = SIE_CTRL_COMMON;
// Enable USB interrupt at processor
irq_set_enabled(USBCTRL_IRQ, true);
usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
USB_INTE_HOST_CONN_DIS_BITS |
USB_INTE_STALL_BITS |
USB_INTE_TRANS_COMPLETE_BITS |
USB_INTE_ERROR_RX_TIMEOUT_BITS |
USB_INTE_ERROR_DATA_SEQ_BITS;
return 0;
}
int usb_hc_deinit(struct usbh_bus *bus)
{
// Enable USB interrupt at processor
irq_set_enabled(USBCTRL_IRQ, false);
// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
usb_osal_sem_delete(g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem);
}
usb_osal_mutex_delete(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
return 0;
}
uint16_t usbh_get_frame_number(struct usbh_bus *bus)
{
return usb_hw->sof_rd;
}
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
{
uint8_t nports;
uint8_t port;
uint32_t status;
nports = CONFIG_USBHOST_MAX_RHPORTS;
port = setup->wIndex;
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_SET_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_GET_DESCRIPTOR:
break;
case HUB_REQUEST_GET_STATUS:
memset(buf, 0, 4);
break;
default:
break;
}
} else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
switch (setup->wValue) {
case HUB_PORT_FEATURE_ENABLE:
break;
case HUB_PORT_FEATURE_SUSPEND:
case HUB_PORT_FEATURE_C_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_C_CONNECTION:
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 0;
break;
case HUB_PORT_FEATURE_C_ENABLE:
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 0;
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
break;
case HUB_PORT_FEATURE_C_RESET:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_SET_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
switch (setup->wValue) {
case HUB_PORT_FEATURE_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_RESET:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_GET_STATUS:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
status = 0;
if (g_rp2040_hcd[bus->hcd.hcd_id].port_csc) {
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
}
if (g_rp2040_hcd[bus->hcd.hcd_id].port_pec) {
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
}
if (g_rp2040_hcd[bus->hcd.hcd_id].port_pe) {
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
status |= (1 << HUB_PORT_FEATURE_ENABLE);
if (usbh_get_port_speed() == USB_SPEED_LOW) {
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
}
}
status |= (1 << HUB_PORT_FEATURE_POWER);
memcpy(buf, &status, 4);
break;
default:
break;
}
}
return 0;
}
int usbh_submit_urb(struct usbh_urb *urb)
{
struct rp2040_pipe *pipe;
struct usbh_bus *bus;
int chidx;
size_t flags;
int ret = 0;
if (!urb || !urb->hport || !urb->ep || !urb->hport->bus) {
return -USB_ERR_INVAL;
}
if (!urb->hport->connected || !(usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS)) {
return -USB_ERR_NOTCONN;
}
if (urb->errorcode == -USB_ERR_BUSY) {
return -USB_ERR_BUSY;
}
bus = urb->hport->bus;
if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) {
chidx = 0;
/* all the control transfers use the only one ep0 register, we need to lock */
usb_osal_mutex_take(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
} else {
chidx = rp2040_pipe_alloc(bus);
if (chidx == -1) {
return -USB_ERR_NOMEM;
}
}
flags = usb_osal_enter_critical_section();
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[chidx];
pipe->chidx = chidx;
pipe->urb = urb;
urb->hcpriv = pipe;
urb->errorcode = -USB_ERR_BUSY;
urb->actual_length = 0;
usb_osal_leave_critical_section(flags);
switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) {
case USB_ENDPOINT_TYPE_CONTROL:
pipe->ep0_state = USB_EP0_STATE_SETUP;
rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_BULK:
case USB_ENDPOINT_TYPE_INTERRUPT:
rp2040_bulk_int_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
break;
default:
break;
}
if (urb->timeout > 0) {
/* wait until timeout or sem give */
ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
if (ret < 0) {
goto errout_timeout;
}
urb->timeout = 0;
ret = urb->errorcode;
/* we can free pipe when waitsem is done */
rp2040_pipe_free(pipe);
if (chidx == 0) {
usb_osal_mutex_give(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
}
}
return ret;
errout_timeout:
if (chidx == 0) {
usb_osal_mutex_give(g_rp2040_hcd[bus->hcd.hcd_id].ep0_mutex);
}
urb->timeout = 0;
usbh_kill_urb(urb);
return ret;
}
int usbh_kill_urb(struct usbh_urb *urb)
{
struct rp2040_pipe *pipe;
struct usbh_bus *bus;
size_t flags;
if (!urb || !urb->hcpriv || !urb->hport->bus) {
return -USB_ERR_INVAL;
}
bus = urb->hport->bus;
ARG_UNUSED(bus);
flags = usb_osal_enter_critical_section();
pipe = (struct rp2040_pipe *)urb->hcpriv;
urb->hcpriv = NULL;
urb->errorcode = -USB_ERR_SHUTDOWN;
pipe->urb = NULL;
usb_hw_clear->int_ep_ctrl = 1 << pipe->chidx;
usb_hw_clear->buf_status = 1 << (pipe->chidx * 2 + 0);
usb_hw_clear->buf_status = 1 << (pipe->chidx * 2 + 1);
*pipe->endpoint_control = 0;
*pipe->buffer_control = 0;
if (urb->timeout) {
usb_osal_sem_give(pipe->waitsem);
} else {
rp2040_pipe_free(pipe);
}
usb_osal_leave_critical_section(flags);
return 0;
}
static void rp2040_urb_waitup(struct usbh_urb *urb)
{
struct rp2040_pipe *pipe;
pipe = (struct rp2040_pipe *)urb->hcpriv;
pipe->urb = NULL;
urb->hcpriv = NULL;
if (urb->timeout) {
usb_osal_sem_give(pipe->waitsem);
} else {
rp2040_pipe_free(pipe);
}
if (urb->complete) {
if (urb->errorcode < 0) {
urb->complete(urb->arg, urb->errorcode);
} else {
urb->complete(urb->arg, urb->actual_length);
}
}
}
static void rp2040_handle_buffer_status(struct usbh_bus *bus)
{
struct rp2040_pipe *pipe;
struct usbh_urb *urb;
uint32_t remaining_buffers;
uint32_t size;
remaining_buffers = usb_hw->buf_status;
uint32_t bit = 1u;
if (remaining_buffers & bit) {
remaining_buffers &= ~bit;
usb_hw_clear->buf_status = bit;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0];
urb = pipe->urb;
switch (pipe->ep0_state) {
case USB_EP0_STATE_IN_DATA:
size = *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer, size);
urb->transfer_buffer += size;
urb->actual_length += size;
if (*pipe->endpoint_control & EP_CTRL_DOUBLE_BUFFERED_BITS) {
if (size == USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
size = (*pipe->buffer_control >> 16) & USB_BUF_CTRL_LEN_MASK;
memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer + 64, size);
urb->transfer_buffer += size;
urb->actual_length += size;
}
}
if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) {
pipe->ep0_state = USB_EP0_STATE_OUT_STATUS;
rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
urb->data_toggle ^= 1;
usb_start_transfer(bus, 0, 0x80);
}
break;
case USB_EP0_STATE_OUT_DATA:
urb->actual_length += *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
if (*pipe->endpoint_control & EP_CTRL_DOUBLE_BUFFERED_BITS) {
urb->actual_length += (*pipe->buffer_control >> 16) & USB_BUF_CTRL_LEN_MASK;
}
if (urb->transfer_buffer_length == 0) {
pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
} else {
urb->data_toggle ^= 1;
usb_start_transfer(bus, 0, 0x00);
}
break;
case USB_EP0_STATE_IN_STATUS:
case USB_EP0_STATE_OUT_STATUS:
urb->errorcode = 0;
rp2040_urb_waitup(urb);
break;
default:
break;
}
}
for (uint8_t i = 1; remaining_buffers && i <= CONFIG_USBHOST_PIPE_NUM; i++) {
for (uint8_t j = 0; j < 2; j++) {
bit = 1 << (i * 2 + j);
if (remaining_buffers & bit) {
remaining_buffers &= ~bit;
usb_hw_clear->buf_status = bit;
pipe = &g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i];
urb = pipe->urb;
if (urb == NULL) {
continue;
}
if (j == 0) { //IN
size = *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
memcpy(urb->transfer_buffer, (uint8_t *)pipe->data_buffer, size);
urb->transfer_buffer += size;
urb->actual_length += size;
urb->data_toggle ^= 1;
if (size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) || urb->transfer_buffer_length == 0) {
urb->errorcode = 0;
rp2040_urb_waitup(urb);
} else {
usb_start_transfer(bus, i, urb->ep->bEndpointAddress);
}
} else { //OUT
urb->data_toggle ^= 1;
urb->actual_length += *pipe->buffer_control & USB_BUF_CTRL_LEN_MASK;
if (urb->transfer_buffer_length == 0) {
urb->errorcode = 0;
rp2040_urb_waitup(urb);
} else {
usb_start_transfer(bus, i, urb->ep->bEndpointAddress);
}
}
}
}
}
}
void USBH_IRQHandler(uint8_t busid)
{
uint32_t status;
uint32_t handled = 0;
struct usbh_bus *bus;
struct rp2040_pipe *pipe;
struct usbh_urb *urb;
bus = &g_usbhost_bus[busid];
status = usb_hw->ints;
if (status & USB_INTS_HOST_CONN_DIS_BITS) {
handled |= USB_INTS_HOST_CONN_DIS_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
if (usbh_get_port_speed()) {
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 1;
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
} else {
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 0;
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
}
}
if (status & USB_INTS_STALL_BITS) {
handled |= USB_INTS_STALL_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS;
}
if (status & USB_INTS_BUFF_STATUS_BITS) {
handled |= USB_INTS_BUFF_STATUS_BITS;
rp2040_handle_buffer_status(bus);
}
if (status & USB_INTS_TRANS_COMPLETE_BITS) {
handled |= USB_INTS_TRANS_COMPLETE_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) {
pipe = (struct rp2040_pipe *)&g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0];
urb = pipe->urb;
if (urb) {
if (urb->setup->wLength) {
if (urb->setup->bmRequestType & 0x80) {
pipe->ep0_state = USB_EP0_STATE_IN_DATA;
} else {
pipe->ep0_state = USB_EP0_STATE_OUT_DATA;
}
} else {
pipe->ep0_state = USB_EP0_STATE_IN_STATUS;
}
urb->actual_length = 8;
rp2040_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
}
} else {
}
}
if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) {
handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS;
}
if (status & USB_INTS_ERROR_DATA_SEQ_BITS) {
handled |= USB_INTS_ERROR_DATA_SEQ_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
}
if (status ^ handled) {
USB_LOG_ERR("Unhandled IRQ 0x%x\n", (uint)(status ^ handled));
}
}
void rp2040_usbh_irq(void)
{
USBH_IRQHandler(0);
}

View File

@ -0,0 +1,125 @@
#include "usbd_core.h"
/* Endpoint state */
struct usb_dc_ep_state {
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_type; /* Endpoint type */
uint8_t ep_stalled; /* Endpoint stall flag */
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t actual_xfer_len;
};
/* Driver state */
struct xxx_udc {
volatile uint8_t dev_addr;
struct usb_dc_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct usb_dc_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
} g_xxx_udc;
__WEAK void usb_dc_low_level_init(void)
{
}
__WEAK void usb_dc_low_level_deinit(void)
{
}
int usb_dc_init(uint8_t busid)
{
memset(&g_xxx_udc, 0, sizeof(struct xxx_udc));
usb_dc_low_level_init();
return 0;
}
int usb_dc_deinit(uint8_t busid)
{
return 0;
}
int usbd_set_address(uint8_t busid, const uint8_t addr)
{
return 0;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}
uint8_t usbd_get_port_speed(uint8_t busid)
{
return USB_SPEED_FULL;
}
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
g_xxx_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_xxx_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_xxx_udc.out_ep[ep_idx].ep_enable = true;
} else {
g_xxx_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_xxx_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_xxx_udc.in_ep[ep_idx].ep_enable = true;
}
return 0;
}
int usbd_ep_close(uint8_t busid, const uint8_t ep)
{
return 0;
}
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
{
return 0;
}
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
{
return 0;
}
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
{
return 0;
}
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
uint32_t tmp;
if (!data && data_len) {
return -1;
}
g_xxx_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_xxx_udc.in_ep[ep_idx].xfer_len = data_len;
g_xxx_udc.in_ep[ep_idx].actual_xfer_len = 0;
return 0;
}
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep);
if (!data && data_len) {
return -1;
}
g_xxx_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
g_xxx_udc.out_ep[ep_idx].xfer_len = data_len;
g_xxx_udc.out_ep[ep_idx].actual_xfer_len = 0;
return 0;
}
void USBD_IRQHandler(uint8_t busid)
{
}

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
int usb_hc_init(struct usbh_bus *bus)
{
return 0;
}
int usb_hc_deinit(struct usbh_bus *bus)
{
return 0;
}
uint16_t usbh_get_frame_number(struct usbh_bus *bus)
{
return 0;
}
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
{
uint8_t nports;
uint8_t port;
uint32_t status;
nports = CONFIG_USBHOST_MAX_RHPORTS;
port = setup->wIndex;
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_NOTSUPP;
}
break;
case HUB_REQUEST_SET_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_NOTSUPP;
}
break;
case HUB_REQUEST_GET_DESCRIPTOR:
break;
case HUB_REQUEST_GET_STATUS:
memset(buf, 0, 4);
break;
default:
break;
}
} else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
switch (setup->wValue) {
case HUB_PORT_FEATURE_ENABLE:
break;
case HUB_PORT_FEATURE_SUSPEND:
break;
case HUB_PORT_FEATURE_C_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_C_CONNECTION:
break;
case HUB_PORT_FEATURE_C_ENABLE:
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
break;
case HUB_PORT_FEATURE_C_RESET:
break;
default:
return -USB_ERR_NOTSUPP;
}
break;
case HUB_REQUEST_SET_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
switch (setup->wValue) {
case HUB_PORT_FEATURE_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_RESET:
break;
default:
return -USB_ERR_NOTSUPP;
}
break;
case HUB_REQUEST_GET_STATUS:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}
memcpy(buf, &status, 4);
break;
default:
break;
}
}
return 0;
}
int usbh_submit_urb(struct usbh_urb *urb)
{
return -USB_ERR_NOTSUPP;
}
int usbh_kill_urb(struct usbh_urb *urb)
{
return -USB_ERR_NOTSUPP;
}
void USBH_IRQHandler(uint8_t busid)
{
}