diff --git a/components/drivers/usb/cherryusb/CherryUSB.svg b/components/drivers/usb/cherryusb/CherryUSB.svg index c1ed4782122..91de329f8d8 100644 --- a/components/drivers/usb/cherryusb/CherryUSB.svg +++ b/components/drivers/usb/cherryusb/CherryUSB.svg @@ -1,3 +1,3 @@ -
CherryUSB
CherryUSB
Hardware
Hardware
BL
BL
DWC2
DWC2
OHCI
OHCI
EHCI
EHCI
XHCI
XHCI
MUSB
MUSB
FSDEV
FSDEV
HPM
HPM
Device Controller Driver (DCD)
Device Controller Driver (DCD)
Host Controller Driver (HCD)
Host Controller Driver (HCD)
OS Abstraction Layer (OSAL)
OS Abstraction Layer (OSAL)
USB Host
USB Host
USB Host Core
USB Host Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
HUB
HUB
USB Device
USB Device
USB Device Core
USB Device Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
DFU
DFU
optional
optional
required
required
Text is not SVG - cannot display
\ No newline at end of file +
CherryUSB
CherryUSB
Hardware
Hardware
CDNS3
CDNS3
CHIPIDEA
CHIPIDEA
XHCI
XHCI
EHCI
EHCI
OHCI
OHCI
DWC2
DWC2
MUSB
MUSB
FOTG
FOTG
Device Controller Driver (DCD)
Device Controller Driver (DCD)
Host Controller Driver (HCD)
Host Controller Driver (HCD)
OS Abstraction Layer (OSAL)
OS Abstraction Layer (OSAL)
USB Host
USB Host
USB Host Core
USB Host Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
HUB
HUB
USB Device
USB Device
USB Device Core
USB Device Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
DFU
DFU
optional
optional
required
required
\ No newline at end of file diff --git a/components/drivers/usb/cherryusb/Kconfig b/components/drivers/usb/cherryusb/Kconfig index 6f6789d0029..67c6ad543a1 100644 --- a/components/drivers/usb/cherryusb/Kconfig +++ b/components/drivers/usb/cherryusb/Kconfig @@ -38,6 +38,8 @@ if RT_USING_CHERRYUSB bool "dwc2_gd" config RT_CHERRYUSB_DEVICE_DWC2_HC bool "dwc2_hc" + config RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE + bool "dwc2_kendryte" config RT_CHERRYUSB_DEVICE_DWC2_CUSTOM bool "dwc2_custom" config RT_CHERRYUSB_DEVICE_MUSB_ES @@ -182,6 +184,8 @@ if RT_USING_CHERRYUSB bool "dwc2_st" config RT_CHERRYUSB_HOST_DWC2_ESP bool "dwc2_esp" + config RT_CHERRYUSB_HOST_DWC2_KENDRYTE + bool "dwc2_kendryte" config RT_CHERRYUSB_HOST_DWC2_CUSTOM bool "dwc2_custom" config RT_CHERRYUSB_HOST_MUSB_ES diff --git a/components/drivers/usb/cherryusb/README.md b/components/drivers/usb/cherryusb/README.md index bbea73f2f46..e56946a7722 100644 --- a/components/drivers/usb/cherryusb/README.md +++ b/components/drivers/usb/cherryusb/README.md @@ -1,6 +1,16 @@ -# CherryUSB - -[中文版](./README_zh.md) +

CherryUSB

+

+ + + + +

+ +

+ 中文 + | + English +

CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP. @@ -103,6 +113,7 @@ CherryUSB Host Stack has the following functions: - Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm) - Support Vendor class (serial, net, wifi) - Support USB modeswitch +- Support Android Open Accessory - Support multi host with the same USB IP The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin. @@ -149,7 +160,7 @@ Only standard and commercial USB IP are listed. | IP | device | host | Support status | |:----------------:|:----------:|:--------:|:--------------:| -| OHCI(intel) | none | OHCI | × | +| OHCI(intel) | none | OHCI | √ | | EHCI(intel) | none | EHCI | √ | | XHCI(intel) | none | XHCI | √ | | UHCI(intel) | none | UHCI | × | @@ -186,6 +197,7 @@ 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 | |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 | @@ -212,4 +224,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8. Thanks to the following companies for their support (in no particular order). - + diff --git a/components/drivers/usb/cherryusb/README_zh.md b/components/drivers/usb/cherryusb/README_zh.md index 1e8b54398ee..50d2b6f672b 100644 --- a/components/drivers/usb/cherryusb/README_zh.md +++ b/components/drivers/usb/cherryusb/README_zh.md @@ -1,6 +1,16 @@ -# CherryUSB - -[English](./README.md) +

CherryUSB

+

+ + + + +

+ +

+ 中文 + | + English +

CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。 @@ -103,6 +113,7 @@ CherryUSB Host 协议栈当前实现以下功能: - 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能) - 支持 Vendor 类 class (serial, net, wifi) - 支持 USB modeswitch +- 支持 Android Open Accessory - 支持相同 USB IP 的多主机 同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。 @@ -149,7 +160,7 @@ x 受以下宏影响: | IP | device | host | Support status | |:----------------:|:----------:|:--------:|:--------------:| -| OHCI(intel) | none | OHCI | × | +| OHCI(intel) | none | OHCI | √ | | EHCI(intel) | none | EHCI | √ | | XHCI(intel) | none | XHCI | √ | | UHCI(intel) | none | UHCI | × | @@ -187,6 +198,7 @@ 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 | |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 | @@ -214,4 +226,4 @@ CherryUSB 微信群:与我联系后邀请加入 感谢以下企业支持(顺序不分先后)。 - + diff --git a/components/drivers/usb/cherryusb/SConscript b/components/drivers/usb/cherryusb/SConscript index e8e69705b00..58d0aa01c2c 100644 --- a/components/drivers/usb/cherryusb/SConscript +++ b/components/drivers/usb/cherryusb/SConscript @@ -45,6 +45,9 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']): if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_HC']): src += Glob('port/dwc2/usb_dc_dwc2.c') src += Glob('port/dwc2/usb_glue_hc.c') + if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE']): + src += Glob('port/dwc2/usb_dc_dwc2.c') + src += Glob('port/dwc2/usb_glue_kendryte.c') if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_CUSTOM']): src += Glob('port/dwc2/usb_dc_dwc2.c') if GetDepend(['RT_CHERRYUSB_DEVICE_MUSB_ES']): @@ -177,6 +180,9 @@ if GetDepend(['RT_CHERRYUSB_HOST']): if GetDepend(['RT_CHERRYUSB_HOST_DWC2_ESP']): src += Glob('port/dwc2/usb_hc_dwc2.c') src += Glob('port/dwc2/usb_glue_esp.c') + if GetDepend(['RT_CHERRYUSB_HOST_DWC2_KENDRYTE']): + src += Glob('port/dwc2/usb_hc_dwc2.c') + src += Glob('port/dwc2/usb_glue_kendryte.c') if GetDepend(['RT_CHERRYUSB_HOST_DWC2_CUSTOM']): src += Glob('port/dwc2/usb_hc_dwc2.c') if GetDepend(['RT_CHERRYUSB_HOST_MUSB_STANDARD']): diff --git a/components/drivers/usb/cherryusb/VERSION b/components/drivers/usb/cherryusb/VERSION index 82894229cf1..340d4aefcd5 100644 --- a/components/drivers/usb/cherryusb/VERSION +++ b/components/drivers/usb/cherryusb/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 1 VERSION_MINOR = 4 -PATCHLEVEL = 1 +PATCHLEVEL = 2 VERSION_TWEAK = 0 EXTRAVERSION = 0 diff --git a/components/drivers/usb/cherryusb/cherryusb.cmake b/components/drivers/usb/cherryusb/cherryusb.cmake index 81e4f8262c0..271717008ca 100644 --- a/components/drivers/usb/cherryusb/cherryusb.cmake +++ b/components/drivers/usb/cherryusb/cherryusb.cmake @@ -40,6 +40,7 @@ ${CMAKE_CURRENT_LIST_DIR}/class/adb ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi +${CMAKE_CURRENT_LIST_DIR}/class/aoa ) if(CONFIG_CHERRYUSB_DEVICE) @@ -218,6 +219,9 @@ if(CONFIG_CHERRYUSB_HOST) if(CONFIG_CHERRYUSB_HOST_BL616) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c) endif() + if(CONFIG_CHERRYUSB_HOST_AOA) + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c) + endif() if(DEFINED CONFIG_CHERRYUSB_HOST_HCD) if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo") @@ -294,4 +298,9 @@ endif() if(CONFIG_CHERRYMP) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c) list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp) + if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos") + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c) + elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread") + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c) + endif() endif() \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/cherryusb_config_template.h b/components/drivers/usb/cherryusb/cherryusb_config_template.h index 30869b437a1..e7d5230f1c5 100644 --- a/components/drivers/usb/cherryusb/cherryusb_config_template.h +++ b/components/drivers/usb/cherryusb/cherryusb_config_template.h @@ -208,6 +208,9 @@ #define CONFIG_USBDEV_EP_NUM 8 #endif +/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */ +// #define CONFIG_USB_HS + /* ---------------- FSDEV Configuration ---------------- */ //#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference diff --git a/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h b/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h new file mode 100644 index 00000000000..6b6c715c2a6 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USB_AOA_H +#define USB_AOA_H + +//AOA 1.0 +#define AOA_ACCESSORY_VENDOR_ID 0x18D1 +#define AOA_ACCESSORY_PRODUCT_ID 0x2D00 +#define AOA_ACCESSORY_ADB_PRODUCT_ID 0x2D01 + +//AOA 2.0 +#define AOA_AUDIO_PRODUCT_ID 0x2D02 +#define AOA_AUDIO_ADB_PRODUCT_ID 0x2D03 +#define AOA_ACCESSORY_AUDIO_PRODUCT_ID 0x2D04 +#define AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID 0x2D05 + +//AOA 1.0 +#define AOA_ACCESSORY_GET_PROTOCOL 51 +#define AOA_ACCESSORY_SEND_STRING 52 +#define AOA_ACCESSORY_START 53 + +//AOA 2.0 +#define AOA_ACCESSORY_REGISTER_HID 54 +#define AOA_ACCESSORY_UNREGISTER_HID 55 +#define AOA_ACCESSORY_SET_HID_REPORT_DESC 56 +#define AOA_ACCESSORY_SEND_HID_EVENT 57 +#define AOA_ACCESSORY_SET_AUDIO_MODE 58 + +#define AOA_ACCESSORY_STRING_MANUFACTURER 0 +#define AOA_ACCESSORY_STRING_MODEL 1 +#define AOA_ACCESSORY_STRING_DESCRIPTION 2 +#define AOA_ACCESSORY_STRING_VERSION 3 +#define AOA_ACCESSORY_STRING_URI 4 +#define AOA_ACCESSORY_STRING_SERIAL 5 + +struct aoa_string_info { + char acc_manufacturer[64]; + char acc_model[64]; + char acc_description[64]; + char acc_version[64]; + char acc_uri[64]; + char acc_serial[64]; +}; + +#endif /* USB_AOA_H */ \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c new file mode 100644 index 00000000000..20cef52cf31 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_aoa.h" + +#undef USB_DBG_TAG +#define USB_DBG_TAG "usbh_aoa" +#include "usb_log.h" + +#define DEV_FORMAT "/dev/aoa" + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_aoa_buffer[128]; + +static struct usbh_aoa g_aoa_class; + +int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info) +{ + struct usb_setup_packet *setup; + int ret; + + setup = hport->setup; + + if (setup == NULL) { + return -USB_ERR_INVAL; + } + + USB_LOG_INFO("Try switch into aoa mode\r\n"); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_GET_PROTOCOL; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 2; + + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("AOA version: v%d.%d\r\n", g_aoa_buffer[0], g_aoa_buffer[1]); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_MANUFACTURER; + setup->wLength = strlen(info->acc_manufacturer) + 1; + + memcpy(g_aoa_buffer, info->acc_manufacturer, strlen(info->acc_manufacturer)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_MODEL; + setup->wLength = strlen(info->acc_model) + 1; + + memcpy(g_aoa_buffer, info->acc_model, strlen(info->acc_model)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_DESCRIPTION; + setup->wLength = strlen(info->acc_description) + 1; + + memcpy(g_aoa_buffer, info->acc_description, strlen(info->acc_description)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_VERSION; + setup->wLength = strlen(info->acc_version) + 1; + + memcpy(g_aoa_buffer, info->acc_version, strlen(info->acc_version)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_URI; + setup->wLength = strlen(info->acc_uri) + 1; + + memcpy(g_aoa_buffer, info->acc_uri, strlen(info->acc_uri)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_SERIAL; + setup->wLength = strlen(info->acc_serial) + 1; + + memcpy(g_aoa_buffer, info->acc_serial, strlen(info->acc_serial)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_START; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 0; + + ret = usbh_control_transfer(hport, setup, NULL); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("Switch into aoa mode success, wait usb device restart...\r\n"); + return 0; +} + +int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len) +{ + struct usb_setup_packet *setup; + int ret; + uint8_t len; + uint32_t offset; + + if (!aoa_class || !aoa_class->hport) { + return -USB_ERR_INVAL; + } + setup = aoa_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_REGISTER_HID; + setup->wValue = id; + setup->wIndex = report_len; + setup->wLength = 0; + + ret = usbh_control_transfer(aoa_class->hport, setup, NULL); + if (ret < 0) { + return ret; + } + + offset = 0; + while (report_len > 0) { + len = report_len > 64 ? 64 : report_len; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SET_HID_REPORT_DESC; + setup->wValue = id; + setup->wIndex = offset; + setup->wLength = len; + + memcpy(g_aoa_buffer, report + offset, len); + ret = usbh_control_transfer(aoa_class->hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + offset += len; + report_len -= len; + } + return ret; +} + +int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len) +{ + struct usb_setup_packet *setup; + int ret; + uint8_t len; + uint32_t offset; + + if (!aoa_class || !aoa_class->hport) { + return -USB_ERR_INVAL; + } + setup = aoa_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_HID_EVENT; + setup->wValue = id; + setup->wIndex = 0; + setup->wLength = event_len; + + memcpy(g_aoa_buffer, event, event_len); + return usbh_control_transfer(aoa_class->hport, setup, event); +} + +static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + struct usbh_aoa *aoa_class = &g_aoa_class; + + memset(aoa_class, 0, sizeof(struct usbh_aoa)); + + aoa_class->hport = hport; + aoa_class->intf = intf; + + hport->config.intf[intf].priv = aoa_class; + + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(aoa_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(aoa_class->bulkout, ep_desc); + } + } + + strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN); + + USB_LOG_INFO("Register AOA Class:%s\r\n", hport->config.intf[intf].devname); + + usbh_aoa_run(aoa_class); + return 0; +} + +static int usbh_aoa_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_aoa *aoa_class = (struct usbh_aoa *)hport->config.intf[intf].priv; + + if (aoa_class) { + if (aoa_class->bulkin) { + usbh_kill_urb(&aoa_class->bulkin_urb); + } + + if (aoa_class->bulkout) { + usbh_kill_urb(&aoa_class->bulkout_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister AOA Class:%s\r\n", hport->config.intf[intf].devname); + usbh_aoa_stop(aoa_class); + } + + memset(aoa_class, 0, sizeof(struct usbh_aoa)); + } + + return ret; +} + +__WEAK void usbh_aoa_run(struct usbh_aoa *aoa_class) +{ + (void)aoa_class; +} + +__WEAK void usbh_aoa_stop(struct usbh_aoa *aoa_class) +{ + (void)aoa_class; +} + +static const uint16_t aoa_id_table[][2] = { + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_ADB_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_ADB_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID }, + { 0, 0 }, +}; + +const struct usbh_class_driver aoa_class_driver = { + .driver_name = "aoa", + .connect = usbh_aoa_connect, + .disconnect = usbh_aoa_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info aoa_intf_class_info = { + .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0x00, + .id_table = aoa_id_table, + .class_driver = &aoa_class_driver +}; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h new file mode 100644 index 00000000000..3b184e8b980 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_AOA_H +#define USBH_AOA_H + +#include "usb_aoa.h" + +struct usbh_aoa { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + + uint8_t intf; + uint8_t minor; + + void *user_data; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info); +int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len); +int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len); + +void usbh_aoa_run(struct usbh_aoa *aoa_class); +void usbh_aoa_stop(struct usbh_aoa *aoa_class); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_AOA_H */ \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/audio/usb_audio.h b/components/drivers/usb/cherryusb/class/audio/usb_audio.h index 1aced20ff4f..ff7a9fe2a95 100644 --- a/components/drivers/usb/cherryusb/class/audio/usb_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usb_audio.h @@ -648,6 +648,18 @@ struct audio_cs_if_ac_feature_unit_descriptor { #define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n) +struct audio_cs_if_ac_selector_unit_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bUnitID; + uint8_t bNrInPins; + uint8_t baSourceID[1]; + uint8_t iSelector; +} __PACKED; + +#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n) + struct audio_cs_if_as_general_descriptor { uint8_t bLength; uint8_t bDescriptorType; diff --git a/components/drivers/usb/cherryusb/class/audio/usbd_audio.c b/components/drivers/usb/cherryusb/class/audio/usbd_audio.c index 4ff3767abff..458f1c191f7 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbd_audio.c +++ b/components/drivers/usb/cherryusb/class/audio/usbd_audio.c @@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup memcpy(&volume, *data, *len); if (volume < 0x8000) { volume_db = volume / 256; - } else if (volume > 0x8000) { - volume_db = (0xffff - volume + 1) / -256; + } else { + volume_db = (volume - 0x10000) / 256; } - volume_db += 128; /* 0 ~ 255 */ - USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume); + USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db); break; case AUDIO_REQUEST_GET_CUR: volume_db = usbd_audio_get_volume(busid, ep, ch); - volume_db -= 128; if (volume_db >= 0) { volume = volume_db * 256; } else { - volume = volume_db * 256 + 0xffff + 1; + volume = volume_db * 256 + 0x10000; } + USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); memcpy(*data, &volume, 2); *len = 2; break; case AUDIO_REQUEST_GET_MIN: - (*data)[0] = 0x00; /* -2560/256 dB */ - (*data)[1] = 0xdb; + (*data)[0] = 0x00; /* -100 dB */ + (*data)[1] = 0x9c; *len = 2; break; case AUDIO_REQUEST_GET_MAX: @@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup *len = 2; break; case AUDIO_REQUEST_GET_RES: - (*data)[0] = 0x00; /* -256/256 dB */ + (*data)[0] = 0x00; /* 1 dB */ (*data)[1] = 0x01; *len = 2; break; @@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup case AUDIO_REQUEST_CUR: if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { volume_db = usbd_audio_get_volume(busid, ep, ch); - volume = volume_db; + if (volume_db >= 0) { + volume = volume_db * 256; + } else { + volume = volume_db * 256 + 0x10000; + } + USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); memcpy(*data, &volume, 2); *len = 2; } else { memcpy(&volume, *data, *len); - volume_db = volume; - USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume); + if (volume < 0x8000) { + volume_db = volume / 256; + } else { + volume_db = (volume - 0x10000) / 256; + } + USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db); } break; case AUDIO_REQUEST_RANGE: if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { *((uint16_t *)(*data + 0)) = 1; - *((uint16_t *)(*data + 2)) = 0; - *((uint16_t *)(*data + 4)) = 100; - *((uint16_t *)(*data + 6)) = 1; + *((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */ + *((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */ + *((uint16_t *)(*data + 6)) = 0x100; /* RES 1 dB */ *len = 8; } else { } @@ -312,12 +320,12 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, return intf; } -__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume) +__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db) { (void)busid; (void)ep; (void)ch; - (void)volume; + (void)volume_db; } __WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch) diff --git a/components/drivers/usb/cherryusb/class/audio/usbd_audio.h b/components/drivers/usb/cherryusb/class/audio/usbd_audio.h index 442405a2f97..75a0b17dcda 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbd_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usbd_audio.h @@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface void usbd_audio_open(uint8_t busid, uint8_t intf); void usbd_audio_close(uint8_t busid, uint8_t intf); -void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume); +void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db); int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch); void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute); bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch); diff --git a/components/drivers/usb/cherryusb/class/audio/usbh_audio.c b/components/drivers/usb/cherryusb/class/audio/usbh_audio.c index 9e838bbae0f..6d8b4559e10 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbh_audio.c +++ b/components/drivers/usb/cherryusb/class/audio/usbh_audio.c @@ -184,18 +184,21 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name) return ret; } -int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume) +int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db) { struct usb_setup_packet *setup; int ret; uint8_t feature_id = 0xff; + uint8_t intf; uint16_t volume_hex; + int volume_min_db; + int volume_max_db; if (!audio_class || !audio_class->hport) { return -USB_ERR_INVAL; } - if (volume > 100) { + if ((volume_db > 127) || (volume_db < -127)) { return -USB_ERR_INVAL; } @@ -204,20 +207,102 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) { feature_id = audio_class->as_msg_table[i].feature_terminal_id; + intf = audio_class->as_msg_table[i].stream_intf; } } + if (feature_id == 0xff) { + return -USB_ERR_NODEV; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_CUR; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_MIN; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_MAX; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_RES; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2); + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = AUDIO_REQUEST_SET_CUR; setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; setup->wLength = 2; - volume_hex = -0xDB00 / 100 * volume + 0xdb00; + if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) { + volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256; + } else { + volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256; + } + + if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) { + volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256; + } else { + volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256; + } - memcpy(g_audio_buf, &volume_hex, 2); - ret = usbh_control_transfer(audio_class->hport, setup, NULL); + USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db); + if (volume_db >= 0) { + volume_hex = volume_db * 256; + if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) { + return -USB_ERR_RANGE; + } + } else { + volume_hex = volume_db * 256 + 0x10000; + if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) { + return -USB_ERR_RANGE; + } + } + + memcpy(g_audio_buf, &volume_hex, 2); + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex; return ret; } @@ -226,6 +311,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ struct usb_setup_packet *setup; int ret; uint8_t feature_id = 0xff; + uint8_t intf = 0xff; if (!audio_class || !audio_class->hport) { return -USB_ERR_INVAL; @@ -235,9 +321,14 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) { feature_id = audio_class->as_msg_table[i].feature_terminal_id; + intf = audio_class->as_msg_table[i].stream_intf; } } + if (feature_id == 0xff) { + return -USB_ERR_NODEV; + } + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = AUDIO_REQUEST_SET_CUR; setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch; @@ -246,7 +337,10 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ memcpy(g_audio_buf, &mute, 1); ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - + if (ret < 0) { + return ret; + } + audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute; return ret; } @@ -286,13 +380,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class) static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) { int ret; - uint8_t cur_iface = 0xff; - uint8_t cur_iface_count = 0xff; - uint8_t cur_alt_setting = 0xff; + uint8_t cur_iface = 0; + uint8_t cur_iface_count = 0; + uint8_t cur_alt_setting = 0; uint8_t input_offset = 0; uint8_t output_offset = 0; uint8_t feature_unit_offset = 0; uint8_t *p; + struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; struct usbh_audio *audio_class = usbh_audio_class_alloc(); if (audio_class == NULL) { @@ -327,26 +422,24 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) case AUDIO_CONTROL_INPUT_TERMINAL: { struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p; - memcpy(&audio_class->ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor)); + memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor)); input_offset++; } break; case AUDIO_CONTROL_OUTPUT_TERMINAL: { struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p; - memcpy(&audio_class->ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor)); + memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor)); output_offset++; } break; case AUDIO_CONTROL_FEATURE_UNIT: { struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p; - memcpy(&audio_class->ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength); + memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength); feature_unit_offset++; } break; - case AUDIO_CONTROL_PROCESSING_UNIT: - - break; default: - break; + USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]); + return -USB_ERR_NOTSUPP; } } else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) { switch (p[DESC_bDescriptorSubType]) { @@ -383,7 +476,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) } if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) { - USB_LOG_ERR("Audio descriptor is invalid\r\n"); + USB_LOG_ERR("Audio control descriptor is invalid\r\n"); + return -USB_ERR_INVAL; + } + + if (cur_iface_count == 0xff) { + USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n"); return -USB_ERR_INVAL; } @@ -392,21 +490,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { /* Search 0x0101 in input or output desc */ for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) { - if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_input.bTerminalID) { + if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) { /* INPUT --> FEATURE UNIT --> OUTPUT */ - audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[streamidx].ac_input.bTerminalID; + audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID; /* Search input terminal id in feature desc */ for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) { - if (audio_class->ac_msg_table[streamidx].ac_input.bTerminalID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID) { - audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID; + if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) { + audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID; /* Search feature unit id in output desc */ for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) { - if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID == audio_class->ac_msg_table[outputid].ac_output.bSourceID) { - audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[outputid].ac_output.bTerminalID; + if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) { + audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID; - switch (audio_class->ac_msg_table[outputid].ac_output.wTerminalType) { + switch (ac_msg_table[outputid].ac_output.wTerminalType) { case AUDIO_OUTTERM_SPEAKER: audio_class->as_msg_table[i].stream_name = "speaker"; break; @@ -426,21 +524,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) break; } } - } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_output.bTerminalID) { + } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) { /* OUTPUT --> FEATURE UNIT --> INPUT */ - audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[streamidx].ac_output.bTerminalID; + audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID; /* Search output terminal id in feature desc */ for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) { - if (audio_class->ac_msg_table[streamidx].ac_output.bSourceID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID) { - audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID; + if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) { + audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID; /* Search feature unit id in input desc */ for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) { - if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID == audio_class->ac_msg_table[inputid].ac_input.bTerminalID) { - audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[inputid].ac_input.bTerminalID; + if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) { + audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID; - switch (audio_class->ac_msg_table[inputid].ac_input.wTerminalType) { + switch (ac_msg_table[inputid].ac_input.wTerminalType) { case AUDIO_INTERM_MIC: audio_class->as_msg_table[i].stream_name = "mic"; break; @@ -458,6 +556,13 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) } } + for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { + if (audio_class->as_msg_table[i].stream_name == NULL) { + USB_LOG_ERR("Audio stream search fail\r\n"); + return -USB_ERR_NODEV; + } + } + for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name); if (ret < 0) { @@ -537,18 +642,18 @@ const struct usbh_class_driver audio_streaming_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_AUDIOCONTROL, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &audio_ctrl_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_AUDIOSTREAMING, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &audio_streaming_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/audio/usbh_audio.h b/components/drivers/usb/cherryusb/class/audio/usbh_audio.h index d6eeeffb020..2e583ac0be5 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbh_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usbh_audio.h @@ -26,6 +26,11 @@ struct usbh_audio_as_msg { uint8_t output_terminal_id; uint8_t ep_attr; uint8_t num_of_altsetting; + uint16_t volume_min; + uint16_t volume_max; + uint16_t volume_res; + uint16_t volume_cur; + bool mute; struct audio_cs_if_as_general_descriptor as_general; struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS]; }; @@ -43,7 +48,6 @@ struct usbh_audio { uint16_t bcdADC; uint8_t bInCollection; uint8_t stream_intf_num; - struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; void *user_data; @@ -55,7 +59,7 @@ extern "C" { int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution); int usbh_audio_close(struct usbh_audio *audio_class, const char *name); -int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume); +int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db); int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute); void usbh_audio_run(struct usbh_audio *audio_class); diff --git a/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h b/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h index eb2b286269b..d1546eec575 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h +++ b/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h @@ -524,7 +524,7 @@ struct cdc_ncm_ndp16 { int_ep, /* bEndpointAddress */ \ 0x03, /* bmAttributes */ \ 0x08, 0x00, /* wMaxPacketSize */ \ - 0x10, /* bInterval */ \ + 0x05, /* bInterval */ \ 0x09, /* bLength */ \ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ @@ -596,7 +596,7 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) int_ep, /* bEndpointAddress */ \ 0x03, /* bmAttributes */ \ 0x10, 0x00, /* wMaxPacketSize */ \ - 0x10, /* bInterval */ \ + 0x05, /* bInterval */ \ 0x09, /* bLength */ \ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ diff --git a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c index 29e82ceeaee..5ae10a207c3 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c @@ -7,17 +7,21 @@ #include "usbd_cdc_ecm.h" #define CDC_ECM_OUT_EP_IDX 0 -#define CDC_ECM_IN_EP_IDX 1 -#define CDC_ECM_INT_EP_IDX 2 +#define CDC_ECM_IN_EP_IDX 1 +#define CDC_ECM_INT_EP_IDX 2 + +/* Ethernet Maximum Segment size, typically 1514 bytes */ +#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1536U /* Describe EndPoints configuration */ static struct usbd_endpoint cdc_ecm_ep_data[3]; +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; +#endif static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16]; -volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL; volatile uint32_t g_cdc_ecm_rx_data_length = 0; volatile uint32_t g_cdc_ecm_tx_data_length = 0; @@ -68,8 +72,10 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed break; } - if (bytes2send) { - usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send); + if (usb_device_is_configured(0)) { + if (bytes2send) { + usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send); + } } } @@ -93,11 +99,11 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set * bit3 Broadcast * bit4 Multicast */ - if (g_current_net_status == 0) { - g_current_net_status = 1; - usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL); - } - +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP + g_connect_speed_table[0] = 100000000; /* 100 Mbps */ + g_connect_speed_table[1] = 100000000; /* 100 Mbps */ + usbd_cdc_ecm_set_connect(true, g_connect_speed_table); +#endif break; default: USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest); @@ -117,10 +123,11 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg) g_current_net_status = 0; g_cdc_ecm_rx_data_length = 0; g_cdc_ecm_tx_data_length = 0; - g_cdc_ecm_rx_data_buffer = NULL; break; case USBD_EVENT_CONFIGURED: - usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr)); +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); +#endif break; default: @@ -132,14 +139,8 @@ void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) { (void)busid; - g_cdc_ecm_rx_data_length += nbytes; - - if (nbytes < usbd_get_ep_mps(0, ep)) { - g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer; - usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length); - } else { - usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep)); - } + g_cdc_ecm_rx_data_length = nbytes; + usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_data_length); } void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) @@ -150,6 +151,7 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) /* send zlp */ usbd_ep_start_write(0, ep, NULL, 0); } else { + usbd_cdc_ecm_data_send_done(g_cdc_ecm_tx_data_length); g_cdc_ecm_tx_data_length = 0; } } @@ -160,14 +162,20 @@ void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes) (void)ep; (void)nbytes; - if (g_current_net_status == 1) { - g_current_net_status = 2; - usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table); + if (g_current_net_status == 2) { + g_current_net_status = 3; + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE, 0, g_connect_speed_table); + } else { + g_current_net_status = 0; } } int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len) { + if (!usb_device_is_configured(0)) { + return -USB_ERR_NODEV; + } + if (g_cdc_ecm_tx_data_length > 0) { return -USB_ERR_BUSY; } @@ -175,14 +183,17 @@ int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len) g_cdc_ecm_tx_data_length = len; USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length); - return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length); + return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, len); } -void usbd_cdc_ecm_start_read_next(void) +int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len) { + if (!usb_device_is_configured(0)) { + return -USB_ERR_NODEV; + } + g_cdc_ecm_rx_data_length = 0; - g_cdc_ecm_rx_data_buffer = NULL; - usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, usbd_get_ep_mps(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr)); + return usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, buf, len); } #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP @@ -190,19 +201,19 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void) { struct pbuf *p; - if (g_cdc_ecm_rx_data_buffer == NULL) { + if (g_cdc_ecm_rx_data_length == 0) { return NULL; } p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL); if (p == NULL) { - usbd_cdc_ecm_start_read_next(); + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); return NULL; } usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length); p->len = g_cdc_ecm_rx_data_length; USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length); - usbd_cdc_ecm_start_read_next(); + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); return p; } @@ -250,13 +261,24 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const return intf; } -void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]) +void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]) +{ + if (connect) { + g_current_net_status = 2; + memcpy(g_connect_speed_table, speed, 8); + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL); + } else { + g_current_net_status = 1; + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_DISCONNECTED, NULL); + } +} + +__WEAK void usbd_cdc_ecm_data_recv_done(uint32_t len) { - memcpy(g_connect_speed_table, speed, 8); + (void)len; } -__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len) +__WEAK void usbd_cdc_ecm_data_send_done(uint32_t len) { - (void)buf; (void)len; } diff --git a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h index 8d9e5c9fe00..3e0284e3288 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h +++ b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h @@ -12,21 +12,15 @@ extern "C" { #endif -/* Ethernet Maximum Segment size, typically 1514 bytes */ -#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U - /* Init cdc ecm interface driver */ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep); -/* Setup request command callback api */ -void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]); +void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]); -/* Api for eth only without any net stack */ -uint8_t *usbd_cdc_ecm_get_tx_buffer(void); -void usbd_cdc_ecm_send_done(void); +void usbd_cdc_ecm_data_recv_done(uint32_t len); +void usbd_cdc_ecm_data_send_done(uint32_t len); int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len); -void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len); -void usbd_cdc_ecm_start_read_next(void); +int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len); #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP #include "lwip/netif.h" diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c index ceb5ad0c2dc..53666b32f03 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c @@ -267,18 +267,18 @@ const struct usbh_class_driver cdc_data_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_ABSTRACT_CONTROL_MODEL, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &cdc_acm_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_CDC_DATA, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &cdc_data_class_driver }; 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 76cfb41aa39..c4743e56d30 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c @@ -323,9 +323,9 @@ const struct usbh_class_driver cdc_ecm_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL, - .protocol = CDC_COMMON_PROTOCOL_NONE, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL, + .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE, .id_table = NULL, .class_driver = &cdc_ecm_class_driver }; \ No newline at end of file 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 094241aab58..f9f3c533819 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c @@ -403,9 +403,9 @@ const struct usbh_class_driver cdc_ncm_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_NETWORK_CONTROL_MODEL, - .protocol = CDC_COMMON_PROTOCOL_NONE, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL, + .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE, .id_table = NULL, .class_driver = &cdc_ncm_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/hid/usbh_hid.c b/components/drivers/usb/cherryusb/class/hid/usbh_hid.c index de1ddc07488..0fd58abb153 100644 --- a/components/drivers/usb/cherryusb/class/hid/usbh_hid.c +++ b/components/drivers/usb/cherryusb/class/hid/usbh_hid.c @@ -303,9 +303,9 @@ const struct usbh_class_driver hid_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_HID, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_HID, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &hid_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c index 2bcf4ddb48d..9dae3966075 100644 --- a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c +++ b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c @@ -734,9 +734,9 @@ const struct usbh_class_driver hub_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_HUB, - .subclass = 0, - .protocol = 0, + .bInterfaceClass = USB_DEVICE_CLASS_HUB, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, .id_table = NULL, .class_driver = &hub_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c index 1327175fce5..96cb53d2630 100644 --- a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c +++ b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c @@ -443,9 +443,9 @@ const struct usbh_class_driver msc_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_MASS_STORAGE, - .subclass = MSC_SUBCLASS_SCSI, - .protocol = MSC_PROTOCOL_BULK_ONLY, + .bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE, + .bInterfaceSubClass = MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY, .id_table = NULL, .class_driver = &msc_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/template/usbh_xxx.c b/components/drivers/usb/cherryusb/class/template/usbh_xxx.c index 78d531fc3cf..4456b3c4a1d 100644 --- a/components/drivers/usb/cherryusb/class/template/usbh_xxx.c +++ b/components/drivers/usb/cherryusb/class/template/usbh_xxx.c @@ -89,9 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = 0, - .subclass = 0, - .protocol = 0, + .bInterfaceClass = 0, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, .id_table = NULL, .class_driver = &xxx_class_driver }; 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 e8c7eb15378..66c1f078033 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c @@ -817,9 +817,9 @@ static const struct usbh_class_driver asix_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = asix_id_table, .class_driver = &asix_class_driver }; \ No newline at end of file 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 778ab264794..10fc0483982 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c @@ -2272,9 +2272,9 @@ static const struct usbh_class_driver rtl8152_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info rtl8152_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = rtl_id_table, .class_driver = &rtl8152_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c index d0de5b4cf2d..3bee462db81 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c @@ -370,9 +370,9 @@ const struct usbh_class_driver ch34x_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = ch34x_id_table, .class_driver = &ch34x_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c index 4cd06b95be4..6f41b41be37 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c @@ -319,9 +319,9 @@ const struct usbh_class_driver cp210x_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = cp210x_id_table, .class_driver = &cp210x_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c index 4ed698390c3..82defaab7fd 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c @@ -392,9 +392,9 @@ const struct usbh_class_driver ftdi_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = ftdi_id_table, .class_driver = &ftdi_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c index 42c963db4e1..01ee700fb83 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c @@ -440,9 +440,9 @@ const struct usbh_class_driver pl2303_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = pl2303_id_table, .class_driver = &pl2303_class_driver }; \ No newline at end of file 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 34cbcf87e4c..9275faacc63 100644 --- a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c +++ b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c @@ -504,9 +504,9 @@ static const struct usbh_class_driver bl616_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = bl616_id_table, .class_driver = &bl616_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c b/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c index ecfb4651901..0c3339c9fc5 100644 --- a/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c +++ b/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c @@ -220,9 +220,9 @@ static const uint16_t xbox_id_table[][2] = { CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VEND_SPECIFIC, - .subclass = 0x5d, - .protocol = 0x01, + .bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC, + .bInterfaceSubClass = 0x5d, + .bInterfaceProtocol = 0x01, .id_table = xbox_id_table, .class_driver = &xbox_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/video/usbd_video.c b/components/drivers/usb/cherryusb/class/video/usbd_video.c index a1a42cdcf1e..dae28eb544a 100644 --- a/components/drivers/usb/cherryusb/class/video/usbd_video.c +++ b/components/drivers/usb/cherryusb/class/video/usbd_video.c @@ -18,10 +18,20 @@ struct usbd_video_priv { uint8_t power_mode; uint8_t error_code; struct video_entity_info info[3]; - uint8_t *ep_buffer; + uint8_t *ep_buf0; + uint8_t *ep_buf1; + bool ep_buf0_ready; + bool ep_buf1_ready; + uint32_t ep_buf0_len; + uint32_t ep_buf1_len; + uint8_t ep_buf_idx; + bool stream_finish; + uint32_t max_packets; uint8_t *stream_buf; uint32_t stream_len; uint32_t stream_offset; + uint8_t stream_frameid; + uint32_t stream_headerlen; } g_usbd_video[CONFIG_USBDEV_MAX_BUS]; static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) @@ -741,6 +751,43 @@ static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dw g_usbd_video[busid].commit.bPreferedVersion = 0; g_usbd_video[busid].commit.bMinVersion = 0; g_usbd_video[busid].commit.bMaxVersion = 0; + + g_usbd_video[busid].stream_frameid = 0; + g_usbd_video[busid].stream_headerlen = 2; +} + +static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf) +{ + struct video_payload_header *header; + uint32_t len; + uint32_t offset; + + len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets); + offset = 0; + while (len > 0) { + header = (struct video_payload_header *)&ep_buf[offset]; + header->bHeaderLength = g_usbd_video[busid].stream_headerlen; + header->headerInfoUnion.bmheaderInfo = 0; + header->headerInfoUnion.headerInfoBits.endOfHeader = 1; + header->headerInfoUnion.headerInfoBits.endOfFrame = 0; + header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid; + + uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen); + + usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen], + &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset], + len2); + + g_usbd_video[busid].stream_offset += len2; + len -= len2; + offset += (len2 + g_usbd_video[busid].stream_headerlen); + + if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) { + header->headerInfoUnion.headerInfoBits.endOfFrame = 1; + } + } + + return offset; } struct usbd_interface *usbd_video_init_intf(uint8_t busid, @@ -770,74 +817,68 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep) { - struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer; uint32_t remain; - uint32_t len; - bool last_packet = false; - - header->bHeaderLength = 2; - header->headerInfoUnion.headerInfoBits.endOfHeader = 1; - remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset; - - len = MIN(remain, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - header->bHeaderLength); - memcpy(&g_usbd_video[busid].ep_buffer[header->bHeaderLength], - &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset], - len); + if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */ + g_usbd_video[busid].ep_buf0_ready = false; + g_usbd_video[busid].ep_buf_idx = 1; + usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len); + } else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */ + g_usbd_video[busid].ep_buf1_ready = false; + g_usbd_video[busid].ep_buf_idx = 0; + usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len); + } else { + if (g_usbd_video[busid].stream_finish) { + return true; + } + } - g_usbd_video[busid].stream_offset += len; + if (!g_usbd_video[busid].ep_buf0_ready) { + remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset; + if (remain == 0) { + g_usbd_video[busid].stream_frameid ^= 1; + g_usbd_video[busid].stream_finish = true; + } else { + g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0); + g_usbd_video[busid].ep_buf0_ready = true; + if (!g_usbd_video[busid].ep_buf1_ready) { + g_usbd_video[busid].ep_buf_idx = 0; + usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len); + } + } + } - if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) { - last_packet = true; - header->headerInfoUnion.headerInfoBits.endOfFrame = 1; + if (!g_usbd_video[busid].ep_buf1_ready) { + remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset; + if (remain == 0) { + g_usbd_video[busid].stream_frameid ^= 1; + g_usbd_video[busid].stream_finish = true; + } else { + g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1); + g_usbd_video[busid].ep_buf1_ready = true; + } } - usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buffer, len + header->bHeaderLength); - return last_packet; + return false; } -int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len) +int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len) { - if (usb_device_is_configured(busid) == 0) { + if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) { return -1; } - g_usbd_video[busid].ep_buffer = ep_buffer; - g_usbd_video[busid].stream_buf = buf; - g_usbd_video[busid].stream_len = len; + g_usbd_video[busid].ep_buf0 = ep_buf0; + g_usbd_video[busid].ep_buf1 = ep_buf1; + g_usbd_video[busid].ep_buf0_ready = false; + g_usbd_video[busid].ep_buf1_ready = false; + g_usbd_video[busid].ep_buf_idx = 0; + g_usbd_video[busid].stream_finish = false; + g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize; + g_usbd_video[busid].stream_buf = stream_buf; + g_usbd_video[busid].stream_len = stream_len; g_usbd_video[busid].stream_offset = 0; - struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer; - - header->headerInfoUnion.headerInfoBits.frameIdentifier ^= 1; - header->headerInfoUnion.headerInfoBits.endOfFrame = 0; - usbd_video_stream_split_transfer(busid, ep); return 0; } - -uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len) -{ - uint32_t packets; - uint32_t last_packet_size; - uint32_t picture_pos = 0; - static uint8_t uvc_header[2] = { 0x02, 0x80 }; - - packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2); - last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)); - - for (size_t i = 0; i < packets; i++) { - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0]; - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1]; - if (i == (packets - 1)) { - memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size); - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1); - } else { - memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2); - picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2; - } - } - uvc_header[1] ^= 1; - *out_len = (input_len + 2 * packets); - return packets; -} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/video/usbd_video.h b/components/drivers/usb/cherryusb/class/video/usbd_video.h index 24855c897d4..a2a98bb8c01 100644 --- a/components/drivers/usb/cherryusb/class/video/usbd_video.h +++ b/components/drivers/usb/cherryusb/class/video/usbd_video.h @@ -22,9 +22,7 @@ void usbd_video_open(uint8_t busid, uint8_t intf); void usbd_video_close(uint8_t busid, uint8_t intf); bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep); -int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len); - -uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len); +int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len); #ifdef __cplusplus } diff --git a/components/drivers/usb/cherryusb/class/video/usbh_video.c b/components/drivers/usb/cherryusb/class/video/usbh_video.c index 043eb1d6bde..7379151250d 100644 --- a/components/drivers/usb/cherryusb/class/video/usbh_video.c +++ b/components/drivers/usb/cherryusb/class/video/usbh_video.c @@ -531,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VIDEO, - .subclass = VIDEO_SC_VIDEOCONTROL, - .protocol = VIDEO_PC_PROTOCOL_UNDEFINED, + .bInterfaceClass = USB_DEVICE_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL, + .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED, .id_table = NULL, .class_driver = &video_ctrl_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VIDEO, - .subclass = VIDEO_SC_VIDEOSTREAMING, - .protocol = VIDEO_PC_PROTOCOL_UNDEFINED, + .bInterfaceClass = USB_DEVICE_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING, + .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED, .id_table = NULL, .class_driver = &video_streaming_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c index 61bcd290d13..43849706ea2 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c @@ -478,7 +478,7 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t); g_rndis_rx_data_length = hdr->DataLength; - usbd_rndis_data_recv_done(); + usbd_rndis_data_recv_done(g_rndis_rx_data_length); } void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) @@ -489,6 +489,7 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) /* send zlp */ usbd_ep_start_write(0, ep, NULL, 0); } else { + usbd_rndis_data_send_done(g_rndis_tx_data_length); g_rndis_tx_data_length = 0; } } @@ -592,3 +593,13 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf, return intf; } + +__WEAK void usbd_rndis_data_recv_done(uint32_t len) +{ + (void)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 8a9581f68d1..72b89eab890 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h @@ -18,7 +18,8 @@ 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_data_recv_done(void); +void usbd_rndis_data_recv_done(uint32_t len); +void usbd_rndis_data_send_done(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 9f78866ab5a..991f09579b3 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c @@ -393,18 +393,18 @@ static const uint16_t bluetooth_id_table[][2] = { CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = bluetooth_id_table, .class_driver = &bluetooth_class_driver }; #else CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_WIRELESS, - .subclass = 0x01, - .protocol = 0x01, + .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS, + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x01, .id_table = NULL, .class_driver = &bluetooth_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c index fa53f8400b0..e9eaff0114d 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c @@ -600,9 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_WIRELESS, - .subclass = 0x01, - .protocol = 0x03, + .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS, + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x03, .id_table = NULL, .class_driver = &rndis_class_driver }; diff --git a/components/drivers/usb/cherryusb/common/usb_log.h b/components/drivers/usb/cherryusb/common/usb_log.h index 9074ed9752b..8c798c7cb44 100644 --- a/components/drivers/usb/cherryusb/common/usb_log.h +++ b/components/drivers/usb/cherryusb/common/usb_log.h @@ -88,6 +88,8 @@ static inline void usb_hexdump(const void *ptr, uint32_t buflen) unsigned char *buf = (unsigned char *)ptr; uint32_t i, j; + (void)buf; + for (i = 0; i < buflen; i += 16) { CONFIG_USB_PRINTF("%08X:", i); diff --git a/components/drivers/usb/cherryusb/common/usb_version.h b/components/drivers/usb/cherryusb/common/usb_version.h index b68b8f69790..d207af9dc23 100644 --- a/components/drivers/usb/cherryusb/common/usb_version.h +++ b/components/drivers/usb/cherryusb/common/usb_version.h @@ -15,7 +15,7 @@ #undef CHERRYUSB_VERSION_STR #endif -#define CHERRYUSB_VERSION 0x010401 -#define CHERRYUSB_VERSION_STR "v1.4.1" +#define CHERRYUSB_VERSION 0x010402 +#define CHERRYUSB_VERSION_STR "v1.4.2" #endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/core/usbd_core.c b/components/drivers/usb/cherryusb/core/usbd_core.c index ea471e54985..d7fb351775f 100644 --- a/components/drivers/usb/cherryusb/core/usbd_core.c +++ b/components/drivers/usb/cherryusb/core/usbd_core.c @@ -64,6 +64,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv { bool test_req; #endif struct usbd_interface *intf[16]; + uint8_t intf_altsetting[16]; uint8_t intf_offset; struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM]; @@ -98,6 +99,7 @@ static bool is_device_configured(uint8_t busid) * This function sets endpoint configuration according to one specified in USB * endpoint descriptor and then enables it for data transfers. * + * @param [in] busid busid * @param [in] ep Endpoint descriptor byte array * * @return true if successfully configured and enabled @@ -125,6 +127,7 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto * This function cancels transfers that are associated with endpoint and * disabled endpoint itself. * + * @param [in] busid busid * @param [in] ep Endpoint descriptor byte array * * @return true if successfully deconfigured and disabled @@ -144,6 +147,7 @@ static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descrip * This function parses the list of installed USB descriptors and attempts * to find the specified USB descriptor. * + * @param [in] busid busid * @param [in] type_index Type and index of the descriptor * @param [out] data Descriptor data * @param [out] len Descriptor length @@ -370,6 +374,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da * index and alternate setting by parsing the installed USB descriptor list. * A configuration index of 0 unconfigures the device. * + * @param [in] busid busid * @param [in] config_index Configuration index * @param [in] alt_setting Alternate setting number * @@ -439,6 +444,7 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t /** * @brief set USB interface * + * @param [in] busid busid * @param [in] iface Interface index * @param [in] alt_setting Alternate setting number * @@ -494,7 +500,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting goto find_end; } else if (cur_alt_setting == alt_setting) { ret = usbd_set_endpoint(busid, ep_desc); - goto find_end; } else { } } @@ -522,6 +527,7 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting /** * @brief handle a standard device request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -617,6 +623,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet * /** * @brief handle a standard interface request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -703,11 +710,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe ret = false; break; case USB_REQUEST_GET_INTERFACE: - (*data)[0] = 0; + (*data)[0] = g_usbd_core[busid].intf_altsetting[intf_num]; *len = 1; break; case USB_REQUEST_SET_INTERFACE: + g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue); usbd_set_interface(busid, setup->wIndex, setup->wValue); *len = 0; break; @@ -723,6 +731,7 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe /** * @brief handle a standard endpoint request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -787,6 +796,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet /** * @brief handle standard requests (list in chapter 9) * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -830,8 +840,7 @@ static int usbd_standard_request_handler(uint8_t busid, struct usb_setup_packet /** * @brief handler for class requests * - * If a custom request handler was installed, this handler is called first. - * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -863,8 +872,7 @@ static int usbd_class_request_handler(uint8_t busid, struct usb_setup_packet *se /** * @brief handler for vendor requests * - * If a custom request handler was installed, this handler is called first. - * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -1006,6 +1014,7 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s /** * @brief handle setup request( standard/class/vendor/other) * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -1167,7 +1176,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup) #ifdef CONFIG_USBDEV_EP0_INDATA_NO_COPY g_usbd_core[busid].ep0_data_buf = buf; #else - memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue); + usb_memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue); #endif } else { /* use memcpy(*data, xxx, len); has copied into ep0 buffer, we do nothing */ diff --git a/components/drivers/usb/cherryusb/core/usbh_core.c b/components/drivers/usb/cherryusb/core/usbh_core.c index d4de88e54f7..cb36f97eea8 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.c +++ b/components/drivers/usb/cherryusb/core/usbh_core.c @@ -93,19 +93,22 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin struct usbh_class_info *index = NULL; for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) { - if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->bInterfaceClass == class)) { continue; } - if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->bInterfaceSubClass == subclass)) { continue; } - if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) { continue; } if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) { /* scan id table */ uint32_t i; - for (i = 0; index->id_table[i][0] && index->id_table[i][0] != vid && index->id_table[i][1] != pid; i++) { + for (i = 0; index->id_table[i][0]; i++) { + if (index->id_table[i][0] == vid && index->id_table[i][1] == pid) { + break; + } } /* do not match, continue next */ if (!index->id_table[i][0]) { @@ -831,6 +834,37 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub * } } +static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port) +{ + struct usbh_hubport *hport; + struct usbh_hub *hub_next; + + if (hub->index == hub_index) { + hport = &hub->child[hub_port - 1]; + return hport; + } else { + for (uint8_t port = 0; port < hub->nports; port++) { + hport = &hub->child[port]; + if (hport->connected) { + for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { + if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) { + if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) { + hub_next = hport->config.intf[itf].priv; + + if (hub_next && hub_next->connected) { + hport = usbh_list_all_hubport(hub_next, hub_index, hub_port); + if (hport) { + return hport; + } + } + } + } + } + } + } + } + return NULL; +} void *usbh_find_class_instance(const char *devname) { usb_slist_t *bus_list; @@ -855,6 +889,23 @@ void *usbh_find_class_instance(const char *devname) return NULL; } +struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port) +{ + struct usbh_hub *hub; + struct usbh_bus *bus; + struct usbh_hubport *hport; + size_t flags; + + flags = usb_osal_enter_critical_section(); + + bus = &g_usbhost_bus[busid]; + hub = &bus->hcd.roothub; + + hport = usbh_list_all_hubport(hub, hub_index, hub_port); + usb_osal_leave_critical_section(flags); + return hport; +} + int lsusb(int argc, char **argv) { 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 6674fcb4953..eaddb304329 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.h +++ b/components/drivers/usb/cherryusb/core/usbh_core.h @@ -61,9 +61,9 @@ extern "C" { struct usbh_class_info { uint8_t match_flags; /* Used for product specific matches; range is inclusive */ - uint8_t class; /* Base device class code */ - uint8_t subclass; /* Sub-class, depends on base class. Eg. */ - uint8_t protocol; /* Protocol, depends on base class. Eg. */ + uint8_t bInterfaceClass; /* Base device class code */ + uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */ + uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */ const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */ const struct usbh_class_driver *class_driver; }; @@ -275,6 +275,7 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett int usbh_initialize(uint8_t busid, uintptr_t reg_base); int usbh_deinitialize(uint8_t busid); void *usbh_find_class_instance(const char *devname); +struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port); int lsusb(int argc, char **argv); 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 32bd9109a56..148f324c37a 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 @@ -332,14 +332,15 @@ void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base) */ void hid_mouse_test(uint8_t busid) { + if(usb_device_is_configured(busid) == false) { + return; + } /*!< move mouse pointer */ mouse_cfg.x += 10; mouse_cfg.y = 0; - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } + hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c index 1d70aaa5553..9147c92320f 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c @@ -6,6 +6,10 @@ #include "usbd_core.h" #include "usbd_cdc_ecm.h" +#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP +#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo" +#endif + /*!< endpoint address */ #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 @@ -222,12 +226,12 @@ void cdc_ecm_lwip_init(void) while (!netif_is_up(netif)) { } - // while (dhserv_init(&dhcp_config)) {} + while (dhserv_init(&dhcp_config)) {} - // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} + while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} } -void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len) +void usbd_cdc_ecm_data_recv_done(uint32_t len) { } diff --git a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c index 310788360c1..a83a75551aa 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c @@ -6,6 +6,10 @@ #include "usbd_core.h" #include "usbd_rndis.h" +#ifndef CONFIG_USBDEV_RNDIS_USING_LWIP +#error "Please enable CONFIG_USBDEV_RNDIS_USING_LWIP for this demo" +#endif + /*!< endpoint address */ #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 @@ -170,7 +174,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p) return usbd_rndis_eth_tx(p); } -void usbd_rndis_data_recv_done(void) +void usbd_rndis_data_recv_done(uint32_t len) { eth_device_ready(&rndis_dev); } @@ -258,12 +262,12 @@ void rndis_lwip_init(void) while (!netif_is_up(netif)) { } - // while (dhserv_init(&dhcp_config)) {} + while (dhserv_init(&dhcp_config)) {} - // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} + while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} } -void usbd_rndis_data_recv_done(void) +void usbd_rndis_data_recv_done(uint32_t len) { } diff --git a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c index 7527f396d81..4d1afc3056d 100644 --- a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c @@ -236,12 +236,13 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c index e6d24d7cb9e..564d1718bba 100644 --- a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c @@ -304,14 +304,15 @@ void draw_circle(uint8_t *buf) /* https://cps-check.com/cn/polling-rate-check */ void hid_mouse_test(uint8_t busid) { + if(usb_device_is_configured(busid) == false) { + return; + } + int counter = 0; while (counter < 1000) { draw_circle((uint8_t *)&mouse_cfg); - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } 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 b528c4a11dd..786c3240394 100644 --- a/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c @@ -307,6 +307,10 @@ void hid_mouse_test(uint8_t busid) static uint32_t count = 1000; int ret; + if(usb_device_is_configured(busid) == false) { + return; + } + // if (gpio_read_pin(GPIO_PIN) == 1) { // ret = usbd_send_remote_wakeup(busid); // if (ret < 0) { @@ -317,11 +321,8 @@ void hid_mouse_test(uint8_t busid) while (count) { draw_circle((uint8_t *)&mouse_cfg); - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } diff --git a/components/drivers/usb/cherryusb/demo/usb_host.c b/components/drivers/usb/cherryusb/demo/usb_host.c index 7198418893b..817103d5c08 100644 --- a/components/drivers/usb/cherryusb/demo/usb_host.c +++ b/components/drivers/usb/cherryusb/demo/usb_host.c @@ -254,38 +254,38 @@ static void usbh_msc_thread(void *argument) } #endif +#if TEST_USBH_CDC_ACM void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) { -#if TEST_USBH_CDC_ACM usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, cdc_acm_class); -#endif } void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) { } +#endif +#if TEST_USBH_HID void usbh_hid_run(struct usbh_hid *hid_class) { -#if TEST_USBH_HID usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class); -#endif } void usbh_hid_stop(struct usbh_hid *hid_class) { } +#endif +#if TEST_USBH_MSC void usbh_msc_run(struct usbh_msc *msc_class) { -#if TEST_USBH_MSC usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class); -#endif } void usbh_msc_stop(struct usbh_msc *msc_class) { } +#endif #if TEST_USBH_AUDIO #error "commercial charge" @@ -294,3 +294,26 @@ void usbh_msc_stop(struct usbh_msc *msc_class) #if TEST_USBH_VIDEO #error "commercial charge" #endif + +#if 0 +#include "usbh_aoa.h" + +static struct aoa_string_info deviceinfo = { + .acc_manufacturer = "CherryUSB", + .acc_model = "CherryUSB", + .acc_description = "Android Open Accessory CherryUSB", + .acc_version = "1.0", + .acc_uri = "http://developer.android.com/tools/adk/index.html", + .acc_serial = "CherryUSB" +}; + +int aoa_switch(int argc, char **argv) +{ + struct usbh_hubport *hport = usbh_find_hubport(0, 1, 1); + + usbh_aoa_switch(hport, &deviceinfo); + return 0; +} + +SHELL_CMD_EXPORT_ALIAS(aoa_switch, aoa_switch, aoa_switch); +#endif \ No newline at end of file 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 85a5146d4b3..6a4116222a0 100644 --- a/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c @@ -9,6 +9,8 @@ #include "usbd_hid.h" #include "cherryusb_mjpeg.h" +#define MAX_PACKETS_IN_ONE_TRANSFER 1 + #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x86 @@ -267,7 +269,7 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = { USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_write_buffer[AUDIO_IN_PACKET]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; volatile bool video_tx_flag = 0; volatile bool audio_tx_flag = 0; @@ -331,8 +333,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - video_iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + video_iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -458,56 +462,30 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(hid_write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(hid_write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; + memset(video_packet_buffer, 0, sizeof(video_packet_buffer)); - (void)packets; - memset(video_packet_buffer, 0, 40 * 1024); while (1) { if (video_tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), video_packet_buffer, &out_len); -#if 1 video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, video_packet_buffer, out_len); + usbd_video_stream_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[0][0], &video_packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); while (video_iso_tx_busy) { if (video_tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (video_iso_tx_busy) { - if (video_tx_flag == 0) { - break; - } - } - } else { - video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (video_iso_tx_busy) { - if (video_tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file 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 376068edac8..e325964a2fd 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_h264_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_h264_template.c @@ -7,6 +7,8 @@ #include "usbd_video.h" #include "cherryusb_h264.h" +#define MAX_PACKETS_IN_ONE_TRANSFER 1 + #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x83 @@ -180,8 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -202,7 +206,7 @@ void video_init(uint8_t busid, uintptr_t reg_base) usbd_initialize(busid, reg_base, usbd_event_handler); } -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][40 * 1024]; void video_test(uint8_t busid) { @@ -210,40 +214,16 @@ void video_test(uint8_t busid) uint32_t packets; (void)packets; - memset(packet_buffer, 0, 40 * 1024); + memset(packet_buffer, 0, sizeof(packet_buffer)); while (1) { if (tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264), packet_buffer, &out_len); -#if 1 iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); + usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } else { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file 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 51a4422613f..1d2ae01ba4b 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c @@ -7,7 +7,7 @@ #include "usbd_video.h" #include "cherryusb_mjpeg.h" -#define VIDEO_STREAM_SPLIT_ENABLE 1 +#define MAX_PACKETS_IN_ONE_TRANSFER 1 #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x83 @@ -182,14 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { -#if VIDEO_STREAM_SPLIT_ENABLE if (usbd_video_stream_split_transfer(busid, ep)) { /* one frame has done */ iso_tx_busy = false; } -#else - iso_tx_busy = false; -#endif } static struct usbd_endpoint video_in_ep = { @@ -210,42 +206,21 @@ void video_init(uint8_t busid, uintptr_t reg_base) usbd_initialize(busid, reg_base, usbd_event_handler); } -#if VIDEO_STREAM_SPLIT_ENABLE -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE]; -#else -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024]; -#endif +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; - - (void)packets; - (void)out_len; memset(packet_buffer, 0, sizeof(packet_buffer)); while (1) { if (tx_flag) { -#if VIDEO_STREAM_SPLIT_ENABLE iso_tx_busy = true; - usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); + usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len); - - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } -#endif } } } \ No newline at end of file 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 f90344d17e8..4ba71701c48 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c @@ -7,6 +7,8 @@ #include "usbd_video.h" #include "cherryusb_yuyv.h" +#define MAX_PACKETS_IN_ONE_TRANSFER 1 + #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x83 @@ -182,8 +184,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -204,48 +208,21 @@ void video_init(uint8_t busid, uintptr_t reg_base) usbd_initialize(busid, reg_base, usbd_event_handler); } -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; + memset(packet_buffer, 0, sizeof(packet_buffer)); - (void)packets; - memset(packet_buffer, 0, 40 * 1024); while (1) { if (tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv), packet_buffer, &out_len); -#if 1 iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); + usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } else { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c index 04ec1dd25ac..52570879974 100644 --- a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c @@ -371,12 +371,13 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/idf_component.yml b/components/drivers/usb/cherryusb/idf_component.yml new file mode 100644 index 00000000000..a500a240473 --- /dev/null +++ b/components/drivers/usb/cherryusb/idf_component.yml @@ -0,0 +1,25 @@ +version: "1.4.2" +description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP +tags: + - usb + - usb-device + - usb-host + - cdc_acm + - cdc_ecm + - cdc_ncm + - hid + - msc + - rndis + - uvc + - uac + - winusb +url: https://github.com/cherry-embedded/CherryUSB +repository: https://github.com/cherry-embedded/CherryUSB.git +documentation: https://cherryusb.readthedocs.io/ +issues: https://github.com/cherry-embedded/CherryUSB/issues +dependencies: + idf: ">=5.0" +targets: + - esp32s2 + - esp32s3 + - esp32p4 \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c index be16ea1495b..b20e17d8755 100644 --- a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c +++ b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c @@ -6,10 +6,6 @@ #error must enable RT_USING_TIMER_SOFT to support timer callback in thread #endif -#if IDLE_THREAD_STACK_SIZE < 2048 -#error "IDLE_THREAD_STACK_SIZE must be >= 2048" -#endif - #if RT_TIMER_THREAD_STACK_SIZE < 2048 #error "RT_TIMER_THREAD_STACK_SIZE must be >= 2048" #endif diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c index 4b4b72d497c..7aabd411fcd 100644 --- a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c +++ b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c @@ -101,6 +101,11 @@ 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; diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c index 758ffd77f37..a8d3036a357 100644 --- a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c +++ b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c @@ -101,6 +101,11 @@ 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_HIGH; diff --git a/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c b/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c index 3d1971653d6..c6b6c0fee57 100644 --- a/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c +++ b/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c @@ -1,3 +1,14 @@ +/* + * Copyright (c) 2021-2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "usb_chipidea_reg.h" diff --git a/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c b/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c index 29bb2d292c0..3f9b46b6af0 100644 --- a/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c +++ b/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "fsl_common.h" diff --git a/components/drivers/usb/cherryusb/port/dwc2/README.md b/components/drivers/usb/cherryusb/port/dwc2/README.md index faf9ab5a1a9..3218b31cd56 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/README.md +++ b/components/drivers/usb/cherryusb/port/dwc2/README.md @@ -20,6 +20,11 @@ If you are using more than one port, all ip parameters must be the same(like fif ## GD32 +CONFIG_USBDEV_EP_NUM 必须为4 或者 6,并删除 usb_dc_dwc2.c 中 while(1){} + +当 CONFIG_USBDEV_EP_NUM 为4 时,fifo_num 不得大于 320 字 +当 CONFIG_USBDEV_EP_NUM 为6 时,fifo_num 不得大于 1280 字 + - GD32F30X_CL - GD32F405、GD32F407 - GD32F450 diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c b/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c index 72006abd5fe..6054a334a67 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c @@ -136,10 +136,12 @@ static inline int dwc2_reset(uint8_t busid) do { if (++count > 200000U) { - return -1; + break; } } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + USB_OTG_GLB->GRSTCTL &= ~USB_OTG_GRSTCTL_CSRST; + return 0; } @@ -478,7 +480,7 @@ static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum) msk = USB_OTG_DEV->DIEPMSK; emp = USB_OTG_DEV->DIEPEMPMSK; - msk |= ((emp >> (epnum & 0x07)) & 0x1U) << 7; + msk |= ((emp >> (epnum & 0x0F)) & 0x1U) << 7; tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT; USB_OTG_INEP((uint32_t)epnum)->DIEPINT = tmpreg; @@ -790,7 +792,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) } while ((USB_OTG_OUTEP(ep_idx)->DOEPINT & USB_OTG_DOEPINT_EPDISD) != USB_OTG_DOEPINT_EPDISD); /* Clear and unmask endpoint disabled interrupt */ - USB_OTG_OUTEP(ep_idx)->DOEPINT |= USB_OTG_DOEPINT_EPDISD; + USB_OTG_OUTEP(ep_idx)->DOEPINT = USB_OTG_DOEPINT_EPDISD; } USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep_idx & 0x07)) << 16)); @@ -810,7 +812,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) } while ((USB_OTG_INEP(ep_idx)->DIEPINT & USB_OTG_DIEPINT_EPDISD) != USB_OTG_DIEPINT_EPDISD); /* Clear and unmask endpoint disabled interrupt */ - USB_OTG_INEP(ep_idx)->DIEPINT |= USB_OTG_DIEPINT_EPDISD; + USB_OTG_INEP(ep_idx)->DIEPINT = USB_OTG_DIEPINT_EPDISD; } USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07))); @@ -1161,17 +1163,17 @@ void USBD_IRQHandler(uint8_t busid) dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup); } if (gint_status & USB_OTG_GINTSTS_ENUMDNE) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; dwc2_set_turnaroundtime(busid, SystemCoreClock, dwc2_get_devspeed(busid)); USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK; } if (gint_status & USB_OTG_GINTSTS_PXFR_INCOMPISOOUT) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_PXFR_INCOMPISOOUT; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_PXFR_INCOMPISOOUT; } if (gint_status & USB_OTG_GINTSTS_IISOIXFR) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_IISOIXFR; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_IISOIXFR; } if (gint_status & USB_OTG_GINTSTS_SOF) { diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c index 137b1d87046..8d45f651394 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c @@ -7,6 +7,9 @@ #include "stdint.h" #include "usb_dwc2_reg.h" +extern unsigned int system_core_clock; + +uint32_t SystemCoreClock; /* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example: * * usbx->gccfg_bit.pwrdown = TRUE; @@ -17,6 +20,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) { + SystemCoreClock = system_core_clock; #ifdef CONFIG_USB_HS return ((1 << 16) | (1 << 21)); #else @@ -35,6 +39,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base) { + SystemCoreClock = system_core_clock; #ifdef CONFIG_USB_HS return ((1 << 16) | (1 << 21)); #else diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c index 7121ac9dbd2..f3fa4d92f7a 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c @@ -7,6 +7,10 @@ #include "stdint.h" #include "usb_dwc2_reg.h" +#if CONFIG_USBDEV_EP_NUM != 4 && CONFIG_USBDEV_EP_NUM != 6 +#error "gd32 only has 4 endpoints for pa11/pa12 and 6 endpoints for pb14/pb15" +#endif + /* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example: * * usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; 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 f73dc5e9528..4dff31f83f4 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c @@ -166,6 +166,8 @@ uint32_t usbd_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 @@ -192,6 +194,8 @@ 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 9b0fc66015b..09f55170a5c 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c @@ -215,6 +215,12 @@ static inline void dwc2_chan_char_init(struct usbh_bus *bus, uint8_t ch_num, uin regval |= USB_OTG_HCCHAR_EPDIR; } + if ((usbh_get_port_speed(bus, 0) == USB_SPEED_HIGH) && (speed != USB_SPEED_HIGH)) { + USB_LOG_ERR("Do not support LS/FS device on HS hub\r\n"); + while (1) { + } + } + /* LS device plugged to HUB */ if ((speed == USB_SPEED_LOW) && (usbh_get_port_speed(bus, 0) != USB_SPEED_LOW)) { regval |= USB_OTG_HCCHAR_LSDEV; @@ -1131,4 +1137,4 @@ void USBH_IRQHandler(uint8_t busid) USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT; } } -} +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c index 9fc87c39b70..500bc02a40d 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c @@ -9,6 +9,19 @@ #include #include "usbh_core.h" #include "usb_hc_ehci.h" +#include "usb_hc_ohci.h" + +#if !defined(CONFIG_USB_EHCI_CONFIGFLAG) +#error "aic ehci must define CONFIG_USB_EHCI_CONFIGFLAG" +#endif + +#if !defined(CONFIG_USB_EHCI_WITH_OHCI) +#error "aic must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device" +#endif + +#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400 +#error "aic CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400" +#endif extern void USBH_IRQHandler(uint8_t busid); @@ -117,21 +130,12 @@ void usb_hc_low_level_init(struct usbh_bus *bus) aicos_request_irq(config[i].irq_num + 1, (irq_handler_t)aic_ohci_isr, 0, "usb_host_ohci", bus); aicos_irq_enable(config[i].irq_num); + aicos_irq_enable(config[i].irq_num + 1); } 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; + return USB_SPEED_HIGH; } void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len) @@ -149,7 +153,7 @@ void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len) aicos_dcache_clean_invalid_range((size_t *)addr, len); } -int usbh_init(void) +int __usbh_init(void) { #if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB1_HOST) int bus_id = 0; @@ -171,11 +175,5 @@ int usbh_init(void) #include #include -INIT_ENV_EXPORT(usbh_init); - -#if defined (RT_USING_FINSH) -#include - -MSH_CMD_EXPORT_ALIAS(lsusb, lsusb, list usb device); -#endif +INIT_ENV_EXPORT(__usbh_init); #endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c index 17724008495..40105a94984 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c @@ -35,6 +35,11 @@ static void usb_host_mode_init(USB_Type *ptr) /* Set parallel transceiver width */ ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK; +#ifdef CONFIG_USB_HOST_FORCE_FULL_SPEED + /* Set usb forced to full speed mode */ + ptr->PORTSC1 |= USB_PORTSC1_PFSC_MASK; +#endif + /* Not use interrupt threshold. */ ptr->USBCMD &= ~USB_USBCMD_ITC_MASK; } @@ -53,7 +58,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus) #endif } - usb_phy_init((USB_Type *)(bus->hcd.reg_base)); + usb_phy_init((USB_Type *)(bus->hcd.reg_base), true); intc_m_enable_irq(_hcd_irqnum[bus->hcd.hcd_id]); } @@ -86,18 +91,18 @@ uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port) extern void USBH_IRQHandler(uint8_t busid); +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0) void isr_usbh0(void) { USBH_IRQHandler(_hcd_busid[0]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0) #ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1) void isr_usbh1(void) { USBH_IRQHandler(_hcd_busid[1]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1) #endif #endif diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c index 7f8f4bf5548..92b2c25ec85 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbh_core.h" #include "fsl_common.h" #include "usb_chipidea_reg.h" 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 8b9caba419b..4f61854a338 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c @@ -952,6 +952,7 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) { } + USB_LOG_INFO("Switch port %u to OHCI\r\n", port); return ohci_roothub_control(bus, setup, buf); } #endif @@ -1063,7 +1064,9 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) { } - return ohci_roothub_control(bus, setup, buf); + + USB_LOG_INFO("Switch port %u to OHCI\r\n", port); + return -USB_ERR_NOTSUPP; } #endif break; diff --git a/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c b/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c index b2dd9cca4da..f27e8c6993f 100644 --- a/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c +++ b/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c @@ -154,7 +154,8 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) case USB_ENDPOINT_TYPE_ISOCHRONOUS: wEpRegVal = USB_EP_ISOCHRONOUS; - break; + USB_LOG_ERR("Do not support iso in fsdev\r\n"); + return -1; default: break; diff --git a/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c b/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c index 625c8b11fbf..b663fd9afc5 100644 --- a/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c +++ b/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c @@ -128,8 +128,6 @@ int usbd_set_remote_wakeup(uint8_t busid) } usb_force_port_resume(ptr); - while (ptr->PORTSC1 & USB_PORTSC1_FPR_MASK) { - } return 0; } @@ -362,18 +360,18 @@ void USBD_IRQHandler(uint8_t busid) #if !defined(USBD_USE_CUSTOM_ISR) || !USBD_USE_CUSTOM_ISR +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0) void isr_usbd0(void) { USBD_IRQHandler(_dcd_busid[0]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0) #ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1) void isr_usbd1(void) { USBD_IRQHandler(_dcd_busid[1]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1) #endif #endif diff --git a/components/drivers/usb/cherryusb/port/ohci/README.md b/components/drivers/usb/cherryusb/port/ohci/README.md index 34e753c3125..928eb0c3fd8 100644 --- a/components/drivers/usb/cherryusb/port/ohci/README.md +++ b/components/drivers/usb/cherryusb/port/ohci/README.md @@ -1,18 +1,23 @@ # Note -This OHCI is a companion controller of EHCI. +This OHCI is a companion controller of EHCI. But you can use OHCI only without CONFIG_USB_EHCI_WITH_OHCI definition. + +**And you need to pay for using OHCI driver**. ## Support Chip List ### AllwinnerTech -- F133 +- F133(EHCI + OHCI) ### Nuvoton -- Nuvoton all series +- Nuvoton all series(EHCI + OHCI, OHCI only) ### Artinchip -- d13x, d21x +- d13x, d21x(EHCI + OHCI) + +### NXP +- LPC4X/LPC5X(OHCI only) \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c b/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c new file mode 100644 index 00000000000..51ab7814052 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "fsl_device_registers.h" +#include "fsl_power.h" +#include "usbh_core.h" + +#if defined(CONFIG_USB_EHCI_WITH_OHCI) +#error "lpc does not have ehci" +#endif + +void usb_hc_low_level_init(struct usbh_bus *bus) +{ +#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT)) + SYSMPU_Enable(SYSMPU, 0); +#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */ + + NVIC_ClearPendingIRQ(USB0_IRQn); + NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn); + + POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB0 Phy */ + + RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn); + + CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U); + + NVIC_SetPriority(USB0_IRQn, 3); + EnableIRQ(USB0_IRQn); +} + + +void usb_hc_low_level_deinit(struct usbh_bus *bus) +{ + DisableIRQ(USB0_IRQn); +} + +void USB0_IRQHandler(void) +{ + extern void USBH_IRQHandler(uint8_t busid); + USBH_IRQHandler(0); +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c index fda180909d9..2bec2a03988 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c +++ b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c @@ -4,18 +4,58 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "usb_hc_ohci.h" -#include "usb_hc_ehci.h" + +/* Frame Interval / Periodic Start. + * + * At 12Mbps, there are 12000 bit time in each 1Msec frame. + */ + +#define OHCI_FMINTERVAL_FI (12000 - 1) +#define OHCI_FMINTERVAL_FSMPS ((6 * (OHCI_FMINTERVAL_FI - 210)) / 7) +#define DEFAULT_FMINTERVAL ((OHCI_FMINTERVAL_FSMPS << OHCI_FMINT_FSMPS_SHIFT) | OHCI_FMINTERVAL_FI) +#define DEFAULT_PERSTART ((OHCI_FMINTERVAL_FI * 9) / 10) + +struct ohci_hcd g_ohci_hcd[CONFIG_USBHOST_MAX_BUS]; + +USB_NOCACHE_RAM_SECTION struct ohci_ed_hw g_ohci_ed_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_OHCI_ED_NUM]; +USB_NOCACHE_RAM_SECTION struct ohci_hcca ohci_hcca[CONFIG_USBHOST_MAX_BUS]; int ohci_init(struct usbh_bus *bus) { volatile uint32_t timeout = 0; uint32_t regval; + struct ohci_ed_hw *ed; + + memset(&g_ohci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ohci_hcd)); + memset(g_ohci_ed_pool[bus->hcd.hcd_id], 0, sizeof(struct ohci_ed_hw) * CONFIG_USB_OHCI_ED_NUM); + + for (uint32_t i = 0; i < 32; i++) { + ohci_hcca[bus->hcd.hcd_id].inttbl[i] = 0; + } + + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + if ((uint32_t)&ed->hw % 32) { + USB_LOG_ERR("struct ohci_ed_hw is not align 32\r\n"); + return -USB_ERR_INVAL; + } + for (uint8_t i = 0; i < CONFIG_USB_OHCI_TD_NUM; i++) { + if ((uint32_t)&ed->td_pool[i] % 32) { + USB_LOG_ERR("struct ohci_td_hw is not align 32\r\n"); + return -USB_ERR_INVAL; + } + } + } + + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + ed->waitsem = usb_osal_sem_create(0); + } USB_LOG_INFO("OHCI hcrevision:0x%02x\r\n", (unsigned int)OHCI_HCOR->hcrevision); + OHCI_HCOR->hcintdis = OHCI_INT_MIE; OHCI_HCOR->hccontrol = 0; - OHCI_HCOR->hccontrolheaded = 0; - OHCI_HCOR->hcbulkheaded = 0; OHCI_HCOR->hccmdsts = OHCI_CMDST_HCR; while (OHCI_HCOR->hccmdsts & OHCI_CMDST_HCR) { @@ -26,45 +66,39 @@ int ohci_init(struct usbh_bus *bus) } } - /* Frame Interval / Periodic Start. - * - * At 12Mbps, there are 12000 bit time in each 1Msec frame. - */ - -#define BITS_PER_FRAME 12000 -#define FI (BITS_PER_FRAME - 1) -#define FSMPS ((6 * (FI - 210)) / 7) -#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI) -#define DEFAULT_PERSTART (((9 * BITS_PER_FRAME) / 10) - 1) - OHCI_HCOR->hcfminterval = DEFAULT_FMINTERVAL; OHCI_HCOR->hcperiodicstart = DEFAULT_PERSTART; + OHCI_HCOR->hclsthreshold = 0x628; + + OHCI_HCOR->hccontrolheaded = 0; + OHCI_HCOR->hcbulkheaded = 0; + OHCI_HCOR->hchcca = (uintptr_t)&ohci_hcca[bus->hcd.hcd_id]; + + /* Clear pending interrupts */ + regval = OHCI_HCOR->hcintsts; + OHCI_HCOR->hcintsts = regval; /* Put HC in operational state */ regval = OHCI_HCOR->hccontrol; + regval &= ~OHCI_CTRL_CBSR; regval &= ~OHCI_CTRL_HCFS_MASK; regval |= OHCI_CTRL_HCFS_OPER; + regval |= OHCI_CTRL_CBSR; + regval |= OHCI_CTRL_CLE; OHCI_HCOR->hccontrol = regval; - /* Set global power in HcRhStatus */ - OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; + g_ohci_hcd[bus->hcd.hcd_id].n_ports = OHCI_HCOR->hcrhdescriptora & OHCI_RHDESCA_NDP_MASK; + USB_LOG_INFO("OHCI n_ports:%d\r\n", g_ohci_hcd[bus->hcd.hcd_id].n_ports); - /* Set HCCA base address */ - OHCI_HCOR->hchcca = 0; + OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_PSM; + OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_NPS; - /* Clear pending interrupts */ - regval = OHCI_HCOR->hcintsts; - OHCI_HCOR->hcintsts = regval; - - for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) { - regval = OHCI_HCOR->hcrhportsts[port]; - regval |= OHCI_RHPORTST_PPS; - OHCI_HCOR->hcrhportsts[port] = regval; - } + /* Set global power in HcRhStatus */ + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; + usb_osal_msleep(20); /* Enable OHCI interrupts */ - OHCI_HCOR->hcinten = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC | - OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + OHCI_HCOR->hcinten = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; return 0; } @@ -72,15 +106,25 @@ int ohci_init(struct usbh_bus *bus) int ohci_deinit(struct usbh_bus *bus) { uint32_t regval; + struct ohci_ed_hw *ed; /* Disable OHCI interrupts */ - OHCI_HCOR->hcintdis = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC | - OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + OHCI_HCOR->hcintdis = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + + /* Clear pending interrupts */ + regval = OHCI_HCOR->hcintsts; + OHCI_HCOR->hcintsts = regval; + + OHCI_HCOR->hcrhsts &= ~OHCI_RHSTATUS_SGP; + + regval = OHCI_HCOR->hccontrol; + regval &= ~OHCI_CTRL_HCFS_MASK; + regval |= OHCI_CTRL_HCFS_SUSPEND; + OHCI_HCOR->hccontrol = regval; - for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) { - regval = OHCI_HCOR->hcrhportsts[port]; - regval &= ~OHCI_RHPORTST_PPS; - OHCI_HCOR->hcrhportsts[port] = regval; + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + usb_osal_sem_delete(ed->waitsem); } return 0; @@ -97,7 +141,7 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u uint8_t port; uint32_t temp; - nports = g_ehci_hcd[bus->hcd.hcd_id].n_pcc; + nports = g_ohci_hcd[bus->hcd.hcd_id].n_ports; port = setup->wIndex; if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) { @@ -139,28 +183,46 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u switch (setup->wValue) { case HUB_PORT_FEATURE_ENABLE: + temp = OHCI_RHPORTST_CCS; break; case HUB_PORT_FEATURE_SUSPEND: + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_RESUME; + OHCI_HCOR->hccontrol = temp; + + usb_osal_msleep(20); + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_OPER; + OHCI_HCOR->hccontrol = temp; + + temp = OHCI_RHPORTST_POCI; + break; case HUB_PORT_FEATURE_C_SUSPEND: + temp = OHCI_RHPORTST_PSSC; break; case HUB_PORT_FEATURE_POWER: + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_CGP; + temp = OHCI_RHPORTST_LSDA; break; case HUB_PORT_FEATURE_C_CONNECTION: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_CSC; + temp = OHCI_RHPORTST_CSC; break; case HUB_PORT_FEATURE_C_ENABLE: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PESC; + temp = OHCI_RHPORTST_PESC; break; case HUB_PORT_FEATURE_C_OVER_CURREN: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_OCIC; + temp = OHCI_RHPORTST_OCIC; break; case HUB_PORT_FEATURE_C_RESET: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRSC; + temp = OHCI_RHPORTST_PRSC; break; default: return -USB_ERR_NOTSUPP; } + OHCI_HCOR->hcrhportsts[port - 1] = temp; break; case HUB_REQUEST_SET_FEATURE: if (!port || port > nports) { @@ -169,11 +231,17 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u switch (setup->wValue) { case HUB_PORT_FEATURE_SUSPEND: + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_SUSPEND; + OHCI_HCOR->hccontrol = temp; + break; case HUB_PORT_FEATURE_POWER: + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; break; case HUB_PORT_FEATURE_RESET: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRS; + OHCI_HCOR->hcrhportsts[port - 1] = OHCI_RHPORTST_PRS; while (OHCI_HCOR->hcrhportsts[port - 1] & OHCI_RHPORTST_PRS) { } @@ -188,7 +256,6 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u return -USB_ERR_INVAL; } temp = OHCI_HCOR->hcrhportsts[port - 1]; - memcpy(buf, &temp, 4); break; default: @@ -216,9 +283,9 @@ void OHCI_IRQHandler(uint8_t busid) bus = &g_usbhost_bus[busid]; usbsts = OHCI_HCOR->hcintsts & OHCI_HCOR->hcinten; - OHCI_HCOR->hcintsts = usbsts; if (usbsts & OHCI_INT_RHSC) { + OHCI_HCOR->hcintsts = OHCI_INT_RHSC; for (int port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) { uint32_t portsc = OHCI_HCOR->hcrhportsts[port]; @@ -236,5 +303,51 @@ void OHCI_IRQHandler(uint8_t busid) } } if (usbsts & OHCI_INT_WDH) { + OHCI_HCOR->hcintsts = OHCI_INT_WDH; } -} \ No newline at end of file +} + +#ifndef CONFIG_USB_EHCI_WITH_OHCI +__WEAK void usb_hc_low_level_init(struct usbh_bus *bus) +{ + (void)bus; +} + +__WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus) +{ + (void)bus; +} + +int usb_hc_init(struct usbh_bus *bus) +{ + usb_hc_low_level_init(bus); + return ohci_init(bus); +} + +int usb_hc_deinit(struct usbh_bus *bus) +{ + ohci_deinit(bus); + usb_hc_low_level_deinit(bus); + return 0; +} + +int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf) +{ + return ohci_roothub_control(bus, setup, buf); +} + +int usbh_submit_urb(struct usbh_urb *urb) +{ + return ohci_submit_urb(urb); +} + +int usbh_kill_urb(struct usbh_urb *urb) +{ + return ohci_kill_urb(urb); +} + +void USBH_IRQHandler(uint8_t busid) +{ + OHCI_IRQHandler(busid); +} +#endif \ No newline at end of file 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 68815d9d195..19d5190966b 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h +++ b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h @@ -12,6 +12,38 @@ #define OHCI_HCOR ((struct ohci_hcor *)(uintptr_t)(bus->hcd.reg_base + CONFIG_USB_OHCI_HCOR_OFFSET)) +#define OHCI_PTR2ADDR(x) ((uint32_t)(uintptr_t)(x) & ~0x0F) +#define OHCI_ADDR2ED(x) ((struct ohci_ed_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F)) +#define OHCI_ADDR2TD(x) ((struct ohci_td_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F)) + +#ifndef CONFIG_USB_OHCI_ED_NUM +#define CONFIG_USB_OHCI_ED_NUM CONFIG_USBHOST_PIPE_NUM +#endif +#ifndef CONFIG_USB_OHCI_TD_NUM +#define CONFIG_USB_OHCI_TD_NUM 3 +#endif + +struct ohci_ed_hw; +struct ohci_td_hw { + struct ohci_gtd hw; + struct usbh_urb *urb; + uint32_t buf_start; + uint32_t length; +} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */ + +struct ohci_ed_hw { + struct ohci_ed hw; + struct ohci_td_hw td_pool[CONFIG_USB_OHCI_TD_NUM]; + uint32_t td_count; + uint8_t ed_type; + usb_osal_sem_t waitsem; +} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */ + +struct ohci_hcd { + bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM]; + uint8_t n_ports; +}; + int ohci_init(struct usbh_bus *bus); int ohci_deinit(struct usbh_bus *bus); uint16_t ohci_get_frame_number(struct usbh_bus *bus); diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h b/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h index 030350e5cc6..61f7f4bf9a0 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h +++ b/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h @@ -95,10 +95,10 @@ /* HcControl: HC control (7.1.2) */ #define OHCI_CTRL_CBSR (3 << 0) /* Bit 0: Control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* Bit 1: Periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* Bit 2: Isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* Bit 3: Control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* Bit 4: Bulk list enable */ +#define OHCI_CTRL_PLE (1 << 2) /* Bit 2: Periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* Bit 3: Isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* Bit 4: Control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* Bit 5: Bulk list enable */ #define OHCI_CTRL_HCFS_SHIFT (6) /* Bits 6-7: Host controller functional state */ #define OHCI_CTRL_HCFS_MASK (3 << OHCI_CTRL_HCFS_SHIFT) # define OHCI_CTRL_HCFS_RESET (0 << OHCI_CTRL_HCFS_SHIFT) @@ -261,9 +261,9 @@ # define ED_CONTROL_D_IN (2 << ED_CONTROL_D_SHIFT) /* IN */ # define ED_CONTROL_D_TD2 (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */ -#define ED_CONTROL_S (1 << 13) /* Bit 13: Speed (low) */ -#define ED_CONTROL_K (1 << 14) /* Bit 14: Skip */ -#define ED_CONTROL_F (1 << 15) /* Bit 15: Format (isochronous) */ +#define ED_CONTROL_SPPED_LOW (1 << 13) /* Bit 13: Speed (low) */ +#define ED_CONTROL_SKIP (1 << 14) /* Bit 14: Skip */ +#define ED_CONTROL_FORMAT_ISO (1 << 15) /* Bit 15: Format (isochronous) */ #define ED_CONTROL_MPS_SHIFT (16) /* Bits 16-26: Maximum packet size */ #define ED_CONTROL_MPS_MASK (0x7ff << ED_CONTROL_MPS_SHIFT) @@ -406,7 +406,7 @@ struct ohci_hcor /* Endpoint Descriptor Offsets (4.2.1) */ -struct ohci_ed_s +struct ohci_ed { volatile uint32_t ctrl; /* ED status/control bits */ volatile uint32_t tailp; /* TD Queue Tail Pointer (TailP) */ @@ -416,7 +416,7 @@ struct ohci_ed_s /* General Transfer Descriptor (4.3.1) */ -struct ohci_gtd_s +struct ohci_gtd { volatile uint32_t ctrl; /* TD status/control bits */ volatile uint32_t cbp; /* Current Buffer Pointer (CBP) */ @@ -426,7 +426,7 @@ struct ohci_gtd_s /* Isochronous Transfer Descriptor Offsets (4.3.2) */ -struct ohci_itd_s +struct ohci_itd { volatile uint32_t ctrl; /* TD status/control bits */ volatile uint32_t bp0; /* Buffer page 0 (BP0 */ @@ -437,7 +437,7 @@ struct ohci_itd_s /* Host Controller Communications Area Format (4.4.1) */ -struct ohci_hcca_s +struct ohci_hcca { /* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */