From de30bd110511f60a8801805707093214c565f11e Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Fri, 7 Mar 2025 14:08:56 +0800 Subject: [PATCH] update(cherryusb): update to v1.4.3 Signed-off-by: sakumisu <1203593632@qq.com> --- components/drivers/usb/cherryusb/Kconfig | 4 +- components/drivers/usb/cherryusb/README.md | 8 +- components/drivers/usb/cherryusb/README_zh.md | 8 +- components/drivers/usb/cherryusb/SConscript | 12 +- components/drivers/usb/cherryusb/VERSION | 2 +- .../drivers/usb/cherryusb/cherryusb.cmake | 6 + .../usb/cherryusb/cherryusb_config_template.h | 40 +- .../usb/cherryusb/class/audio/usb_audio.h | 74 + .../usb/cherryusb/class/cdc/usbh_cdc_ecm.c | 4 +- .../usb/cherryusb/class/cdc/usbh_cdc_ecm.h | 2 +- .../usb/cherryusb/class/cdc/usbh_cdc_ncm.c | 8 +- .../usb/cherryusb/class/cdc/usbh_cdc_ncm.h | 2 +- .../drivers/usb/cherryusb/class/hid/usb_hid.h | 158 +- .../usb/cherryusb/class/hub/usbh_hub.c | 4 +- .../usb/cherryusb/class/msc/usbd_msc.c | 6 +- .../usb/cherryusb/class/msc/usbh_msc.c | 111 +- .../usb/cherryusb/class/msc/usbh_msc.h | 1 + .../cherryusb/class/vendor/net/usbh_asix.c | 4 +- .../cherryusb/class/vendor/net/usbh_asix.h | 2 +- .../cherryusb/class/vendor/net/usbh_rtl8152.c | 4 +- .../cherryusb/class/vendor/net/usbh_rtl8152.h | 2 +- .../cherryusb/class/vendor/wifi/usbh_bl616.c | 4 +- .../cherryusb/class/vendor/wifi/usbh_bl616.h | 2 +- .../usb/cherryusb/class/wireless/usbd_rndis.c | 56 +- .../usb/cherryusb/class/wireless/usbd_rndis.h | 4 + .../cherryusb/class/wireless/usbh_bluetooth.c | 6 +- .../cherryusb/class/wireless/usbh_bluetooth.h | 6 +- .../usb/cherryusb/class/wireless/usbh_rndis.c | 24 +- .../usb/cherryusb/class/wireless/usbh_rndis.h | 2 +- .../drivers/usb/cherryusb/common/usb_dc.h | 5 +- .../drivers/usb/cherryusb/common/usb_dcache.h | 19 + .../drivers/usb/cherryusb/common/usb_hc.h | 3 + .../drivers/usb/cherryusb/common/usb_log.h | 4 +- .../drivers/usb/cherryusb/common/usb_osal.h | 10 +- .../drivers/usb/cherryusb/common/usb_util.h | 8 + .../drivers/usb/cherryusb/core/usbd_core.c | 114 +- .../drivers/usb/cherryusb/core/usbh_core.c | 24 +- .../drivers/usb/cherryusb/core/usbh_core.h | 1 + .../cherryusb/demo/adb/usbd_adb_template.c | 78 +- .../demo/audio_v1_mic_multichan_template.c | 84 +- .../audio_v1_mic_speaker_multichan_template.c | 151 +- .../demo/audio_v2_mic_multichan_template.c | 85 ++ .../audio_v2_mic_speaker_multichan_template.c | 101 +- .../audio_v2_speaker_multichan_template.c | 143 +- .../demo/bootuf2/msc_bootuf2_template.c | 68 + .../cherryusb/demo/cdc_acm_hid_msc_template.c | 101 +- .../usb/cherryusb/demo/cdc_acm_msc_template.c | 12 +- .../cherryusb/demo/cdc_acm_multi_template.c | 82 +- .../usb/cherryusb/demo/cdc_acm_template.c | 74 +- .../usb/cherryusb/demo/cdc_ecm_template.c | 74 +- .../usb/cherryusb/demo/cdc_rndis_template.c | 78 +- .../demo/dfu_with_st_tool_template.c | 68 + .../demo/hid_custom_inout_template.c | 102 ++ .../cherryusb/demo/hid_keyboard_template.c | 100 ++ .../usb/cherryusb/demo/hid_mouse_template.c | 100 ++ .../demo/hid_remote_wakeup_template.c | 100 ++ .../usb/cherryusb/demo/midi_template.c | 123 +- .../usb/cherryusb/demo/msc_ram_template.c | 68 + .../usb/cherryusb/demo/msc_storage_template.c | 172 --- .../drivers/usb/cherryusb/demo/usb_host.c | 24 +- .../demo/video_audiov1_hid_template.c | 119 ++ .../demo/video_static_h264_template.c | 76 + .../demo/video_static_mjpeg_template.c | 76 + .../demo/video_static_yuyv_template.c | 78 + .../usb/cherryusb/demo/webusb_hid_template.c | 127 +- .../usb/cherryusb/demo/winusb1.0_template.c | 98 +- .../cherryusb/demo/winusb2.0_cdc_template.c | 187 ++- .../cherryusb/demo/winusb2.0_hid_template.c | 166 ++- .../drivers/usb/cherryusb/idf_component.yml | 2 +- .../usb/cherryusb/osal/usb_osal_rtthread.c | 2 + .../cherryusb/platform/rtthread/usbh_dfs.c | 66 +- .../usb/cherryusb/port/aic/usb_dc_aic.c | 1304 +++++++++++++++++ .../usb/cherryusb/port/aic/usb_dc_aic_ll.c | 43 + .../usb/cherryusb/port/aic/usb_dc_aic_reg.h | 301 ++++ .../usb/cherryusb/port/ch32/ch585_usbhs_dc.c | 525 +++++++ .../usb/cherryusb/port/ch32/ch585_usbhs_reg.h | 450 ++++++ .../cherryusb/port/ch32/usb_ch58x_dc_usbfs.c | 639 ++++++++ .../cherryusb/port/ch32/usb_ch58x_usbfs_reg.h | 249 ++++ .../drivers/usb/cherryusb/port/dwc2/README.md | 4 +- .../usb/cherryusb/port/dwc2/usb_glue_esp.c | 1 + .../usb/cherryusb/port/dwc2/usb_glue_st.c | 2 - .../usb/cherryusb/port/dwc2/usb_hc_dwc2.c | 38 +- .../drivers/usb/cherryusb/port/ehci/README.md | 2 +- .../usb/cherryusb/port/ehci/usb_glue_t113.c | 219 +++ .../usb/cherryusb/port/ehci/usb_hc_ehci.c | 46 +- .../usb/cherryusb/port/ehci/usb_hc_ehci.h | 12 +- .../usb/cherryusb/port/fsdev/README.md | 5 +- .../usb/cherryusb/port/musb/usb_hc_musb.c | 16 +- .../usb/cherryusb/port/ohci/usb_hc_ohci.h | 8 +- .../usb/cherryusb/port/rp2040/README.md | 5 + .../usb/cherryusb/port/rp2040/usb_dc_rp2040.c | 588 ++++++++ .../usb/cherryusb/port/rp2040/usb_hc_rp2040.c | 824 +++++++++++ .../usb/cherryusb/port/template/usb_dc.c | 125 ++ .../usb/cherryusb/port/template/usb_hc.c | 133 ++ 94 files changed, 8719 insertions(+), 559 deletions(-) create mode 100644 components/drivers/usb/cherryusb/common/usb_dcache.h delete mode 100644 components/drivers/usb/cherryusb/demo/msc_storage_template.c create mode 100644 components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c create mode 100644 components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c create mode 100644 components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h create mode 100644 components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c create mode 100644 components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h create mode 100644 components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c create mode 100644 components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h create mode 100644 components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c create mode 100644 components/drivers/usb/cherryusb/port/rp2040/README.md create mode 100644 components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c create mode 100644 components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c create mode 100644 components/drivers/usb/cherryusb/port/template/usb_dc.c create mode 100644 components/drivers/usb/cherryusb/port/template/usb_hc.c diff --git a/components/drivers/usb/cherryusb/Kconfig b/components/drivers/usb/cherryusb/Kconfig index 2b7ce80679..9e0f8ce02a 100644 --- a/components/drivers/usb/cherryusb/Kconfig +++ b/components/drivers/usb/cherryusb/Kconfig @@ -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 diff --git a/components/drivers/usb/cherryusb/README.md b/components/drivers/usb/cherryusb/README.md index e56946a772..25e7f0b624 100644 --- a/components/drivers/usb/cherryusb/README.md +++ b/components/drivers/usb/cherryusb/README.md @@ -12,7 +12,7 @@ English

