diff --git a/components/drivers/usb/cherryusb/Kconfig b/components/drivers/usb/cherryusb/Kconfig index ce39f3e713..98e3315107 100644 --- a/components/drivers/usb/cherryusb/Kconfig +++ b/components/drivers/usb/cherryusb/Kconfig @@ -123,16 +123,17 @@ if CHERRYUSB prompt "Enable usb mtp device, it is commercial charge" default n - config CHERRYUSB_DEVICE_DFU - bool - prompt "Enable usb dfu device" - default n config CHERRYUSB_DEVICE_ADB bool prompt "Enable usb adb device" default n + config CHERRYUSB_DEVICE_DFU + bool + prompt "Enable usb dfu device" + default n + choice prompt "Select usb device template" default CHERRYUSB_DEVICE_TEMPLATE_NONE diff --git a/components/drivers/usb/cherryusb/Kconfig.rtt b/components/drivers/usb/cherryusb/Kconfig.rtt index 209332f5e6..2d35b4cae6 100644 --- a/components/drivers/usb/cherryusb/Kconfig.rtt +++ b/components/drivers/usb/cherryusb/Kconfig.rtt @@ -125,11 +125,21 @@ if RT_USING_CHERRYUSB prompt "Enable usb mtp device, it is commercial charge" default n + config RT_CHERRYUSB_DEVICE_ADB + bool + prompt "Enable usb adb device" + default n + config RT_CHERRYUSB_DEVICE_DFU bool prompt "Enable usb dfu device" default n + config RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV + bool + prompt "Enable chardev for cdc acm device" + default n + choice prompt "Select usb device template" default RT_CHERRYUSB_DEVICE_TEMPLATE_NONE @@ -169,6 +179,10 @@ if RT_USING_CHERRYUSB bool "winusbv2_cdc" config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID bool "winusbv2_hid" + config RT_CHERRYUSB_DEVICE_TEMPLATE_ADB + bool "adb" + config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV + bool "cdc_acm_chardev" endchoice config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME diff --git a/components/drivers/usb/cherryusb/Kconfig.rttpkg b/components/drivers/usb/cherryusb/Kconfig.rttpkg index 73d5f3b2b4..63614327dd 100644 --- a/components/drivers/usb/cherryusb/Kconfig.rttpkg +++ b/components/drivers/usb/cherryusb/Kconfig.rttpkg @@ -124,11 +124,21 @@ if PKG_USING_CHERRYUSB prompt "Enable usb mtp device, it is commercial charge" default n + config PKG_CHERRYUSB_DEVICE_ADB + bool + prompt "Enable usb adb device" + default n + config PKG_CHERRYUSB_DEVICE_DFU bool prompt "Enable usb dfu device" default n + config PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV + bool + prompt "Enable chardev for cdc acm device" + default n + choice prompt "Select usb device template" default PKG_CHERRYUSB_DEVICE_TEMPLATE_NONE @@ -168,6 +178,10 @@ if PKG_USING_CHERRYUSB bool "winusbv2_cdc" config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID bool "winusbv2_hid" + config PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB + bool "adb" + config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV + bool "cdc_acm_chardev" endchoice config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME diff --git a/components/drivers/usb/cherryusb/SConscript b/components/drivers/usb/cherryusb/SConscript index acbddefb4f..eba0a3e182 100644 --- a/components/drivers/usb/cherryusb/SConscript +++ b/components/drivers/usb/cherryusb/SConscript @@ -127,13 +127,17 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']): src += Glob('class/cdc/usbd_cdc_ncm.c') if GetDepend(['RT_CHERRYUSB_DEVICE_DFU']): src += Glob('class/dfu/usbd_dfu.c') + if GetDepend(['RT_CHERRYUSB_DEVICE_ADB']): + src += Glob('class/adb/usbd_adb.c') + src += Glob('platform/rtthread/usbd_adb_shell.c') + + if GetDepend(['RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV']): + src += Glob('platform/rtthread/usbd_serial.c') if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']): src += Glob('demo/cdc_acm_template.c') - if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC']): + if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC']) or GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']): src += Glob('demo/msc_ram_template.c') - if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']): - src += Glob('platform/rtthread/usbd_msc_blkdev.c') if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']): src += Glob('demo/hid_mouse_template.c') if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']): @@ -162,6 +166,10 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']): src += Glob('demo/winusb2.0_cdc_template.c') if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID']): src += Glob('demo/winusb2.0_hid_template.c') + if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_ADB']): + src += Glob('demo/adb/usbd_adb_template.c') + if GetDepend(['RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV']): + src += Glob('demo/cdc_acm_rttchardev_template.c') # USB HOST if GetDepend(['RT_CHERRYUSB_HOST']): @@ -285,6 +293,13 @@ if GetDepend(['RT_CHERRYUSB_HOST']): CPPDEFINES+=['TEST_USBH_MSC=0'] src += Glob('demo/usb_host.c') + if GetDepend(['RT_CHERRYUSB_HOST_CDC_ACM']) \ + or GetDepend(['RT_CHERRYUSB_HOST_FTDI']) \ + or GetDepend(['RT_CHERRYUSB_HOST_CH34X']) \ + or GetDepend(['RT_CHERRYUSB_HOST_CP210X']) \ + or GetDepend(['RT_CHERRYUSB_HOST_PL2303']): + src += Glob('platform/rtthread/usbh_serial.c') + if GetDepend('RT_USING_DFS') and GetDepend(['RT_CHERRYUSB_HOST_MSC']): src += Glob('platform/rtthread/usbh_dfs.c') 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 6bc19b2045..4bc7f81b01 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c @@ -350,6 +350,7 @@ static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf) switch (version) { case 0x400: ftdi_class->chip_type = FT232B; + break; case 0x500: ftdi_class->chip_type = FT2232C; break; diff --git a/components/drivers/usb/cherryusb/demo/adb/cherryadb.png b/components/drivers/usb/cherryusb/demo/adb/cherryadb.png deleted file mode 100644 index 512586b954..0000000000 Binary files a/components/drivers/usb/cherryusb/demo/adb/cherryadb.png and /dev/null differ diff --git a/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c b/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c index c5a2d9ef9b..24f6d7acb5 100644 --- a/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c +++ b/components/drivers/usb/cherryusb/demo/adb/usbd_adb_template.c @@ -164,7 +164,7 @@ static const char *string_descriptor_callback(uint8_t speed, uint8_t index) return string_descriptors[index]; } -const struct usb_descriptor msc_bootuf2_descriptor = { +const struct usb_descriptor adb_descriptor = { .device_descriptor_callback = device_descriptor_callback, .config_descriptor_callback = config_descriptor_callback, .device_quality_descriptor_callback = device_quality_descriptor_callback, @@ -274,9 +274,16 @@ static void usbd_event_handler(uint8_t busid, uint8_t event) static struct usbd_interface intf0; +#ifdef RT_USING_MSH +extern void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep); +#else extern int shell_init(bool need_login); +#endif void cherryadb_init(uint8_t busid, uint32_t reg_base) { +#ifdef RT_USING_MSH + usbd_adb_shell_init(WINUSB_IN_EP, WINUSB_OUT_EP); +#else /* default password is : 12345678 */ /* shell_init() must be called in-task */ if (0 != shell_init(false)) { @@ -286,7 +293,7 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base) ; } } - +#endif #ifdef CONFIG_USBDEV_ADVANCE_DESC usbd_desc_register(busid, &adb_descriptor); #else @@ -297,4 +304,4 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base) #endif usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP)); usbd_initialize(busid, reg_base, usbd_event_handler); -} \ No newline at end of file +} diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_mavlink_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_mavlink_template.c new file mode 100644 index 0000000000..0a8bc3b66c --- /dev/null +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_mavlink_template.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbd_core.h" +#include "usbd_cdc_acm.h" +#include "chry_ringbuffer.h" +#include + +/*!< endpoint address */ +#define CDC_IN_EP 0x81 +#define CDC_OUT_EP 0x02 +#define CDC_INT_EP 0x83 + +#define USBD_VID 0xFFFF +#define USBD_PID 0xFFFF +#define USBD_MAX_POWER 100 +#define USBD_LANGID_STRING 1033 + +/*!< config descriptor size */ +#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) + +#ifdef CONFIG_USB_HS +#define CDC_MAX_MPS 512 +#else +#define CDC_MAX_MPS 64 +#endif + +#ifdef CONFIG_USBDEV_ADVANCE_DESC +static const uint8_t device_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01) +}; + +static const uint8_t config_descriptor[] = { + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02) +}; + +static const uint8_t device_quality_descriptor[] = { + /////////////////////////////////////// + /// device qualifier descriptor + /////////////////////////////////////// + 0x0a, + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, +}; + +static const char *string_descriptors[] = { + (const char[]){ 0x09, 0x04 }, /* Langid */ + "CherryUSB", /* Manufacturer */ + "CherryUSB CDC DEMO", /* Product */ + "2022123456", /* Serial Number */ +}; + +static const uint8_t *device_descriptor_callback(uint8_t speed) +{ + return device_descriptor; +} + +static const uint8_t *config_descriptor_callback(uint8_t speed) +{ + return config_descriptor; +} + +static const uint8_t *device_quality_descriptor_callback(uint8_t speed) +{ + return device_quality_descriptor; +} + +static const char *string_descriptor_callback(uint8_t speed, uint8_t index) +{ + if (index > 3) { + return NULL; + } + return string_descriptors[index]; +} + +const struct usb_descriptor cdc_descriptor = { + .device_descriptor_callback = device_descriptor_callback, + .config_descriptor_callback = config_descriptor_callback, + .device_quality_descriptor_callback = device_quality_descriptor_callback, + .string_descriptor_callback = string_descriptor_callback +}; +#else +/*!< global descriptor */ +static const uint8_t cdc_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02), + /////////////////////////////////////// + /// string0 descriptor + /////////////////////////////////////// + USB_LANGID_INIT(USBD_LANGID_STRING), + /////////////////////////////////////// + /// string1 descriptor + /////////////////////////////////////// + 0x14, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + /////////////////////////////////////// + /// string2 descriptor + /////////////////////////////////////// + 0x26, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'C', 0x00, /* wcChar10 */ + 'D', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ + 'O', 0x00, /* wcChar17 */ + /////////////////////////////////////// + /// string3 descriptor + /////////////////////////////////////// + 0x16, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + '2', 0x00, /* wcChar0 */ + '0', 0x00, /* wcChar1 */ + '2', 0x00, /* wcChar2 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ +#ifdef CONFIG_USB_HS + /////////////////////////////////////// + /// device qualifier descriptor + /////////////////////////////////////// + 0x0a, + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, +#endif + 0x00 +}; +#endif + +chry_ringbuffer_t usb_rx_rb; +uint8_t usb_rx_buffer[2048]; + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t temp_rx_buffer[512]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_tx_buffer[MAVLINK_MAX_PACKET_LEN]; + +volatile bool ep_tx_busy_flag = false; + +static void usbd_event_handler(uint8_t busid, uint8_t event) +{ + switch (event) { + case USBD_EVENT_RESET: + break; + case USBD_EVENT_CONNECTED: + break; + case USBD_EVENT_DISCONNECTED: + break; + case USBD_EVENT_RESUME: + break; + case USBD_EVENT_SUSPEND: + break; + case USBD_EVENT_CONFIGURED: + ep_tx_busy_flag = false; + /* setup first out ep read transfer */ + usbd_ep_start_read(busid, CDC_OUT_EP, temp_rx_buffer, usbd_get_ep_mps(busid, CDC_OUT_EP)); + break; + case USBD_EVENT_SET_REMOTE_WAKEUP: + break; + case USBD_EVENT_CLR_REMOTE_WAKEUP: + break; + + default: + break; + } +} + +void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) +{ + USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes); + + chry_ringbuffer_write(&usb_rx_rb, temp_rx_buffer, nbytes); + usbd_ep_start_read(busid, CDC_OUT_EP, temp_rx_buffer, usbd_get_ep_mps(busid, CDC_OUT_EP)); +} + +void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) +{ + USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes); + + if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) { + /* send zlp */ + usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0); + } else { + ep_tx_busy_flag = false; + } +} + +/*!< endpoint call back */ +struct usbd_endpoint cdc_out_ep = { + .ep_addr = CDC_OUT_EP, + .ep_cb = usbd_cdc_acm_bulk_out +}; + +struct usbd_endpoint cdc_in_ep = { + .ep_addr = CDC_IN_EP, + .ep_cb = usbd_cdc_acm_bulk_in +}; + +static struct usbd_interface intf0; +static struct usbd_interface intf1; + +void cdc_acm_mavlink_init(uint8_t busid, uintptr_t reg_base) +{ + chry_ringbuffer_init(&usb_rx_rb, usb_rx_buffer, sizeof(usb_rx_buffer)); +#ifdef CONFIG_USBDEV_ADVANCE_DESC + usbd_desc_register(busid, &cdc_descriptor); +#else + usbd_desc_register(busid, cdc_descriptor); +#endif + usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0)); + usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1)); + usbd_add_endpoint(busid, &cdc_out_ep); + usbd_add_endpoint(busid, &cdc_in_ep); + usbd_initialize(busid, reg_base, usbd_event_handler); +} + +void cdc_acm_mavlink_write(uint8_t *data, uint32_t len) +{ + if (!usb_device_is_configured(0)) { + return; + } + ep_tx_busy_flag = true; + usbd_ep_start_write(0, CDC_IN_EP, data, len); + while (ep_tx_busy_flag) { + } +} + +void send_heartbeat(void) +{ + mavlink_message_t message; + + const uint8_t system_id = 42; + const uint8_t base_mode = 0; + const uint8_t custom_mode = 0; + mavlink_msg_heartbeat_pack_chan( + system_id, + MAV_COMP_ID_PERIPHERAL, + MAVLINK_COMM_0, + &message, + MAV_TYPE_GENERIC, + MAV_AUTOPILOT_GENERIC, + base_mode, + custom_mode, + MAV_STATE_STANDBY); + + const int len = mavlink_msg_to_send_buffer(usb_tx_buffer, &message); + cdc_acm_mavlink_write(usb_tx_buffer, len); +} + +void handle_heartbeat(const mavlink_message_t *message) +{ + mavlink_heartbeat_t heartbeat; + mavlink_msg_heartbeat_decode(message, &heartbeat); + + USB_LOG_RAW("Got heartbeat from "); + switch (heartbeat.autopilot) { + case MAV_AUTOPILOT_GENERIC: + USB_LOG_RAW("generic"); + break; + case MAV_AUTOPILOT_ARDUPILOTMEGA: + USB_LOG_RAW("ArduPilot"); + break; + case MAV_AUTOPILOT_PX4: + USB_LOG_RAW("PX4"); + break; + default: + USB_LOG_RAW("other"); + break; + } + USB_LOG_RAW(" autopilot\n"); + + send_heartbeat(); +} + +void mavlink_polling(void) +{ + uint8_t ch; + bool ret; + mavlink_message_t message; + mavlink_status_t status; + + ret = chry_ringbuffer_read_byte(&usb_rx_rb, &ch); + if (ret) { + if (mavlink_parse_char(MAVLINK_COMM_0, ch, &message, &status) == 1) { + USB_LOG_INFO( + "Received message %d from %d/%d\n", + message.msgid, message.sysid, message.compid); + + switch (message.msgid) { + case MAVLINK_MSG_ID_HEARTBEAT: + handle_heartbeat(&message); + break; + } + } + } +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_rttchardev_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_rttchardev_template.c new file mode 100644 index 0000000000..f5fec3f0ea --- /dev/null +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_rttchardev_template.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbd_core.h" +#include "usbd_cdc_acm.h" + +/*!< endpoint address */ +#define CDC_IN_EP 0x81 +#define CDC_OUT_EP 0x02 +#define CDC_INT_EP 0x83 + +#define USBD_VID 0xFFFF +#define USBD_PID 0xFFFF +#define USBD_MAX_POWER 100 +#define USBD_LANGID_STRING 1033 + +/*!< config descriptor size */ +#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) + +#ifdef CONFIG_USB_HS +#define CDC_MAX_MPS 512 +#else +#define CDC_MAX_MPS 64 +#endif + +#ifdef CONFIG_USBDEV_ADVANCE_DESC +static const uint8_t device_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01) +}; + +static const uint8_t config_descriptor[] = { + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02) +}; + +static const uint8_t device_quality_descriptor[] = { + /////////////////////////////////////// + /// device qualifier descriptor + /////////////////////////////////////// + 0x0a, + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, +}; + +static const char *string_descriptors[] = { + (const char[]){ 0x09, 0x04 }, /* Langid */ + "CherryUSB", /* Manufacturer */ + "CherryUSB CDC DEMO", /* Product */ + "2022123456", /* Serial Number */ +}; + +static const uint8_t *device_descriptor_callback(uint8_t speed) +{ + return device_descriptor; +} + +static const uint8_t *config_descriptor_callback(uint8_t speed) +{ + return config_descriptor; +} + +static const uint8_t *device_quality_descriptor_callback(uint8_t speed) +{ + return device_quality_descriptor; +} + +static const char *string_descriptor_callback(uint8_t speed, uint8_t index) +{ + if (index > 3) { + return NULL; + } + return string_descriptors[index]; +} + +const struct usb_descriptor cdc_descriptor = { + .device_descriptor_callback = device_descriptor_callback, + .config_descriptor_callback = config_descriptor_callback, + .device_quality_descriptor_callback = device_quality_descriptor_callback, + .string_descriptor_callback = string_descriptor_callback +}; +#else +/*!< global descriptor */ +static const uint8_t cdc_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02), + /////////////////////////////////////// + /// string0 descriptor + /////////////////////////////////////// + USB_LANGID_INIT(USBD_LANGID_STRING), + /////////////////////////////////////// + /// string1 descriptor + /////////////////////////////////////// + 0x14, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + /////////////////////////////////////// + /// string2 descriptor + /////////////////////////////////////// + 0x26, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'C', 0x00, /* wcChar10 */ + 'D', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ + 'O', 0x00, /* wcChar17 */ + /////////////////////////////////////// + /// string3 descriptor + /////////////////////////////////////// + 0x16, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + '2', 0x00, /* wcChar0 */ + '0', 0x00, /* wcChar1 */ + '2', 0x00, /* wcChar2 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ +#ifdef CONFIG_USB_HS + /////////////////////////////////////// + /// device qualifier descriptor + /////////////////////////////////////// + 0x0a, + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, +#endif + 0x00 +}; +#endif + +static void usbd_event_handler(uint8_t busid, uint8_t event) +{ + switch (event) { + case USBD_EVENT_RESET: + break; + case USBD_EVENT_CONNECTED: + break; + case USBD_EVENT_DISCONNECTED: + break; + case USBD_EVENT_RESUME: + break; + case USBD_EVENT_SUSPEND: + break; + case USBD_EVENT_CONFIGURED: + + break; + case USBD_EVENT_SET_REMOTE_WAKEUP: + break; + case USBD_EVENT_CLR_REMOTE_WAKEUP: + break; + + default: + break; + } +} + +extern void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep); + +void cdc_acm_chardev_init(uint8_t busid, uintptr_t reg_base) +{ +#ifdef CONFIG_USBDEV_ADVANCE_DESC + usbd_desc_register(busid, &cdc_descriptor); +#else + usbd_desc_register(busid, cdc_descriptor); +#endif + usbd_cdc_acm_serial_init(busid, CDC_IN_EP, CDC_OUT_EP); + usbd_initialize(busid, reg_base, usbd_event_handler); +} \ 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 f446391f18..1019e0541c 100644 --- a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c @@ -135,7 +135,7 @@ uint8_t USBD_BinaryObjectStoreDescriptor[USBD_BOS_WTOTALLENGTH] = { struct usb_webusb_descriptor webusb_url_desc = { .vendor_code = USBD_WEBUSB_VENDOR_CODE, .string = USBD_WebUSBURLDescriptor, - .string_len = USBD_WINUSB_DESC_SET_LEN + .string_len = URL_DESCRIPTOR_LENGTH }; struct usb_msosv2_descriptor msosv2_desc = { diff --git a/components/drivers/usb/cherryusb/platform/README.md b/components/drivers/usb/cherryusb/platform/README.md index 35f0cdd795..3d7d8808f7 100644 --- a/components/drivers/usb/cherryusb/platform/README.md +++ b/components/drivers/usb/cherryusb/platform/README.md @@ -18,7 +18,8 @@ lwip support with usb host net class(cdc_ecm/cdc_ncm/cdc_rndis/asix/rtl8152/bl61 - DFS support with usb host msc. - lwip support with usb host net class(cdc_ecm/cdc_ncm/cdc_rndis/asix/rtl8152/bl616_wifi). - msh support with lsusb - +- device char support with host cdc_acm/ftdi/ch34x/cp210x/pl2303 +- shell support with adb ## Nuttx diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c index 4a598fe6c0..b37b93f115 100644 --- a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c +++ b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2022 ~ 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "rtthread.h" #include "usb_config.h" diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usbd_adb_shell.c b/components/drivers/usb/cherryusb/platform/rtthread/usbd_adb_shell.c new file mode 100644 index 0000000000..4ab7f59af3 --- /dev/null +++ b/components/drivers/usb/cherryusb/platform/rtthread/usbd_adb_shell.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "usbd_core.h" +#include "usbd_adb.h" + +#ifndef CONFIG_USBDEV_SHELL_RX_BUFSIZE +#define CONFIG_USBDEV_SHELL_RX_BUFSIZE (2048) +#endif + +struct usbd_adb_shell { + struct rt_device parent; + usb_osal_sem_t tx_done; + struct rt_ringbuffer rx_rb; + rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SHELL_RX_BUFSIZE]; +} g_usbd_adb_shell; + +void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len) +{ + rt_ringbuffer_put(&g_usbd_adb_shell.rx_rb, data, len); + + if (g_usbd_adb_shell.parent.rx_indicate) { + g_usbd_adb_shell.parent.rx_indicate(&g_usbd_adb_shell.parent, len); + } +} + +void usbd_adb_notify_write_done(void) +{ + if (g_usbd_adb_shell.tx_done) { + usb_osal_sem_give(g_usbd_adb_shell.tx_done); + } +} + +static rt_err_t usbd_adb_shell_open(struct rt_device *dev, rt_uint16_t oflag) +{ + while (!usb_device_is_configured(0)) { + rt_thread_mdelay(10); + } + return RT_EOK; +} + +static rt_err_t usbd_adb_shell_close(struct rt_device *dev) +{ + if (g_usbd_adb_shell.tx_done) { + usb_osal_sem_give(g_usbd_adb_shell.tx_done); + } + + return RT_EOK; +} + +static rt_ssize_t usbd_adb_shell_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + return rt_ringbuffer_get(&g_usbd_adb_shell.rx_rb, (rt_uint8_t *)buffer, size); +} + +static rt_ssize_t usbd_adb_shell_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + int ret = 0; + + RT_ASSERT(dev != RT_NULL); + + if (!usb_device_is_configured(0)) { + return size; + } + + if (usbd_adb_can_write() && size) { + usb_osal_sem_reset(g_usbd_adb_shell.tx_done); + usbd_abd_write(ADB_SHELL_LOALID, buffer, size); + usb_osal_sem_take(g_usbd_adb_shell.tx_done, 0xffffffff); + } + + return size; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops usbd_adb_shell_ops = { + NULL, + usbd_adb_shell_open, + usbd_adb_shell_close, + usbd_adb_shell_read, + usbd_adb_shell_write, + NULL +}; +#endif + +void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep) +{ + rt_err_t ret; + struct rt_device *device; + + device = &(g_usbd_adb_shell.parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &usbd_adb_shell_ops; +#else + device->init = NULL; + device->open = usbd_adb_shell_open; + device->close = usbd_adb_shell_close; + device->read = usbd_adb_shell_read; + device->write = usbd_adb_shell_write; + device->control = NULL; +#endif + device->user_data = NULL; + + /* register a character device */ + ret = rt_device_register(device, "adb-sh", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE); + +#ifdef RT_USING_POSIX_DEVIO + /* set fops */ + device->fops = NULL; +#endif + + g_usbd_adb_shell.tx_done = usb_osal_sem_create(0); + rt_ringbuffer_init(&g_usbd_adb_shell.rx_rb, g_usbd_adb_shell.rx_rb_buffer, sizeof(g_usbd_adb_shell.rx_rb_buffer)); +} + +static int adb_enter(int argc, char **argv) +{ + (void)argc; + (void)argv; + + finsh_set_device("adb-sh"); + rt_console_set_device("adb-sh"); + + return 0; +} +MSH_CMD_EXPORT(adb_enter, adb_enter); + +static int adb_exit(int argc, char **argv) +{ + (void)argc; + (void)argv; + + usbd_adb_close(ADB_SHELL_LOALID); + + finsh_set_device(RT_CONSOLE_DEVICE_NAME); + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + + return 0; +} +MSH_CMD_EXPORT(adb_exit, adb_exit); diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usbd_serial.c b/components/drivers/usb/cherryusb/platform/rtthread/usbd_serial.c new file mode 100644 index 0000000000..5ce622091b --- /dev/null +++ b/components/drivers/usb/cherryusb/platform/rtthread/usbd_serial.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "usbd_core.h" +#include "usbd_cdc_acm.h" + +#define DEV_FORMAT_CDC_ACM "usb-acm%d" + +#ifndef CONFIG_USBDEV_MAX_CDC_ACM_CLASS +#define CONFIG_USBDEV_MAX_CDC_ACM_CLASS (4) +#endif + +#ifndef CONFIG_USBDEV_SERIAL_RX_BUFSIZE +#define CONFIG_USBDEV_SERIAL_RX_BUFSIZE (2048) +#endif + +struct usbd_serial { + struct rt_device parent; + uint8_t busid; + uint8_t in_ep; + uint8_t out_ep; + struct usbd_interface intf_ctrl; + struct usbd_interface intf_data; + usb_osal_sem_t tx_done; + uint8_t minor; + char name[32]; + struct rt_ringbuffer rx_rb; + rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SERIAL_RX_BUFSIZE]; +}; + +static uint32_t g_devinuse = 0; + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbd_serial_cdc_acm_rx_buf[CONFIG_USBDEV_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(512, CONFIG_USB_ALIGN_SIZE)]; + +static struct usbd_serial g_usbd_serial_cdc_acm[CONFIG_USBDEV_MAX_CDC_ACM_CLASS]; + +static struct usbd_serial *usbd_serial_alloc(void) +{ + uint8_t devno; + struct usbd_serial *serial; + + for (devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) { + if ((g_devinuse & (1U << devno)) == 0) { + g_devinuse |= (1U << devno); + + serial = &g_usbd_serial_cdc_acm[devno]; + memset(serial, 0, sizeof(struct usbd_serial)); + serial->minor = devno; + snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->minor); + return serial; + } + } + return NULL; +} + +static void usbd_serial_free(struct usbd_serial *serial) +{ + uint8_t devno = serial->minor; + + if (devno < 32) { + g_devinuse &= ~(1U << devno); + } + memset(serial, 0, sizeof(struct usbd_serial)); +} + +static rt_err_t usbd_serial_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct usbd_serial *serial; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbd_serial *)dev; + + if (!usb_device_is_configured(serial->busid)) { + USB_LOG_ERR("USB device is not configured\n"); + return -RT_EPERM; + } + + usbd_ep_start_read(serial->busid, serial->out_ep, + g_usbd_serial_cdc_acm_rx_buf[serial->minor], + usbd_get_ep_mps(serial->busid, serial->out_ep)); + return RT_EOK; +} + +static rt_ssize_t usbd_serial_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct usbd_serial *serial; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbd_serial *)dev; + + if (!usb_device_is_configured(serial->busid)) { + return -RT_EPERM; + } + + return rt_ringbuffer_get(&serial->rx_rb, (rt_uint8_t *)buffer, size); +} + +static rt_ssize_t usbd_serial_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct usbd_serial *serial; + int ret = 0; + rt_uint8_t *align_buf; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbd_serial *)dev; + + if (!usb_device_is_configured(serial->busid)) { + return -RT_EPERM; + } + align_buf = (rt_uint8_t *)buffer; + +#ifdef RT_USING_CACHE + if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { + align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE); + if (!align_buf) { + USB_LOG_ERR("serial get align buf failed\n"); + return 0; + } + + usb_memcpy(align_buf, buffer, size); + } +#endif + usb_osal_sem_reset(serial->tx_done); + usbd_ep_start_write(serial->busid, serial->in_ep, align_buf, size); + ret = usb_osal_sem_take(serial->tx_done, 3000); + if (ret < 0) { + USB_LOG_ERR("serial write timeout\n"); + ret = -RT_ETIMEOUT; + } else { + ret = size; + } + +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { + rt_free_align(align_buf); + } +#endif + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops usbd_serial_ops = { + NULL, + usbd_serial_open, + NULL, + usbd_serial_read, + usbd_serial_write, + NULL +}; +#endif + +rt_err_t usbd_serial_register(struct usbd_serial *serial, + void *data) +{ + rt_err_t ret; + struct rt_device *device; + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &usbd_serial_ops; +#else + device->init = NULL; + device->open = usbd_serial_open; + device->close = NULL; + device->read = usbd_serial_read; + device->write = usbd_serial_write; + device->control = NULL; +#endif + device->user_data = data; + + /* register a character device */ + ret = rt_device_register(device, serial->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE); + +#ifdef RT_USING_POSIX_DEVIO + /* set fops */ + device->fops = NULL; +#endif + rt_ringbuffer_init(&serial->rx_rb, serial->rx_rb_buffer, sizeof(serial->rx_rb_buffer)); + + return ret; +} + +void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) +{ + struct usbd_serial *serial; + + for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) { + serial = &g_usbd_serial_cdc_acm[devno]; + if (serial->out_ep == ep) { + rt_ringbuffer_put(&serial->rx_rb, g_usbd_serial_cdc_acm_rx_buf[serial->minor], nbytes); + break; + } + } +} + +void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) +{ + struct usbd_serial *serial; + + if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) { + /* send zlp */ + usbd_ep_start_write(busid, ep, NULL, 0); + } else { + for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) { + serial = &g_usbd_serial_cdc_acm[devno]; + if ((serial->in_ep == ep) && serial->tx_done) { + usb_osal_sem_give(serial->tx_done); + break; + } + } + } +} + +void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep) +{ + struct usbd_serial *serial; + + struct usbd_endpoint cdc_out_ep = { + .ep_addr = out_ep, + .ep_cb = usbd_cdc_acm_bulk_out + }; + + struct usbd_endpoint cdc_in_ep = { + .ep_addr = in_ep, + .ep_cb = usbd_cdc_acm_bulk_in + }; + + serial = usbd_serial_alloc(); + if (serial == NULL) { + USB_LOG_ERR("No more serial device available\n"); + return; + } + + serial->busid = busid; + serial->in_ep = in_ep; + serial->out_ep = out_ep; + serial->tx_done = usb_osal_sem_create(0); + + usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_ctrl)); + usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_data)); + usbd_add_endpoint(busid, &cdc_out_ep); + usbd_add_endpoint(busid, &cdc_in_ep); + + if (usbd_serial_register(serial, NULL) != RT_EOK) { + USB_LOG_ERR("Failed to register serial device\n"); + usbd_serial_free(serial); + return; + } + + USB_LOG_INFO("USB CDC ACM Serial Device %s initialized\n", serial->name); +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c b/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c index 7cdfe1165c..1344f53926 100644 --- a/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c +++ b/components/drivers/usb/cherryusb/platform/rtthread/usbh_dfs.c @@ -30,15 +30,15 @@ static rt_err_t rt_udisk_init(rt_device_t dev) return RT_EOK; } -static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer, - rt_size_t size) +static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer, + rt_size_t size) { struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data; int ret; rt_uint8_t *align_buf; align_buf = (rt_uint8_t *)buffer; -#ifdef RT_USING_CACHE +#ifdef CONFIG_USB_DCACHE_ENABLE if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE); if (!align_buf) { @@ -53,7 +53,7 @@ static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_kprintf("usb mass_storage read failed\n"); return 0; } -#ifdef RT_USING_CACHE +#ifdef CONFIG_USB_DCACHE_ENABLE if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { usb_memcpy(buffer, align_buf, size * msc_class->blocksize); rt_free_align(align_buf); @@ -62,15 +62,15 @@ static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer, return size; } -static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer, - rt_size_t size) +static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer, + rt_size_t size) { struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data; int ret; rt_uint8_t *align_buf; align_buf = (rt_uint8_t *)buffer; -#ifdef RT_USING_CACHE +#ifdef CONFIG_USB_DCACHE_ENABLE if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE); if (!align_buf) { @@ -86,7 +86,7 @@ static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_kprintf("usb mass_storage write failed\n"); return 0; } -#ifdef RT_USING_CACHE +#ifdef CONFIG_USB_DCACHE_ENABLE if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { rt_free_align(align_buf); } diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usbh_serial.c b/components/drivers/usb/cherryusb/platform/rtthread/usbh_serial.c new file mode 100644 index 0000000000..b2888ec8e6 --- /dev/null +++ b/components/drivers/usb/cherryusb/platform/rtthread/usbh_serial.c @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2025, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "usbh_core.h" +#include "usbh_cdc_acm.h" +#include "usbh_ftdi.h" +#include "usbh_cp210x.h" +#include "usbh_ch34x.h" +#include "usbh_pl2303.h" + +#define DEV_FORMAT_VENDOR "ttyUSB%d" +#define DEV_FORMAT_CDC_ACM "ttyACM%d" + +#define USBH_RX_MAX_SIZE 2048 + +#ifndef CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS +#define CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS (4) +#endif + +#ifndef CONFIG_USBHOST_SERIAL_RX_BUFSIZE +#define CONFIG_USBHOST_SERIAL_RX_BUFSIZE (USBH_RX_MAX_SIZE * 2) +#endif + +enum usbh_serial_type { + USBH_SERIAL_TYPE_CDC_ACM = 0, + USBH_SERIAL_TYPE_FTDI, + USBH_SERIAL_TYPE_CP210X, + USBH_SERIAL_TYPE_CH34X, + USBH_SERIAL_TYPE_PL2303, +}; + +struct usbh_serial { + struct rt_device parent; + enum usbh_serial_type type; + uint8_t minor; + char name[CONFIG_USBHOST_DEV_NAMELEN]; + struct rt_ringbuffer rx_rb; + rt_uint8_t rx_rb_buffer[CONFIG_USBHOST_SERIAL_RX_BUFSIZE]; +}; + +static uint32_t g_devinuse_vendor = 0; +static uint32_t g_devinuse_cdc_acm = 0; + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbh_serial_vendor_rx_buf[CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS][USB_ALIGN_UP(USBH_RX_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbh_serial_cdc_acm_rx_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(USBH_RX_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)]; + +static struct usbh_serial *usbh_serial_alloc(uint8_t type) +{ + uint8_t devno; + struct usbh_serial *serial; + + for (devno = 0; devno < CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS; devno++) { + if ((g_devinuse_vendor & (1U << devno)) == 0) { + g_devinuse_vendor |= (1U << devno); + + serial = rt_malloc(sizeof(struct usbh_serial)); + memset(serial, 0, sizeof(struct usbh_serial)); + serial->type = type; + serial->minor = devno; + snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_VENDOR, serial->minor); + return serial; + } + } + return NULL; +} + +static void usbh_serial_free(struct usbh_serial *serial) +{ + uint8_t devno = serial->minor; + + if (devno < 32) { + g_devinuse_vendor &= ~(1U << devno); + } + memset(serial, 0, sizeof(struct usbh_serial)); + rt_free(serial); +} + +static struct usbh_serial *usbh_serial_cdc_acm_alloc(uint8_t type) +{ + uint8_t devno; + struct usbh_serial *serial; + + for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) { + if ((g_devinuse_cdc_acm & (1U << devno)) == 0) { + g_devinuse_cdc_acm |= (1U << devno); + + serial = rt_malloc(sizeof(struct usbh_serial)); + memset(serial, 0, sizeof(struct usbh_serial)); + serial->type = type; + serial->minor = devno; + snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->minor); + return serial; + } + } + return NULL; +} + +static void usbh_serial_cdc_acm_free(struct usbh_serial *serial) +{ + uint8_t devno = serial->minor; + + if (devno < 32) { + g_devinuse_cdc_acm &= ~(1U << devno); + } + memset(serial, 0, sizeof(struct usbh_serial)); + rt_free(serial); +} + +static rt_err_t usbh_serial_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct usbh_serial *serial; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbh_serial *)dev; + + switch (serial->type) { + case USBH_SERIAL_TYPE_CDC_ACM: + break; + case USBH_SERIAL_TYPE_FTDI: + break; + case USBH_SERIAL_TYPE_CP210X: + break; + case USBH_SERIAL_TYPE_CH34X: + break; + case USBH_SERIAL_TYPE_PL2303: + break; + + default: + break; + } + + return RT_EOK; +} + +static rt_err_t usbh_serial_close(struct rt_device *dev) +{ + struct usbh_serial *serial; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbh_serial *)dev; + + switch (serial->type) { + case USBH_SERIAL_TYPE_CDC_ACM: + break; + case USBH_SERIAL_TYPE_FTDI: + break; + case USBH_SERIAL_TYPE_CP210X: + break; + case USBH_SERIAL_TYPE_CH34X: + break; + case USBH_SERIAL_TYPE_PL2303: + break; + + default: + break; + } + + return RT_EOK; +} + +static rt_ssize_t usbh_serial_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct usbh_serial *serial; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbh_serial *)dev; + + return rt_ringbuffer_get(&serial->rx_rb, (rt_uint8_t *)buffer, size); +} + +static rt_ssize_t usbh_serial_write(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct usbh_serial *serial; + int ret = 0; + rt_uint8_t *align_buf; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbh_serial *)dev; + + align_buf = (rt_uint8_t *)buffer; +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { + align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE); + if (!align_buf) { + USB_LOG_ERR("serial get align buf failed\n"); + return 0; + } + + usb_memcpy(align_buf, buffer, size); + } +#endif + + switch (serial->type) { +#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM) + case USBH_SERIAL_TYPE_CDC_ACM: + ret = usbh_cdc_acm_bulk_out_transfer((struct usbh_cdc_acm *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER); + if (ret < 0) { + USB_LOG_ERR("usbh_cdc_acm_bulk_out_transfer failed: %d\n", ret); +#ifdef CONFIG_USB_DCACHE_ENABLE + rt_free_align(align_buf); +#endif + return 0; + } + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI) + case USBH_SERIAL_TYPE_FTDI: + ret = usbh_ftdi_bulk_out_transfer((struct usbh_ftdi *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER); + if (ret < 0) { + USB_LOG_ERR("usbh_ftdi_bulk_out_transfer failed: %d\n", ret); +#ifdef CONFIG_USB_DCACHE_ENABLE + rt_free_align(align_buf); +#endif + return 0; + } + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X) + case USBH_SERIAL_TYPE_CH34X: + ret = usbh_ch34x_bulk_out_transfer((struct usbh_ch34x *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER); + if (ret < 0) { + USB_LOG_ERR("usbh_ch34x_bulk_out_transfer failed: %d\n", ret); +#ifdef CONFIG_USB_DCACHE_ENABLE + rt_free_align(align_buf); +#endif + return 0; + } + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303) + case USBH_SERIAL_TYPE_PL2303: + ret = usbh_pl2303_bulk_out_transfer((struct usbh_pl2303 *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER); + if (ret < 0) { + USB_LOG_ERR("usbh_pl2303_bulk_out_transfer failed: %d\n", ret); +#ifdef CONFIG_USB_DCACHE_ENABLE + rt_free_align(align_buf); +#endif + return 0; + } + break; +#endif + default: + break; + } + +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) { + rt_free_align(align_buf); + } +#endif + + return ret; +} + +static rt_err_t usbh_serial_control(struct rt_device *dev, + int cmd, + void *args) +{ + struct usbh_serial *serial; + struct serial_configure *config; + struct cdc_line_coding line_coding; + int ret = -RT_EINVAL; + + RT_ASSERT(dev != RT_NULL); + + serial = (struct usbh_serial *)dev; + + switch (serial->type) { +#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM) + case USBH_SERIAL_TYPE_CDC_ACM: + if (cmd == RT_DEVICE_CTRL_CONFIG) { + struct usbh_cdc_acm *cdc_acm_class; + cdc_acm_class = (struct usbh_cdc_acm *)dev->user_data; + + config = (struct serial_configure *)args; + + line_coding.dwDTERate = config->baud_rate; + line_coding.bDataBits = config->data_bits; + line_coding.bCharFormat = 0; // STOP_BITS_1 + line_coding.bParityType = config->parity; + + usbh_cdc_acm_set_line_coding(cdc_acm_class, &line_coding); + } + + ret = RT_EOK; + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI) + case USBH_SERIAL_TYPE_FTDI: + if (cmd == RT_DEVICE_CTRL_CONFIG) { + struct usbh_ftdi *ftdi_class; + ftdi_class = (struct usbh_ftdi *)dev->user_data; + + config = (struct serial_configure *)args; + + line_coding.dwDTERate = config->baud_rate; + line_coding.bDataBits = config->data_bits; + line_coding.bCharFormat = 0; // STOP_BITS_1 + line_coding.bParityType = config->parity; + + usbh_ftdi_set_line_coding(ftdi_class, &line_coding); + } + + ret = RT_EOK; + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_CP210X) || defined(RT_CHERRYUSB_HOST_CP210X) + case USBH_SERIAL_TYPE_CP210X: + if (cmd == RT_DEVICE_CTRL_CONFIG) { + struct usbh_cp210x *cp210x_class; + cp210x_class = (struct usbh_cp210x *)dev->user_data; + + config = (struct serial_configure *)args; + + line_coding.dwDTERate = config->baud_rate; + line_coding.bDataBits = config->data_bits; + line_coding.bCharFormat = 0; // STOP_BITS_1 + line_coding.bParityType = config->parity; + + usbh_cp210x_set_line_coding(cp210x_class, &line_coding); + } + + ret = RT_EOK; + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X) + case USBH_SERIAL_TYPE_CH34X: + if (cmd == RT_DEVICE_CTRL_CONFIG) { + struct usbh_ch34x *ch34x_class; + ch34x_class = (struct usbh_ch34x *)dev->user_data; + + config = (struct serial_configure *)args; + + line_coding.dwDTERate = config->baud_rate; + line_coding.bDataBits = config->data_bits; + line_coding.bCharFormat = 0; // STOP_BITS_1 + line_coding.bParityType = config->parity; + + usbh_ch34x_set_line_coding(ch34x_class, &line_coding); + } + + ret = RT_EOK; + break; +#endif +#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303) + case USBH_SERIAL_TYPE_PL2303: + if (cmd == RT_DEVICE_CTRL_CONFIG) { + struct usbh_pl2303 *pl2303_class; + pl2303_class = (struct usbh_pl2303 *)dev->user_data; + + config = (struct serial_configure *)args; + + line_coding.dwDTERate = config->baud_rate; + line_coding.bDataBits = config->data_bits; + line_coding.bCharFormat = 0; // STOP_BITS_1 + line_coding.bParityType = config->parity; + + usbh_pl2303_set_line_coding(pl2303_class, &line_coding); + } + + ret = RT_EOK; + break; +#endif + default: + break; + } + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops usbh_serial_ops = { + NULL, + usbh_serial_open, + usbh_serial_close, + usbh_serial_read, + usbh_serial_write, + usbh_serial_control +}; +#endif + +#ifdef RT_USING_POSIX_DEVIO +#include +#include +#include +#include +#include + +#ifdef RT_USING_POSIX_TERMIOS +#include +#endif + +static rt_err_t usbh_serial_fops_rx_ind(rt_device_t dev, rt_size_t size) +{ + rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN); + + return RT_EOK; +} + +/* fops for serial */ +static int usbh_serial_fops_open(struct dfs_file *fd) +{ + rt_err_t ret = 0; + rt_uint16_t flags = 0; + rt_device_t device; + + device = (rt_device_t)fd->vnode->data; + RT_ASSERT(device != RT_NULL); + + switch (fd->flags & O_ACCMODE) + { + case O_RDONLY: + USB_LOG_DBG("fops open: O_RDONLY!"); + flags = RT_DEVICE_FLAG_RDONLY; + break; + case O_WRONLY: + USB_LOG_DBG("fops open: O_WRONLY!"); + flags = RT_DEVICE_FLAG_WRONLY; + break; + case O_RDWR: + USB_LOG_DBG("fops open: O_RDWR!"); + flags = RT_DEVICE_FLAG_RDWR; + break; + default: + USB_LOG_ERR("fops open: unknown mode - %d!", fd->flags & O_ACCMODE); + break; + } + + if ((fd->flags & O_ACCMODE) != O_WRONLY) + rt_device_set_rx_indicate(device, usbh_serial_fops_rx_ind); + ret = rt_device_open(device, flags); + if (ret == RT_EOK) return 0; + + return ret; +} + +static int usbh_serial_fops_close(struct dfs_file *fd) +{ + rt_device_t device; + + device = (rt_device_t)fd->vnode->data; + + rt_device_set_rx_indicate(device, RT_NULL); + rt_device_close(device); + + return 0; +} + +static int usbh_serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args) +{ + rt_device_t device; + int flags = (int)(rt_base_t)args; + int mask = O_NONBLOCK | O_APPEND; + + device = (rt_device_t)fd->vnode->data; + switch (cmd) + { + case FIONREAD: + break; + case FIONWRITE: + break; + case F_SETFL: + flags &= mask; + fd->flags &= ~mask; + fd->flags |= flags; + break; + } + + return rt_device_control(device, cmd, args); +} + +static int usbh_serial_fops_read(struct dfs_file *fd, void *buf, size_t count) +{ + int size = 0; + rt_device_t device; + + device = (rt_device_t)fd->vnode->data; + + do + { + size = rt_device_read(device, -1, buf, count); + if (size <= 0) + { + if (fd->flags & O_NONBLOCK) + { + size = -EAGAIN; + break; + } + + rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER); + } + }while (size <= 0); + + return size; +} + +static int usbh_serial_fops_write(struct dfs_file *fd, const void *buf, size_t count) +{ + rt_device_t device; + + device = (rt_device_t)fd->vnode->data; + return rt_device_write(device, -1, buf, count); +} + +static int usbh_serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req) +{ + int mask = 0; + int flags = 0; + rt_device_t device; + struct usbh_serial *serial; + + device = (rt_device_t)fd->vnode->data; + RT_ASSERT(device != RT_NULL); + + serial = (struct usbh_serial *)device; + + /* only support POLLIN */ + flags = fd->flags & O_ACCMODE; + if (flags == O_RDONLY || flags == O_RDWR) + { + rt_base_t level; + + rt_poll_add(&(device->wait_queue), req); + + level = rt_hw_interrupt_disable(); + + if (rt_ringbuffer_data_len(&serial->rx_rb)) + mask |= POLLIN; + rt_hw_interrupt_enable(level); + } + // mask|=POLLOUT; + return mask; +} + +const static struct dfs_file_ops usbh_serial_fops = +{ + usbh_serial_fops_open, + usbh_serial_fops_close, + usbh_serial_fops_ioctl, + usbh_serial_fops_read, + usbh_serial_fops_write, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + usbh_serial_fops_poll, +}; +#endif /* RT_USING_POSIX_DEVIO */ + +rt_err_t usbh_serial_register(struct usbh_serial *serial, + void *data) +{ + rt_err_t ret; + struct rt_device *device; + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &usbh_serial_ops; +#else + device->init = NULL; + device->open = usbh_serial_open; + device->close = usbh_serial_close; + device->read = usbh_serial_read; + device->write = usbh_serial_write; + device->control = usbh_serial_control; +#endif + device->user_data = data; + + /* register a character device */ + ret = rt_device_register(device, serial->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE); + +#ifdef RT_USING_POSIX_DEVIO + /* set fops */ + device->fops = &usbh_serial_fops; +#endif + rt_ringbuffer_init(&serial->rx_rb, serial->rx_rb_buffer, sizeof(serial->rx_rb_buffer)); + + return ret; +} + +void usbh_serial_unregister(struct usbh_serial *serial) +{ + RT_ASSERT(serial != NULL); + + rt_device_unregister(&serial->parent); + + if (serial->type == USBH_SERIAL_TYPE_CDC_ACM) { + usbh_serial_cdc_acm_free(serial); + } else { + usbh_serial_free(serial); + } +} + +#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM) +void usbh_cdc_acm_callback(void *arg, int nbytes) +{ + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg; + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &cdc_acm_class->bulkin_urb; + + if (nbytes > 0) { + serial = (struct usbh_serial *)cdc_acm_class->user_data; + rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_cdc_acm_rx_buf[serial->minor], nbytes); + + if (serial->parent.rx_indicate) { + serial->parent.rx_indicate(&serial->parent, nbytes); + } + + usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, g_usbh_serial_cdc_acm_rx_buf[serial->minor], sizeof(g_usbh_serial_cdc_acm_rx_buf[serial->minor]), 0, usbh_cdc_acm_callback, cdc_acm_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + } + } +} + +void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) +{ + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &cdc_acm_class->bulkin_urb; + + serial = usbh_serial_cdc_acm_alloc(USBH_SERIAL_TYPE_CDC_ACM); + cdc_acm_class->user_data = serial; + + usbh_serial_register(serial, cdc_acm_class); + + struct cdc_line_coding linecoding; + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_cdc_acm_set_line_coding(cdc_acm_class, &linecoding); + + usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, g_usbh_serial_cdc_acm_rx_buf[serial->minor], sizeof(g_usbh_serial_cdc_acm_rx_buf[serial->minor]), 0, usbh_cdc_acm_callback, cdc_acm_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + usbh_serial_unregister(serial); + return; + } +} + +void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) +{ + struct usbh_serial *serial; + + serial = (struct usbh_serial *)cdc_acm_class->user_data; + usbh_serial_unregister(serial); +} +#endif + +#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI) +void usbh_ftdi_callback(void *arg, int nbytes) +{ + struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)arg; + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &ftdi_class->bulkin_urb; + + if (nbytes >= 2) { + serial = (struct usbh_serial *)ftdi_class->user_data; + + nbytes -= 2; // Skip the first two bytes (header) + rt_ringbuffer_put(&serial->rx_rb, &g_usbh_serial_vendor_rx_buf[serial->minor][2], nbytes); + + if (serial->parent.rx_indicate && nbytes) { + serial->parent.rx_indicate(&serial->parent, nbytes); + } + + usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ftdi_callback, ftdi_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + } + } +} + +void usbh_ftdi_run(struct usbh_ftdi *ftdi_class) +{ + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &ftdi_class->bulkin_urb; + + serial = usbh_serial_alloc(USBH_SERIAL_TYPE_FTDI); + ftdi_class->user_data = serial; + + usbh_serial_register(serial, ftdi_class); + + struct cdc_line_coding linecoding; + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_ftdi_set_line_coding(ftdi_class, &linecoding); + + usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ftdi_callback, ftdi_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + usbh_serial_unregister(serial); + return; + } +} + +void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class) +{ + struct usbh_serial *serial; + + serial = (struct usbh_serial *)ftdi_class->user_data; + usbh_serial_unregister(serial); +} +#endif + +#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X) +void usbh_ch34x_callback(void *arg, int nbytes) +{ + struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)arg; + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &ch34x_class->bulkin_urb; + + if (nbytes > 0) { + serial = (struct usbh_serial *)ch34x_class->user_data; + rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes); + + if (serial->parent.rx_indicate) { + serial->parent.rx_indicate(&serial->parent, nbytes); + } + + usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ch34x_callback, ch34x_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + } + } +} + +void usbh_ch34x_run(struct usbh_ch34x *ch34x_class) +{ + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &ch34x_class->bulkin_urb; + + serial = usbh_serial_alloc(USBH_SERIAL_TYPE_CH34X); + ch34x_class->user_data = serial; + + usbh_serial_register(serial, ch34x_class); + + struct cdc_line_coding linecoding; + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_ch34x_set_line_coding(ch34x_class, &linecoding); + + usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ch34x_callback, ch34x_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + usbh_serial_unregister(serial); + return; + } +} + +void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class) +{ + struct usbh_serial *serial; + + serial = (struct usbh_serial *)ch34x_class->user_data; + usbh_serial_unregister(serial); +} +#endif + +#if defined(PKG_CHERRYUSB_HOST_CP210X) || defined(RT_CHERRYUSB_HOST_CP210X) +void usbh_cp210x_callback(void *arg, int nbytes) +{ + struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)arg; + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &cp210x_class->bulkin_urb; + + if (nbytes > 0) { + serial = (struct usbh_serial *)cp210x_class->user_data; + rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes); + + if (serial->parent.rx_indicate) { + serial->parent.rx_indicate(&serial->parent, nbytes); + } + + usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_cp210x_callback, cp210x_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + } + } +} + +void usbh_cp210x_run(struct usbh_cp210x *cp210x_class) +{ + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &cp210x_class->bulkin_urb; + + serial = usbh_serial_alloc(USBH_SERIAL_TYPE_CP210X); + cp210x_class->user_data = serial; + + usbh_serial_register(serial, cp210x_class); + + struct cdc_line_coding linecoding; + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_cp210x_set_line_coding(cp210x_class, &linecoding); + + usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_cp210x_callback, cp210x_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + usbh_serial_unregister(serial); + return; + } +} + +void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class) +{ + struct usbh_serial *serial; + + serial = (struct usbh_serial *)cp210x_class->user_data; + usbh_serial_unregister(serial); +} +#endif + +#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303) +void usbh_pl2303_callback(void *arg, int nbytes) +{ + struct usbh_pl2303 *pl2303_class = (struct usbh_pl2303 *)arg; + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &pl2303_class->bulkin_urb; + + if (nbytes > 0) { + serial = (struct usbh_serial *)pl2303_class->user_data; + rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes); + + if (serial->parent.rx_indicate) { + serial->parent.rx_indicate(&serial->parent, nbytes); + } + + usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_pl2303_callback, pl2303_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + } + } +} + +void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class) +{ + struct usbh_serial *serial; + int ret; + struct usbh_urb *urb = &pl2303_class->bulkin_urb; + + serial = usbh_serial_alloc(USBH_SERIAL_TYPE_PL2303); + pl2303_class->user_data = serial; + + usbh_serial_register(serial, pl2303_class); + + struct cdc_line_coding linecoding; + linecoding.dwDTERate = 115200; + linecoding.bDataBits = 8; + linecoding.bParityType = 0; + linecoding.bCharFormat = 0; + usbh_pl2303_set_line_coding(pl2303_class, &linecoding); + + usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_pl2303_callback, pl2303_class); + ret = usbh_submit_urb(urb); + if (ret < 0) { + USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret); + usbh_serial_unregister(serial); + return; + } +} + +void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class) +{ + struct usbh_serial *serial; + + serial = (struct usbh_serial *)pl2303_class->user_data; + usbh_serial_unregister(serial); +} +#endif \ No newline at end of file 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 9925f5e98b..ccaa743f91 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c @@ -178,7 +178,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) 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); + return ((1 << 23) | (1 << 24)); #else return 0; #endif @@ -205,6 +205,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 << 25); #else return 0; #endif @@ -252,4 +254,4 @@ void usb_dcache_flush(uintptr_t addr, size_t size) { SCB_CleanInvalidateDCache_by_Addr((void *)addr, size); } -#endif \ No newline at end of file +#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 46effd5655..09fd628f0b 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c @@ -324,16 +324,11 @@ static inline void dwc2_chan_transfer(struct usbh_bus *bus, uint8_t ch_num, uint static void dwc2_halt(struct usbh_bus *bus, uint8_t ch_num) { volatile uint32_t ChannelEna = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31; - volatile uint32_t HcEpType = (USB_OTG_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18; - volatile uint32_t SplitEna = (USB_OTG_HC(ch_num)->HCSPLT & USB_OTG_HCSPLT_SPLITEN) >> 31; volatile uint32_t count = 0U; volatile uint32_t value; - /* In buffer DMA, Channel disable must not be programmed for non-split periodic channels. - At the end of the next uframe/frame (in the worst case), the core generates a channel halted - and disables the channel automatically. */ - if ((((USB_OTG_GLB->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && (SplitEna == 0U)) && - ((ChannelEna == 0U) || (((HcEpType == HCCHAR_ISOC) || (HcEpType == HCCHAR_INTR))))) { + if (((USB_OTG_GLB->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && + (ChannelEna == 0U)) { return; } @@ -1397,4 +1392,4 @@ void USBH_IRQHandler(uint8_t busid) USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT; } } -} \ No newline at end of file +}