-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 diff --git a/components/drivers/usb/cherryusb/README_zh.md b/components/drivers/usb/cherryusb/README_zh.md index 50d2b6f672..8a5bb45dd2 100644 --- a/components/drivers/usb/cherryusb/README_zh.md +++ b/components/drivers/usb/cherryusb/README_zh.md @@ -12,7 +12,7 @@ English

-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 | ## 软件包支持 diff --git a/components/drivers/usb/cherryusb/SConscript b/components/drivers/usb/cherryusb/SConscript index 29cbd4ae80..e4af1fc5f6 100644 --- a/components/drivers/usb/cherryusb/SConscript +++ b/components/drivers/usb/cherryusb/SConscript @@ -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') diff --git a/components/drivers/usb/cherryusb/VERSION b/components/drivers/usb/cherryusb/VERSION index 340d4aefcd..ce12c2dbf9 100644 --- a/components/drivers/usb/cherryusb/VERSION +++ b/components/drivers/usb/cherryusb/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 1 VERSION_MINOR = 4 -PATCHLEVEL = 2 +PATCHLEVEL = 3 VERSION_TWEAK = 0 EXTRAVERSION = 0 diff --git a/components/drivers/usb/cherryusb/cherryusb.cmake b/components/drivers/usb/cherryusb/cherryusb.cmake index 271717008c..0fe2292239 100644 --- a/components/drivers/usb/cherryusb/cherryusb.cmake +++ b/components/drivers/usb/cherryusb/cherryusb.cmake @@ -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() diff --git a/components/drivers/usb/cherryusb/cherryusb_config_template.h b/components/drivers/usb/cherryusb/cherryusb_config_template.h index e7d5230f1c..41cc246eb1 100644 --- a/components/drivers/usb/cherryusb/cherryusb_config_template.h +++ b/components/drivers/usb/cherryusb/cherryusb_config_template.h @@ -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 diff --git a/components/drivers/usb/cherryusb/class/audio/usb_audio.h b/components/drivers/usb/cherryusb/class/audio/usb_audio.h index ff7a9fe2a9..eb518b7bcb 100644 --- a/components/drivers/usb/cherryusb/class/audio/usb_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usb_audio.h @@ -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 */ diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c index c4743e56d3..5ca1ff33b4 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c @@ -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: diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h index 6e8dbc7f95..a3ab84a5cd 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.h @@ -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 } diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c index f9f3c53381..8bffea7ff8 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c @@ -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: diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h index e9b3e8e055..b86122a232 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.h @@ -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 } diff --git a/components/drivers/usb/cherryusb/class/hid/usb_hid.h b/components/drivers/usb/cherryusb/class/hid/usb_hid.h index b244d11972..62525a7444 100644 --- a/components/drivers/usb/cherryusb/class/hid/usb_hid.h +++ b/components/drivers/usb/cherryusb/class/hid/usb_hid.h @@ -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 */ diff --git a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c index 9dae396607..54377a74be 100644 --- a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c +++ b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c @@ -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) { diff --git a/components/drivers/usb/cherryusb/class/msc/usbd_msc.c b/components/drivers/usb/cherryusb/class/msc/usbd_msc.c index 1f84d02c9b..993617abe1 100644 --- a/components/drivers/usb/cherryusb/class/msc/usbd_msc.c +++ b/components/drivers/usb/cherryusb/class/msc/usbd_msc.c @@ -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); diff --git a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c index 96cb53d263..88c90b0b1a 100644 --- a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c +++ b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c @@ -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) diff --git a/components/drivers/usb/cherryusb/class/msc/usbh_msc.h b/components/drivers/usb/cherryusb/class/msc/usbh_msc.h index 50a61a9c11..c4aee8a855 100644 --- a/components/drivers/usb/cherryusb/class/msc/usbh_msc.h +++ b/components/drivers/usb/cherryusb/class/msc/usbh_msc.h @@ -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); diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c index 66c1f07803..f497671829 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c @@ -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: diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h index 8b0b5d98fd..bdeb0e3107 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.h @@ -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 } diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c index 10fc048398..4913389a22 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c @@ -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: diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h index 9d593b9126..171fa0bf6b 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.h @@ -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 } diff --git a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c index 9275faacc6..059086bebf 100644 --- a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c +++ b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c @@ -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) { diff --git a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h index 6ec5a7a8ab..2d247ae2ea 100644 --- a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h +++ b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.h @@ -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); diff --git a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c index 43849706ea..3f778c2f31 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c @@ -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 @@ -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; -} \ No newline at end of file +} diff --git a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h index 72b89eab89..f0fc3ee233 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h @@ -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); diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c index 991f09579b..e507c7e658 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c @@ -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; diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h index 868ff2c2cc..87eb02acb3 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.h @@ -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); diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c index e9eaff0114..17260acda2 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c @@ -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"); } diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h index 17a400067f..505a07aeb5 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.h @@ -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 } diff --git a/components/drivers/usb/cherryusb/common/usb_dc.h b/components/drivers/usb/cherryusb/common/usb_dc.h index 1f2fdddddc..dd85d7cb98 100644 --- a/components/drivers/usb/cherryusb/common/usb_dc.h +++ b/components/drivers/usb/cherryusb/common/usb_dc.h @@ -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 diff --git a/components/drivers/usb/cherryusb/common/usb_dcache.h b/components/drivers/usb/cherryusb/common/usb_dcache.h new file mode 100644 index 0000000000..60fbb7e90d --- /dev/null +++ b/components/drivers/usb/cherryusb/common/usb_dcache.h @@ -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 */ diff --git a/components/drivers/usb/cherryusb/common/usb_hc.h b/components/drivers/usb/cherryusb/common/usb_hc.h index c4e2a16dc9..3335af2fd3 100644 --- a/components/drivers/usb/cherryusb/common/usb_hc.h +++ b/components/drivers/usb/cherryusb/common/usb_hc.h @@ -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 diff --git a/components/drivers/usb/cherryusb/common/usb_log.h b/components/drivers/usb/cherryusb/common/usb_log.h index 8c798c7cb4..94eedfb63e 100644 --- a/components/drivers/usb/cherryusb/common/usb_log.h +++ b/components/drivers/usb/cherryusb/common/usb_log.h @@ -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) { diff --git a/components/drivers/usb/cherryusb/common/usb_osal.h b/components/drivers/usb/cherryusb/common/usb_osal.h index a3380d1339..aa2f133689 100644 --- a/components/drivers/usb/cherryusb/common/usb_osal.h +++ b/components/drivers/usb/cherryusb/common/usb_osal.h @@ -10,13 +10,21 @@ #include #include +#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; diff --git a/components/drivers/usb/cherryusb/common/usb_util.h b/components/drivers/usb/cherryusb/common/usb_util.h index 624cd9fcb3..b2223b2b94 100644 --- a/components/drivers/usb/cherryusb/common/usb_util.h +++ b/components/drivers/usb/cherryusb/common/usb_util.h @@ -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 */ diff --git a/components/drivers/usb/cherryusb/core/usbd_core.c b/components/drivers/usb/cherryusb/core/usbd_core.c index d7fb351775..2a2fda460d 100644 --- a/components/drivers/usb/cherryusb/core/usbd_core.c +++ b/components/drivers/usb/cherryusb/core/usbd_core.c @@ -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; } diff --git a/components/drivers/usb/cherryusb/core/usbh_core.c b/components/drivers/usb/cherryusb/core/usbh_core.c index cb36f97eea..38b5439fee 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.c +++ b/components/drivers/usb/cherryusb/core/usbh_core.c @@ -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; diff --git a/components/drivers/usb/cherryusb/core/usbh_core.h b/components/drivers/usb/cherryusb/core/usbh_core.h index eaddb30432..1bed410d09 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.h +++ b/components/drivers/usb/cherryusb/core/usbh_core.h @@ -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 diff --git a/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c b/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c index 2090dae25c..c5a2d9ef9b 100644 --- a/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c +++ b/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c @@ -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); } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c b/components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c index 56684e4607..b1622656e6 100644 --- a/components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c +++ b/components/drivers/usb/cherryusb/demo/audio_v1_mic_multichan_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c b/components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c index 4beccc6baf..add1d8db7c 100644 --- a/components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c +++ b/components/drivers/usb/cherryusb/demo/audio_v1_mic_speaker_multichan_template.c @@ -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); } diff --git a/components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c b/components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c index c00fffa9fd..81b8e23094 100644 --- a/components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c +++ b/components/drivers/usb/cherryusb/demo/audio_v2_mic_multichan_template.c @@ -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; + } + } } } diff --git a/components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c b/components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c index 0aebe57517..93630dea9b 100644 --- a/components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c +++ b/components/drivers/usb/cherryusb/demo/audio_v2_mic_speaker_multichan_template.c @@ -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) { } diff --git a/components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c b/components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c index 0abb677a09..b34e03fcd5 100644 --- a/components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c +++ b/components/drivers/usb/cherryusb/demo/audio_v2_speaker_multichan_template.c @@ -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); } diff --git a/components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c b/components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c index fbada2dbe7..7c805699e8 100644 --- a/components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c +++ b/components/drivers/usb/cherryusb/demo/bootuf2/msc_bootuf2_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c index 148f324c37..40cae68f14 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c index a5ad404866..b35cc34ec6 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_msc_template.c @@ -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, diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c index 13f67f4b5f..966a817b1e 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_multi_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_template.c index a13d96a4b9..f8d5c4b941 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_acm_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c index 9147c92320..70a16af65b 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c index a83a75551a..1d43f34ad0 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c b/components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c index cd3ed53dfb..9c36433a08 100644 --- a/components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c +++ b/components/drivers/usb/cherryusb/demo/dfu_with_st_tool_template.c @@ -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); } diff --git a/components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c b/components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c index e5874c7677..47438d41b6 100644 --- a/components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_custom_inout_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c index 4d1afc3056..9fabba60dd 100644 --- a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c index 564d1718bb..bcd03e1d17 100644 --- a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c b/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c index 786c324039..fa4381191d 100644 --- a/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/midi_template.c b/components/drivers/usb/cherryusb/demo/midi_template.c index aa3b2ad78b..0203c74445 100644 --- a/components/drivers/usb/cherryusb/demo/midi_template.c +++ b/components/drivers/usb/cherryusb/demo/midi_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/msc_ram_template.c b/components/drivers/usb/cherryusb/demo/msc_ram_template.c index 90214834c0..1b19a571b5 100644 --- a/components/drivers/usb/cherryusb/demo/msc_ram_template.c +++ b/components/drivers/usb/cherryusb/demo/msc_ram_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/msc_storage_template.c b/components/drivers/usb/cherryusb/demo/msc_storage_template.c deleted file mode 100644 index 047bad8e2f..0000000000 --- a/components/drivers/usb/cherryusb/demo/msc_storage_template.c +++ /dev/null @@ -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 \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/usb_host.c b/components/drivers/usb/cherryusb/demo/usb_host.c index 817103d5c0..c891d67a40 100644 --- a/components/drivers/usb/cherryusb/demo/usb_host.c +++ b/components/drivers/usb/cherryusb/demo/usb_host.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c b/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c index 6a4116222a..0241b5d7a3 100644 --- a/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/video_static_h264_template.c b/components/drivers/usb/cherryusb/demo/video_static_h264_template.c index e325964a2f..607376720d 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_h264_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_h264_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c b/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c index 1d2ae01ba4..0e77b38dc4 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c b/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c index 4ba71701c4..1aca76d025 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c index 5257087997..f446391f18 100644 --- a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/winusb1.0_template.c b/components/drivers/usb/cherryusb/demo/winusb1.0_template.c index 1eb390b92f..6568939cc4 100644 --- a/components/drivers/usb/cherryusb/demo/winusb1.0_template.c +++ b/components/drivers/usb/cherryusb/demo/winusb1.0_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c b/components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c index 493668e55b..34e646efa6 100644 --- a/components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c +++ b/components/drivers/usb/cherryusb/demo/winusb2.0_cdc_template.c @@ -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) { + } + } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c b/components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c index a209dbd59a..1fc6de3565 100644 --- a/components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/winusb2.0_hid_template.c @@ -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); diff --git a/components/drivers/usb/cherryusb/idf_component.yml b/components/drivers/usb/cherryusb/idf_component.yml index a500a24047..b34f4759bf 100644 --- a/components/drivers/usb/cherryusb/idf_component.yml +++ b/components/drivers/usb/cherryusb/idf_component.yml @@ -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 diff --git a/components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c b/components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c index d355699c06..dd1075a5fa 100644 --- a/components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c +++ b/components/drivers/usb/cherryusb/osal/usb_osal_rtthread.c @@ -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; } diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c b/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c index 073d52ea4e..eee64a0bfb 100644 --- a/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c +++ b/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c @@ -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) diff --git a/components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c new file mode 100644 index 0000000000..46cbfea858 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic.c @@ -0,0 +1,1304 @@ +/* + * Copyright (c) 2023, Artinchip Technology Co., Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "usbd_core.h" +#include "usb_dc_aic_reg.h" + +// clang-format off +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +// clang-format on + +#define FS_PORT 0 +#define HS_PORT 1 + +#ifndef CONFIG_USB_AIC_DC_PORT +#error "please select CONFIG_USB_AIC_DC_PORT with FS_PORT or HS_PORT" +#endif + +#ifndef USB_BASE +#define USB_BASE CONFIG_USB_AIC_DC_BASE +#endif + +#ifdef LPKG_CHERRYUSB_DEVICE_HID_IO_TEMPLATE +#define USB_RAM_SIZE 1024 /* define with maximum value*/ +#else +#define USB_RAM_SIZE 512 /* define with maximum value*/ +#endif + +#ifndef USB_NUM_BIDIR_ENDPOINTS +#define USB_NUM_BIDIR_ENDPOINTS 5 /* define with minimum value*/ +#endif + +#define AIC_UDC_REG ((AIC_UDC_RegDef *)(USB_BASE)) +#define AIC_EP_FIFO(i) *(__IO uint32_t *)(USB_BASE + AIC_EP_FIFO_BASE + ((i)*AIC_EP_FIFO_SIZE)) + +static uint8_t g_aic_udc_ibuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); +static uint8_t g_aic_udc_obuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); + +/* Endpoint state */ +struct aic_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; +#ifdef CONFIG_USB_AIC_DMA_ENABLE + uint8_t *xfer_align_buf; + uint32_t xfer_align_len; +#endif + uint32_t xfer_len; + uint32_t actual_xfer_len; +}; + +extern uint32_t usbd_clk; + +/* Driver state */ +/*USB_NOCACHE_RAM_SECTION*/ struct aic_udc { + USB_MEM_ALIGNX struct usb_setup_packet setup; + USB_MEM_ALIGNX struct aic_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/ + struct aic_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ + uint32_t tx_fifo_map; +} g_aic_udc; + +uint8_t rst_allow = 0; +uint8_t ep0_ctrl_stage = 0; /* 1 = setup stage, 2 = data stage, 3 = status stage */ + +#ifdef CONFIG_USB_AIC_DMA_ENABLE +void aic_udc_dcache_clean(uintptr_t addr, uint32_t len) +{ + aicos_dcache_clean_range((size_t *)addr, len); +} + +void aic_udc_dcache_invalidate(uintptr_t addr, uint32_t len) +{ + aicos_dcache_invalid_range((size_t *)addr, len); +} + +void aic_udc_dcache_clean_invalidate(uintptr_t addr, uint32_t len) +{ + aicos_dcache_clean_invalid_range((size_t *)addr, len); +} + +static int aic_udc_ep_buf_alloc(struct aic_ep_state *ep, uint32_t len, + uint8_t *sbuf) +{ + ep->xfer_len = len; + if (len % CACHE_LINE_SIZE) + ep->xfer_align_len = ALIGN_UP(len, CACHE_LINE_SIZE); + else + ep->xfer_align_len = len; + + if (ep->xfer_align_len > USB_RAM_SIZE) { + ep->xfer_align_buf = aicos_malloc_align(0, ep->xfer_align_len, + CACHE_LINE_SIZE); + if (!ep->xfer_align_buf) { + USB_LOG_ERR("alloc error.\r\n"); + return -5; + } + } else { + ep->xfer_align_buf = sbuf; + } + + return 0; +} + +static void aic_udc_ep_buf_free(struct aic_ep_state *ep, uint8_t *sbuf) +{ + if (!ep->xfer_align_buf) + return; + + /* Whether the buf is allocated dynamically */ + if (ep->xfer_align_buf != sbuf) + aicos_free_align(0, ep->xfer_align_buf); + + ep->xfer_align_buf = NULL; + ep->xfer_align_len = 0; +} + +static int aic_udc_ibuf_alloc(struct aic_ep_state *ep, uint32_t len) +{ + return aic_udc_ep_buf_alloc(ep, len, g_aic_udc_ibuf); +} + +static int aic_udc_obuf_alloc(struct aic_ep_state *ep, uint32_t len) +{ + return aic_udc_ep_buf_alloc(ep, len, g_aic_udc_obuf); +} + +static void aic_udc_ibuf_free(struct aic_ep_state *ep) +{ + aic_udc_ep_buf_free(ep, g_aic_udc_ibuf); +} + +static void aic_udc_obuf_free(struct aic_ep_state *ep) +{ + aic_udc_ep_buf_free(ep, g_aic_udc_obuf); +} +#else +#define aic_udc_dcache_clean(addr, len) +#define aic_udc_dcache_invalidate(addr, len) +#define aic_udc_dcache_clean_invalidate(addr, len) +#endif + +static void aic_set_dma_nextep(void) +{ + uint32_t i; + + /* dma to set the next-endpoint pointer. */ + for (i = 0; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + uint32_t next = ((i + 1) % USB_NUM_BIDIR_ENDPOINTS) << DEPCTL_NEXT_EP_BIT; + + AIC_UDC_REG->inepcfg[i] &= ~DEPCTL_NEXT_EP_MASK; + AIC_UDC_REG->inepcfg[i] |= next; + } +} + +static inline int aic_reset(void) +{ + uint32_t count = 0U; + + /* Wait for AHB master IDLE state. */ + do { + if (++count > 200000U) { + return -1; + } + } while ((AIC_UDC_REG->ahbbasic & AHBBASIC_AHBIDLE) == 0U); + + /* Core Soft Reset */ + count = 0U; + AIC_UDC_REG->usbdevinit |= USBDEVINIT_CSFTRST; + + do { + if (++count > 200000U) { + return -1; + } + } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_CSFTRST) == USBDEVINIT_CSFTRST); + + return 0; +} + +static inline int aic_core_init(void) +{ + int ret; + uint32_t usb_gusbcfg = + 0 << 19 /* ULPI Clock SuspendM */ + | 0 << 18 /* ULPI Phy Auto Resume */ + | 0 << 15 /* PHY Low Power Clock sel */ + | 0x5 << 10 /* USB Turnaround time (0x5 for HS phy) */ + | 0 << 7 /* ULPI DDR sel 0:single 8bit, 1:double 4bit */ + /*| 0 << 6 0: high speed utmi+, 1: full speed serial*/ +#ifdef FPGA_BOARD_ARTINCHIP + | 1 << 4 /* 0: utmi+, 1:ulpi*/ +#else + | 0 << 4 /* 0: utmi+, 1:ulpi*/ +#endif + | 0 << 3 /* UTMI+ PHY 0:8bit, 1:16bit (ULPI PHY set 8bit) */ + | 0x7 << 0; /* HS/FS timeout calibration**/ + + /* Reset after a PHY select */ + ret = aic_reset(); + + /* Activate the USB Transceiver */ + AIC_UDC_REG->usbphyif = usb_gusbcfg; + + aic_set_dma_nextep(); + + return ret; +} + +static inline int aic_flush_rxfifo(void) +{ + uint32_t count = 0; + + AIC_UDC_REG->usbdevinit |= USBDEVINIT_RXFFLSH; + + do { + if (++count > 200000U) { + return -1; + } + } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_RXFFLSH) == USBDEVINIT_RXFFLSH); + + return 0; +} + +static inline int aic_flush_txfifo(uint32_t num) +{ + uint32_t count = 0U; + + AIC_UDC_REG->usbdevinit |= USBDEVINIT_TXFNUM(num & USBDEVINIT_TXFNUM_LIMIT); + + do { + if (++count > 200000U) { + return -1; + } + } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_TXFFLSH) == USBDEVINIT_TXFFLSH); + + return 0; +} + +static void aic_set_turnaroundtime(uint32_t hclk, uint8_t speed) +{ + uint32_t UsbTrd; + + /* The USBTRD is configured according to the tables below, depending on AHB frequency + used by application. In the low AHB frequency range it is used to stretch enough the USB response + time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access + latency to the Data FIFO */ + if (speed == USB_ENUM_SPEED_FULL) { + if ((hclk >= 14200000U) && (hclk < 15000000U)) { + /* hclk Clock Range between 14.2-15 MHz */ + UsbTrd = 0xFU; + } else if ((hclk >= 15000000U) && (hclk < 16000000U)) { + /* hclk Clock Range between 15-16 MHz */ + UsbTrd = 0xEU; + } else if ((hclk >= 16000000U) && (hclk < 17200000U)) { + /* hclk Clock Range between 16-17.2 MHz */ + UsbTrd = 0xDU; + } else if ((hclk >= 17200000U) && (hclk < 18500000U)) { + /* hclk Clock Range between 17.2-18.5 MHz */ + UsbTrd = 0xCU; + } else if ((hclk >= 18500000U) && (hclk < 20000000U)) { + /* hclk Clock Range between 18.5-20 MHz */ + UsbTrd = 0xBU; + } else if ((hclk >= 20000000U) && (hclk < 21800000U)) { + /* hclk Clock Range between 20-21.8 MHz */ + UsbTrd = 0xAU; + } else if ((hclk >= 21800000U) && (hclk < 24000000U)) { + /* hclk Clock Range between 21.8-24 MHz */ + UsbTrd = 0x9U; + } else if ((hclk >= 24000000U) && (hclk < 27700000U)) { + /* hclk Clock Range between 24-27.7 MHz */ + UsbTrd = 0x8U; + } else if ((hclk >= 27700000U) && (hclk < 32000000U)) { + /* hclk Clock Range between 27.7-32 MHz */ + UsbTrd = 0x7U; + } else {/* if(hclk >= 32000000) */ + /* hclk Clock Range between 32-200 MHz */ + UsbTrd = 0x6U; + } + } else if (speed == USB_ENUM_SPEED_HIGH) { + UsbTrd = USBPHYIF_HS_TRDT_VALUE; + } else { + UsbTrd = USBPHYIF_DEFAULT_TRDT_VALUE; + } + + AIC_UDC_REG->usbphyif |= USBPHYIF_TOUTCAL_LIMIT; + + AIC_UDC_REG->usbphyif &= ~USBPHYIF_USBTRDTIM_MASK; + AIC_UDC_REG->usbphyif |= (uint32_t)((UsbTrd << USBPHYIF_USBTRDTIM_SHIFT) + & USBPHYIF_USBTRDTIM_MASK); +} + +#if 0 +static void aic_set_txfifo(uint8_t fifo, uint16_t size) +{ + uint8_t i; + uint32_t Tx_Offset; + + /* TXn min size = 16 words. (n : Transmit FIFO index) + When a TxFIFO is not used, the Configuration should be as follows: + case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txm can use the space allocated for Txn. + case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txn should be configured with the minimum space of 16 words + The FIFO is used optimally when used TxFIFOs are allocated in the top + of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. + When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */ + + Tx_Offset = AIC_UDC_REG->rxfifosiz; + + if (fifo == 0U) { + AIC_UDC_REG->nptxfifosiz = ((uint32_t)size << 16) | Tx_Offset; + } else { + Tx_Offset += (AIC_UDC_REG->nptxfifosiz) >> 16; + for (i = 0U; i < (fifo - 1U); i++) { + Tx_Offset += (AIC_UDC_REG->txfifosiz[i] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + AIC_UDC_REG->txfifosiz[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset; + } +} +#endif + +static uint8_t aic_get_devspeed(void) +{ + uint8_t speed; + uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK; + + if (DevEnumSpeed == USB_HIGH_30_60MHZ) { + speed = USB_ENUM_SPEED_HIGH; + } else if (DevEnumSpeed == USB_FULL_30_60MHZ) { + speed = USB_ENUM_SPEED_FULL; + } else { + speed = 0xFU; + } + + return speed; +} + +static void aic_ep0_start_read_setup(uint8_t *psetup) +{ + g_aic_udc.out_ep[0].xfer_buf = psetup; + g_aic_udc.out_ep[0].xfer_len = 8; + ep0_ctrl_stage = 1; + + aic_udc_dcache_invalidate((uintptr_t)psetup, CACHE_LINE_SIZE); + + AIC_UDC_REG->outeptsfsiz[0] = 0U; + AIC_UDC_REG->outeptsfsiz[0] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + AIC_UDC_REG->outeptsfsiz[0] |= (3U * 8U); + AIC_UDC_REG->outeptsfsiz[0] |= DXEPTSIZ_MULCNT_MASK; + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + AIC_UDC_REG->outepdmaaddr[0] = (uint32_t)(uintptr_t)psetup; +#endif + + /* EP enable */ + AIC_UDC_REG->outepcfg[0] |= DEPCTL_CNAK | DEPCTL_EPENA | DEPCTL_USBACTEP; +} + +void aic_ep_write(uint8_t ep_idx, uint8_t *src, uint16_t len) +{ + uint32_t *pSrc = (uint32_t *)src; + uint32_t count32b, i; + + count32b = ((uint32_t)len + 3U) / 4U; + for (i = 0U; i < count32b; i++) { + AIC_EP_FIFO(ep_idx) = __UNALIGNED_UINT32_READ(pSrc); + pSrc++; + } +} + +void aic_ep_read(uint8_t *dest, uint16_t len) +{ + uint32_t *pDest = (uint32_t *)dest; + uint32_t i; + uint32_t count32b = ((uint32_t)len + 3U) / 4U; + + for (i = 0U; i < count32b; i++) { + __UNALIGNED_UINT32_WRITE(pDest, AIC_EP_FIFO(0U)); + pDest++; + } +} + +#ifndef CONFIG_USB_AIC_DMA_ENABLE +static void aic_tx_fifo_empty_procecss(uint8_t ep_idx) +{ + uint32_t len; + //uint32_t len32b; + + len = g_aic_udc.in_ep[ep_idx].xfer_len - g_aic_udc.in_ep[ep_idx].actual_xfer_len; + if (len > g_aic_udc.in_ep[ep_idx].ep_mps) { + len = g_aic_udc.in_ep[ep_idx].ep_mps; + } + + //len32b = (len + 3U) / 4U; + + while (/*((AIC_UDC_REG->ineptxsts[ep_idx] & INEPTXSTS_IN_EP_TXFIFO_STS) >= len32b) &&*/ + (g_aic_udc.in_ep[ep_idx].actual_xfer_len < g_aic_udc.in_ep[ep_idx].xfer_len) && (g_aic_udc.in_ep[ep_idx].xfer_len != 0U)) { + /* Write the FIFO */ + len = g_aic_udc.in_ep[ep_idx].xfer_len - g_aic_udc.in_ep[ep_idx].actual_xfer_len; + if (len > g_aic_udc.in_ep[ep_idx].ep_mps) { + len = g_aic_udc.in_ep[ep_idx].ep_mps; + } + + aic_ep_write(ep_idx, g_aic_udc.in_ep[ep_idx].xfer_buf, len); + g_aic_udc.in_ep[ep_idx].xfer_buf += len; + g_aic_udc.in_ep[ep_idx].actual_xfer_len += len; + } +} +#endif + +/** + * @brief aic_get_glb_intstatus: return the global USB interrupt status + * @retval status + */ +static inline uint32_t aic_get_glb_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = AIC_UDC_REG->usbintsts; + tmpreg &= AIC_UDC_REG->usbintmsk; + + return tmpreg; +} + +/** + * @brief aic_get_outeps_intstatus: return the USB device OUT endpoints interrupt status + * @retval status + */ +static inline uint32_t aic_get_outeps_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = AIC_UDC_REG->usbepint; + tmpreg &= AIC_UDC_REG->usbepintmsk; + + return ((tmpreg & 0xffff0000U) >> 16); +} + +/** + * @brief aic_get_ineps_intstatus: return the USB device IN endpoints interrupt status + * @retval status + */ +static inline uint32_t aic_get_ineps_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = AIC_UDC_REG->usbepint; + tmpreg &= AIC_UDC_REG->usbepintmsk; + + return ((tmpreg & 0xFFFFU)); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param epnum endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +static inline uint32_t aic_get_outep_intstatus(uint8_t epnum) +{ + uint32_t tmpreg; + + tmpreg = AIC_UDC_REG->outepint[epnum]; + tmpreg &= AIC_UDC_REG->outepintmsk; + + return tmpreg; +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param epnum endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +static inline uint32_t aic_get_inep_intstatus(uint8_t epnum) +{ + uint32_t tmpreg; + + tmpreg = AIC_UDC_REG->inepint[epnum]; + tmpreg &= AIC_UDC_REG->inepintmsk; + + return tmpreg; +} + +__WEAK void usb_dc_low_level_init(void) +{ +} + +__WEAK void usb_dc_low_level_deinit(void) +{ +} + +int usb_dc_rst(void) +{ + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if (i == 0U) { + AIC_UDC_REG->inepcfg[i] = DEPCTL_SNAK; + AIC_UDC_REG->outepcfg[i] = DEPCTL_SNAK; + } else { + usbd_ep_close(i); + usbd_ep_close(i | 0x80); + } + AIC_UDC_REG->ineptsfsiz[i] = 0U; + AIC_UDC_REG->inepint[i] = 0xFBFFU; + AIC_UDC_REG->outeptsfsiz[i] = 0U; + AIC_UDC_REG->outepint[i] = 0xFBFFU; + } + + AIC_UDC_REG->usbepintmsk |= 0x10001U; + AIC_UDC_REG->outepintmsk = CTRL_OUT_EP_SETUP_PHASE_DONE | TRANSFER_DONE; + AIC_UDC_REG->inepintmsk = TRANSFER_DONE; +#ifndef CONFIG_USB_AIC_DMA_ENABLE + AIC_UDC_REG->inepintmsk |= INTKN_TXFEMP; +#endif + + aic_flush_txfifo(0x10U); + aic_flush_rxfifo(); + + aic_set_dma_nextep(); + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + aic_udc_obuf_free(&g_aic_udc.out_ep[i]); + aic_udc_ibuf_free(&g_aic_udc.in_ep[i]); + } +#endif + + memset(&g_aic_udc, 0, sizeof(struct aic_udc)); + usbd_event_reset_handler(0); + /* Start reading setup */ + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + + return 0; +} + +int usb_dc_init(uint8_t busid) +{ + int ret; + uint32_t base = 0; + + memset(&g_aic_udc, 0, sizeof(struct aic_udc)); + + usb_dc_low_level_init(); + + /* Disconnect */ + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; + /* Disable Interrupt */ + AIC_UDC_REG->usbdevinit &= ~USBDEVINIT_GLBL_INTR_EN; + + ret = aic_core_init(); + + for (uint8_t i = 0U; i < 2U; i++) { + AIC_UDC_REG->txfifosiz[i] = 0U; + } + + /* Device mode configuration */ + AIC_UDC_REG->usbdevconf |= PERIOD_FRAME_INTERVAL_80; + +#if defined(CONFIG_USB_HS) + /* Set Core speed to High speed mode */ + AIC_UDC_REG->usbdevconf |= DEV_SPEED_HIGH_SPEED_20; +#else + + AIC_UDC_REG->usbdevconf |= DEV_SPEED_FULL_SPEED_20; +#endif + + ret = aic_flush_txfifo(0x10U); + ret = aic_flush_rxfifo(); + + /* Clear all pending Device Interrupts */ + AIC_UDC_REG->inepintmsk = 0U; + AIC_UDC_REG->outepintmsk = 0U; + AIC_UDC_REG->usbepintmsk = 0U; + + /* Disable all interrupts. */ + AIC_UDC_REG->usbintmsk = 0U; + /* Clear any pending interrupts */ + AIC_UDC_REG->usbintsts = 0xBFFFFFFFU; + + /* Enable interrupts matching to the Device mode ONLY */ + AIC_UDC_REG->usbintmsk = INT_RESET | INT_ENUMDONE | + INT_OUT_EP | INT_IN_EP | + INT_INCOMP_ISO_IN_INT | INT_INCOMP_ISO_OUT_INT; + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + AIC_UDC_REG->usbdevinit |= (USBDEVINIT_HBSTLEN_INCR4 << USBDEVINIT_HBSTLEN_SHIFT); + AIC_UDC_REG->usbdevinit |= USBDEVINIT_DMA_EN; +#else + AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY; +#endif + + /* Assign FIFO */ + base = 0; + AIC_UDC_REG->rxfifosiz = AIC_RX_FIFO_SIZE; + base += AIC_RX_FIFO_SIZE; + AIC_UDC_REG->nptxfifosiz = (AIC_NP_TX_FIFO_SIZE << 16) | base; + base += AIC_NP_TX_FIFO_SIZE; + AIC_UDC_REG->txfifosiz[0] = (AIC_PERIOD_TX_FIFO1_SIZE << 16) | base; + base += AIC_PERIOD_TX_FIFO1_SIZE; + AIC_UDC_REG->txfifosiz[1] = (AIC_PERIOD_TX_FIFO2_SIZE << 16) | base; + + usb_dc_rst(); + + /* Enable Interrupt */ + AIC_UDC_REG->usbdevinit |= USBDEVINIT_GLBL_INTR_EN; + /* Connect */ + AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_SFTDISCON; + + return ret; +} + +int usb_dc_deinit(uint8_t busid) +{ + /* Clear Pending interrupt */ + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + AIC_UDC_REG->outepint[i] = 0xFB7FU; + AIC_UDC_REG->inepint[i] = 0xFB7FU; + } + + /* Clear interrupt masks */ + AIC_UDC_REG->inepintmsk = 0U; + AIC_UDC_REG->outepintmsk = 0U; + AIC_UDC_REG->usbepintmsk = 0U; + + /* Flush the FIFO */ + aic_flush_txfifo(0x10U); + aic_flush_rxfifo(); + + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; + + usb_dc_low_level_deinit(); + return 0; +} + +int usbd_set_address(uint8_t busid, const uint8_t addr) +{ + AIC_UDC_REG->usbdevconf &= ~(DEVICE_ADDRESS_MASK); + AIC_UDC_REG->usbdevconf |= ((uint32_t)addr << 4) & DEVICE_ADDRESS_MASK; + + rst_allow = 1; + return 0; +} + +int usbd_set_remote_wakeup(uint8_t busid) +{ + return -1; +} + +uint8_t usbd_get_port_speed(uint8_t busid) +{ + uint8_t speed; + uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK; + + if (DevEnumSpeed == USB_HIGH_30_60MHZ) { + speed = USB_SPEED_HIGH; + } else if (DevEnumSpeed == USB_FULL_30_60MHZ) { + speed = USB_SPEED_FULL; + } else { + speed = USB_SPEED_FULL; + } + + return speed; +} + +int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress); + uint16_t ep_mps; + uint8_t tx_fifo_num = 0; + uint32_t i; + + if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) { + USB_LOG_ERR("Ep addr %d overflow\r\n", ep->bEndpointAddress); + return -1; + } + + if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) { + g_aic_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + g_aic_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); + + AIC_UDC_REG->usbepintmsk |= DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx)); + + ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + if (ep_idx == 0) { + switch (ep_mps) { + case 8: + ep_mps = DEPCTL0_MPS_8; + break; + case 16: + ep_mps = DEPCTL0_MPS_16; + break; + case 32: + ep_mps = DEPCTL0_MPS_32; + break; + case 64: + ep_mps = DEPCTL0_MPS_64; + break; + } + } + + AIC_UDC_REG->outepcfg[ep_idx] |= (ep_mps & DEPCTL_MPS_MASK) | + ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | + DEPCTL_SETD0PID | + DEPCTL_USBACTEP; + } else { + g_aic_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + g_aic_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); + + AIC_UDC_REG->usbepintmsk |= DAINT_IN_MASK & (uint32_t)(1UL << ep_idx); + + /* Period IN EP alloc fifo num */ + if (( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) || + ( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS)) { + for (i=1; i<=2; i++) { + if (g_aic_udc.tx_fifo_map & (1<inepcfg[ep_idx] |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & DEPCTL_MPS_MASK) | + ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | + (tx_fifo_num << 22) | + DEPCTL_SETD0PID | + DEPCTL_USBACTEP; + } + return 0; +} + +int usbd_ep_close(uint8_t busid, const uint8_t ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t tx_fifo_num = 0; + int i = 0; + #define DIS_EP_TIMOUT 100 + + if (USB_EP_DIR_IS_OUT(ep)) { + if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) { + /* (1) Wait for global nak to take effect */ + if (!(AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF)) + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGOUTNAK; + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + if (AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__); + + /* (2) Disable ep */ + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SNAK; + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_EPDIS; + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + if (AIC_UDC_REG->outepint[ep_idx] & EPDISBLD) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__); + + /* Clear EPDISBLD interrupt */ + AIC_UDC_REG->outepint[ep_idx] |= EPDISBLD; + + /* (3) Remove global NAKs */ + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGOUTNAK; + } + + AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx))); + AIC_UDC_REG->outepcfg[ep_idx] = 0; + } else { + tx_fifo_num = (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_TXFIFONUM_MASK) >> DEPCTL_TXFIFONUM_SHIFT; + + if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) { + if (tx_fifo_num) { + /* (1) Wait for Nak effect */ + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK; + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + if (AIC_UDC_REG->inepint[ep_idx] & INEP_NAKEFF) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout INEPINT.NAKEFF\n", __func__); + } else { + /* (1) Wait for Nak effect */ + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGNPINNAK; + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + if (AIC_UDC_REG->usbintsts & INT_GINNAKEFF) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__); + } + + /* (2) Disable ep */ + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK; + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_EPDIS; + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + if (AIC_UDC_REG->inepint[ep_idx] & EPDISBLD) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__); + + /* Clear EPDISBLD interrupt */ + AIC_UDC_REG->inepint[ep_idx] |= EPDISBLD; + + /* (3) Clear Global In NP NAK in Shared FIFO for non periodic ep */ + if (!tx_fifo_num) + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK; + } + + AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << ep_idx)); + AIC_UDC_REG->inepcfg[ep_idx] = 0; + + /* Flush TX FIFO */ + aic_flush_txfifo(tx_fifo_num); + + /* Period IN EP free fifo num */ + if (tx_fifo_num > 0) + g_aic_udc.tx_fifo_map &= ~(1<outepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + AIC_UDC_REG->outepcfg[ep_idx] &= ~(DEPCTL_EPDIS); + } + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_STALL; + } else { + if (((AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + AIC_UDC_REG->inepcfg[ep_idx] &= ~(DEPCTL_EPDIS); + } + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_STALL; + } + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + if (ep_idx == 0) { + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } +#endif + return 0; +} + +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)) { + AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_STALL; + if ((g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || + (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */ + } + } else { + AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_STALL; + if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || + (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */ + } + } + + return 0; +} + +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; +} + +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 pktcnt = 0; + + if (!data && data_len) { + return -1; + } + if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) { + return -2; + } + if (ep_idx && !(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_MPS_MASK)) { + return -3; + } + if ((uint32_t)(uintptr_t)data & 0x03) { + return -4; + } + + g_aic_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data; + g_aic_udc.in_ep[ep_idx].xfer_len = data_len; + g_aic_udc.in_ep[ep_idx].actual_xfer_len = 0; + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + if ((ep_idx != 0) && (data_len > 0) && + ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) || + (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) { + + if (g_aic_udc.in_ep[ep_idx].xfer_align_len != data_len) { + int ret = 0; + + aic_udc_ibuf_free(&g_aic_udc.in_ep[ep_idx]); + ret = aic_udc_ibuf_alloc(&g_aic_udc.in_ep[ep_idx], data_len); + if (ret) + return ret; + } + memcpy(g_aic_udc.in_ep[ep_idx].xfer_align_buf, data, data_len); + data = g_aic_udc.in_ep[ep_idx].xfer_align_buf; + } else { + aic_udc_ibuf_free(&g_aic_udc.in_ep[ep_idx]); + } + + if (data_len>0) + aic_udc_dcache_clean((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE)); +#endif + + AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); + AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); + AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); + + if (data_len == 0) { + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + return 0; + } + + if (ep_idx == 0) { + if (data_len > g_aic_udc.in_ep[ep_idx].ep_mps) { + data_len = g_aic_udc.in_ep[ep_idx].ep_mps; + } + g_aic_udc.in_ep[ep_idx].xfer_len = data_len; + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + } else { + pktcnt = (uint16_t)((data_len + g_aic_udc.in_ep[ep_idx].ep_mps - 1U) / g_aic_udc.in_ep[ep_idx].ep_mps); + + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19)); + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + } + + if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) || + (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT)) { + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1<usblinests & (1U << 8)) == 0U) { + AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID; + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID; + } else { + AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; + } + AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT); + } else if (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) { + AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); + AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT); + } + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + AIC_UDC_REG->inepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data; +#endif + + AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + + 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); + uint32_t pktcnt = 0; + + if (!data && data_len) { + return -1; + } + if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) { + return -2; + } + if (ep_idx && !(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_MPS_MASK)) { + return -3; + } + if (((uint32_t)(uintptr_t)data) & 0x03) { + return -4; + } + + g_aic_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data; + g_aic_udc.out_ep[ep_idx].xfer_len = data_len; + g_aic_udc.out_ep[ep_idx].actual_xfer_len = 0; + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + if ((ep_idx != 0) && (data_len > 0) && + ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) || + (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) { + + if (g_aic_udc.out_ep[ep_idx].xfer_align_len != data_len) { + int ret = 0; + + aic_udc_obuf_free(&g_aic_udc.out_ep[ep_idx]); + ret = aic_udc_obuf_alloc(&g_aic_udc.out_ep[ep_idx], data_len); + if (ret) + return ret; + } + data = g_aic_udc.out_ep[ep_idx].xfer_align_buf; + } else { + aic_udc_obuf_free(&g_aic_udc.out_ep[ep_idx]); + } + + if (data_len > 0) + aic_udc_dcache_invalidate((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE)); +#endif + + AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); + AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); + if (data_len == 0) { + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1 << 19)); + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & g_aic_udc.out_ep[ep_idx].ep_mps); + AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + return 0; + } + + if (ep_idx == 0) { + if (data_len > g_aic_udc.out_ep[ep_idx].ep_mps) { + data_len = g_aic_udc.out_ep[ep_idx].ep_mps; + } + g_aic_udc.out_ep[ep_idx].xfer_len = data_len; + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + } else { + pktcnt = (uint16_t)((data_len + g_aic_udc.out_ep[ep_idx].ep_mps - 1U) / g_aic_udc.out_ep[ep_idx].ep_mps); + + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19)); + AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + } + +#ifdef CONFIG_USB_AIC_DMA_ENABLE + AIC_UDC_REG->outepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data; +#endif + if (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { + if ((AIC_UDC_REG->usblinests & (1U << 8)) == 0U) { + AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID; + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID; + } else { + AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; + } + } + AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + return 0; +} + +void USBD_IRQHandler(void) +{ + uint32_t gint_status, ep_idx, ep_intr, epint, daintmask; + gint_status = aic_get_glb_intstatus(); + + /* Avoid spurious interrupt */ + if (gint_status == 0) { + return; + } + +#ifndef CONFIG_USB_AIC_DMA_ENABLE + uint32_t temp; + uint32_t read_count; + + /* Handle RxQLevel Interrupt */ + if (gint_status & INT_RX_FIFO_NOT_EMPTY) { + AIC_UDC_REG->usbintmsk &= ~(INT_RX_FIFO_NOT_EMPTY); + + temp = AIC_UDC_REG->rxfifosts_pop; + ep_idx = temp & RXFIFOSTS_EPNUM_MASK; + + if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_OUT_DATA_PKT_REC) { + read_count = (temp & RXFIFOSTS_BCNT_MASK) >> 4; + if (read_count != 0) { + aic_ep_read(g_aic_udc.out_ep[ep_idx].xfer_buf, read_count); + g_aic_udc.out_ep[ep_idx].xfer_buf += read_count; + } + } else if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_SETUP_DATA_PKT_REC) { + read_count = (temp & RXFIFOSTS_BCNT_MASK) >> 4; + aic_ep_read((uint8_t *)&g_aic_udc.setup, read_count); + } else { + /* ... */ + } + AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY; + } +#endif + if (gint_status & INT_OUT_EP) { + ep_idx = 0; + ep_intr = aic_get_outeps_intstatus(); + while (ep_intr != 0U) { + if ((ep_intr & 0x1U) != 0U) { + epint = aic_get_outep_intstatus(ep_idx); + uint32_t DoepintReg = AIC_UDC_REG->outepint[ep_idx]; + AIC_UDC_REG->outepint[ep_idx] = DoepintReg; + + struct aic_ep_state *ep = &g_aic_udc.out_ep[ep_idx]; + if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { + #ifdef CONFIG_USB_AIC_DMA_ENABLE + if (ep->xfer_align_buf) + memcpy(ep->xfer_buf, ep->xfer_align_buf, ep->xfer_len); + #endif + if ((ep_idx == 0)) { + if (ep0_ctrl_stage == 1) { + ep0_ctrl_stage = 2; + usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup); + } else { + if (ep->xfer_len == 0) { + /* Out status, start reading setup */ + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } else { + ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + ep->xfer_len = 0; + usbd_event_ep_out_complete_handler(0, 0x00, ep->actual_xfer_len); + } + } + } else { + ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + ep->xfer_len = 0; + usbd_event_ep_out_complete_handler(0, ep_idx, ep->actual_xfer_len); + } + } + + if ((epint & CTRL_OUT_EP_SETUP_PHASE_DONE) == CTRL_OUT_EP_SETUP_PHASE_DONE) { + if (ep0_ctrl_stage == 1) { + ep0_ctrl_stage = 2; + usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup); + } + } + } + ep_intr >>= 1U; + ep_idx++; + } + } + +#ifndef CONFIG_USB_AIC_DMA_ENABLE + if (gint_status & INT_NP_TX_FIFO_EMPTY) { + AIC_UDC_REG->usbintmsk &= ~(INT_NP_TX_FIFO_EMPTY); + aic_tx_fifo_empty_procecss(0); + } +#endif + + if (gint_status & INT_IN_EP) { + ep_idx = 0U; + ep_intr = aic_get_ineps_intstatus(); + while (ep_intr != 0U) { + if ((ep_intr & 0x1U) != 0U) { + epint = aic_get_inep_intstatus(ep_idx); + uint32_t DiepintReg = AIC_UDC_REG->inepint[ep_idx]; + AIC_UDC_REG->inepint[ep_idx] = DiepintReg; + + if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { + if (ep_idx == 0) { + g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + g_aic_udc.in_ep[ep_idx].xfer_len = 0; + usbd_event_ep_in_complete_handler(0, 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len); + + if (g_aic_udc.setup.wLength && ((g_aic_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) { + /* In status, start reading setup */ + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } else if (g_aic_udc.setup.wLength == 0) { + /* In status, start reading setup */ + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } + } else { + g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + g_aic_udc.in_ep[ep_idx].xfer_len = 0; + usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len); + } + } + + #ifndef CONFIG_USB_AIC_DMA_ENABLE + if ((epint & INTKN_TXFEMP) == INTKN_TXFEMP) { + aic_tx_fifo_empty_procecss(ep_idx); + } + #endif + } + ep_intr >>= 1U; + ep_idx++; + } + } + if (gint_status & INT_RESET) { + AIC_UDC_REG->usbintsts |= INT_RESET; + AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_RMTWKUPSIG; + + usb_dc_rst(); + } + + if (gint_status & INT_ENUMDONE) { + AIC_UDC_REG->usbintsts |= INT_ENUMDONE; + aic_set_turnaroundtime(usbd_clk, aic_get_devspeed()); + + AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK; + } + if (gint_status & INT_INCOMP_ISO_OUT_INT) { + daintmask = AIC_UDC_REG->usbepintmsk; + daintmask >>= 16; + + for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) { + if ((BIT(ep_idx) & ~daintmask) || (g_aic_udc.out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) + continue; + if (!(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_USBACTEP)) + continue; + + if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) { + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; + AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + } else { + AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID; + AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID; + } + } + + AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_OUT_INT; + } + + if (gint_status & INT_INCOMP_ISO_IN_INT) { + daintmask = AIC_UDC_REG->usbepintmsk; + daintmask >>= 16; + + for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) { + if (((BIT(ep_idx) & ~daintmask)) || (g_aic_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) + continue; + + if (!(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_USBACTEP)) + continue; + + if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) { + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; + AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + } else { + AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID; + AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID; + } + } + AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_IN_INT; + } + + if (gint_status & INT_SOF) { + AIC_UDC_REG->usbintsts |= INT_SOF; + } + if (gint_status & INT_SUSPEND) { + AIC_UDC_REG->usbintsts |= INT_SUSPEND; + } + if (gint_status & INT_RESUME) { + AIC_UDC_REG->usbintsts |= INT_RESUME; + } +} diff --git a/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c new file mode 100644 index 0000000000..d2db1b5d66 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_ll.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, Artinchip Technology Co., Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#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); +} + diff --git a/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h new file mode 100644 index 0000000000..80e6997ac9 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/aic/usb_dc_aic_reg.h @@ -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 diff --git a/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c b/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c new file mode 100644 index 0000000000..1ccdfe3ea3 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_dc.c @@ -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; + } +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h b/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h new file mode 100644 index 0000000000..29ed6db0e5 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ch32/ch585_usbhs_reg.h @@ -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; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c b/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c new file mode 100644 index 0000000000..5771efb637 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_dc_usbfs.c @@ -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; + } +} diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h b/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h new file mode 100644 index 0000000000..f7fda8c62f --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ch32/usb_ch58x_usbfs_reg.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#define __IO volatile +#include + +#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 diff --git a/components/drivers/usb/cherryusb/port/dwc2/README.md b/components/drivers/usb/cherryusb/port/dwc2/README.md index 3218b31cd5..b35a7a038e 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/README.md +++ b/components/drivers/usb/cherryusb/port/dwc2/README.md @@ -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 diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c index 76abb19ea4..9b62db4e60 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_esp.c @@ -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" diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c index 4dff31f83f..51838091e5 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c @@ -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 diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c index 09f55170a5..de053cd0cd 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c @@ -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; diff --git a/components/drivers/usb/cherryusb/port/ehci/README.md b/components/drivers/usb/cherryusb/port/ehci/README.md index 8160c65d37..ede4cab812 100644 --- a/components/drivers/usb/cherryusb/port/ehci/README.md +++ b/components/drivers/usb/cherryusb/port/ehci/README.md @@ -12,7 +12,7 @@ ### AllwinnerTech -- F133 +- F133/T113 ### Nuvoton diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c new file mode 100644 index 0000000000..99927acbcc --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_t113.c @@ -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 +#include + +INIT_ENV_EXPORT(__usbh_init); + +#endif diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c index 4f61854a33..b40d60d553 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c @@ -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 */ diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h index 714128bc46..8d08cfa19a 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h +++ b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.h @@ -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 { diff --git a/components/drivers/usb/cherryusb/port/fsdev/README.md b/components/drivers/usb/cherryusb/port/fsdev/README.md index ecb9c33c11..95e9ac2e1c 100644 --- a/components/drivers/usb/cherryusb/port/fsdev/README.md +++ b/components/drivers/usb/cherryusb/port/fsdev/README.md @@ -23,10 +23,7 @@ ## GD32 -- GD32F10X_MD、GD32F10X_HD、GD32F10X_XD -- GD32F30X_HD、GD32F30X_XD -- GD32F350 -- GD32F407 +- GD32F10X ## CH32 diff --git a/components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c b/components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c index 39c787f8ab..c32a3b1729 100644 --- a/components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c +++ b/components/drivers/usb/cherryusb/port/musb/usb_hc_musb.c @@ -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); diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h index 19d5190966..1b3220073a 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h +++ b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h @@ -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]; diff --git a/components/drivers/usb/cherryusb/port/rp2040/README.md b/components/drivers/usb/cherryusb/port/rp2040/README.md new file mode 100644 index 0000000000..64887e36e5 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/rp2040/README.md @@ -0,0 +1,5 @@ +# Note + +## Support Chip List + +- RP2040/RP2350 \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c b/components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c new file mode 100644 index 0000000000..418bcd040b --- /dev/null +++ b/components/drivers/usb/cherryusb/port/rp2040/usb_dc_rp2040.c @@ -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); +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c b/components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c new file mode 100644 index 0000000000..90ac9b99be --- /dev/null +++ b/components/drivers/usb/cherryusb/port/rp2040/usb_hc_rp2040.c @@ -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); +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/template/usb_dc.c b/components/drivers/usb/cherryusb/port/template/usb_dc.c new file mode 100644 index 0000000000..516b32ff4d --- /dev/null +++ b/components/drivers/usb/cherryusb/port/template/usb_dc.c @@ -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) +{ +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/template/usb_hc.c b/components/drivers/usb/cherryusb/port/template/usb_hc.c new file mode 100644 index 0000000000..1de1cd5047 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/template/usb_hc.c @@ -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) +{ +} \ No newline at end of file