From 240594aa20031a2a06f5981c6c1ee703223f3f67 Mon Sep 17 00:00:00 2001 From: jzlv Date: Wed, 11 Jan 2023 20:35:55 +0800 Subject: [PATCH] [update][cherryusb] sync from cherryusb master --- components/cherryusb/CMakeLists.txt | 2 +- .../cherryusb/cherryusb_config_template.h | 49 ++- components/cherryusb/class/cdc/usbh_cdc_acm.c | 38 ++ components/cherryusb/class/cdc/usbh_cdc_acm.h | 2 + components/cherryusb/class/hid/usbh_hid.c | 32 +- components/cherryusb/class/hid/usbh_hid.h | 2 + components/cherryusb/class/hub/usbh_hub.c | 162 ++++---- components/cherryusb/class/hub/usbh_hub.h | 2 - components/cherryusb/class/msc/usbd_msc.c | 116 +----- components/cherryusb/class/msc/usbd_msc.h | 4 +- components/cherryusb/class/msc/usbh_msc.c | 12 + components/cherryusb/class/msc/usbh_msc.h | 2 + components/cherryusb/class/video/usbd_video.c | 5 +- components/cherryusb/class/video/usbh_video.c | 238 ++++++----- components/cherryusb/class/video/usbh_video.h | 20 +- components/cherryusb/common/usb_dc.h | 10 + components/cherryusb/common/usb_def.h | 28 +- components/cherryusb/common/usb_hc.h | 7 + components/cherryusb/common/usb_util.h | 4 +- components/cherryusb/core/usbd_core.c | 378 +++++++++++++++--- components/cherryusb/core/usbd_core.h | 15 + components/cherryusb/core/usbh_core.c | 27 +- components/cherryusb/core/usbh_core.h | 6 +- components/cherryusb/osal/usb_osal.h | 8 +- components/cherryusb/osal/usb_osal_freertos.c | 35 +- components/cherryusb/osal/usb_osal_rtthread.c | 31 +- components/cherryusb/port/ehci/usb_hc_ehci.c | 183 +++++---- examples/peripherals/usbhost/usb_host.c | 35 +- 28 files changed, 939 insertions(+), 514 deletions(-) diff --git a/components/cherryusb/CMakeLists.txt b/components/cherryusb/CMakeLists.txt index ee02dc6b..d19d3c77 100644 --- a/components/cherryusb/CMakeLists.txt +++ b/components/cherryusb/CMakeLists.txt @@ -1,4 +1,4 @@ -sdk_generate_library() +sdk_generate_library() sdk_add_include_directories(common) sdk_add_include_directories(osal) sdk_add_include_directories(core) diff --git a/components/cherryusb/cherryusb_config_template.h b/components/cherryusb/cherryusb_config_template.h index 7791fa20..adec67eb 100644 --- a/components/cherryusb/cherryusb_config_template.h +++ b/components/cherryusb/cherryusb_config_template.h @@ -6,6 +6,8 @@ #ifndef CHERRYUSB_CONFIG_H #define CHERRYUSB_CONFIG_H +#define CHERRYUSB_VERSION 0x000700 + /* ================ USB common Configuration ================ */ #define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__) @@ -42,6 +44,17 @@ /* Enable test mode */ // #define CONFIG_USBDEV_TEST_MODE +//#define CONFIG_USBDEV_TX_RX_THREAD + +#ifdef CONFIG_USBDEV_TX_RX_THREAD +#ifndef CONFIG_USBDEV_TX_RX_PRIO +#define CONFIG_USBDEV_TX_RX_PRIO 4 +#endif +#ifndef CONFIG_USBDEV_TX_RX_STACKSIZE +#define CONFIG_USBDEV_TX_RX_STACKSIZE 2048 +#endif +#endif + #ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE #define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 #endif @@ -58,18 +71,6 @@ #define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" #endif -// #define CONFIG_USBDEV_MSC_THREAD - -#ifdef CONFIG_USBDEV_MSC_THREAD -#ifndef CONFIG_USBDEV_MSC_STACKSIZE -#define CONFIG_USBDEV_MSC_STACKSIZE 2048 -#endif - -#ifndef CONFIG_USBDEV_MSC_PRIO -#define CONFIG_USBDEV_MSC_PRIO 4 -#endif -#endif - #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 #endif @@ -78,13 +79,31 @@ #define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 #endif +#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE +#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128 +#endif + +#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE +#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536 +#endif + +#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID +#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff +#endif + +#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC +#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB" +#endif + +#define CONFIG_USBDEV_RNDIS_USING_LWIP + /* ================ USB HOST Stack Configuration ================== */ #define CONFIG_USBHOST_MAX_RHPORTS 1 #define CONFIG_USBHOST_MAX_EXTHUBS 1 #define CONFIG_USBHOST_MAX_EHPORTS 4 #define CONFIG_USBHOST_MAX_INTERFACES 6 -#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8 +#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1 #define CONFIG_USBHOST_MAX_ENDPOINTS 4 #define CONFIG_USBHOST_DEV_NAMELEN 16 @@ -121,8 +140,8 @@ /* ================ EHCI Configuration ================ */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) +#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) +#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) #define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE diff --git a/components/cherryusb/class/cdc/usbh_cdc_acm.c b/components/cherryusb/class/cdc/usbh_cdc_acm.c index 77300a9c..825b7cbf 100644 --- a/components/cherryusb/class/cdc/usbh_cdc_acm.c +++ b/components/cherryusb/class/cdc/usbh_cdc_acm.c @@ -146,6 +146,7 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname); + usbh_cdc_acm_run(cdc_acm_class); return ret; } @@ -166,6 +167,7 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_pipe_free(cdc_acm_class->bulkout); } + usbh_cdc_acm_stop(cdc_acm_class); memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm)); usb_free(cdc_acm_class); @@ -176,12 +178,38 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } +static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf) +{ + return 0; +} + +static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + return 0; +} + +__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) +{ + +} + +__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) +{ + +} + const struct usbh_class_driver cdc_acm_class_driver = { .driver_name = "cdc_acm", .connect = usbh_cdc_acm_connect, .disconnect = usbh_cdc_acm_disconnect }; +const struct usbh_class_driver cdc_data_class_driver = { + .driver_name = "cdc_data", + .connect = usbh_cdc_data_connect, + .disconnect = usbh_cdc_data_disconnect +}; + CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, .class = USB_DEVICE_CLASS_CDC, @@ -191,3 +219,13 @@ CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = { .pid = 0x00, .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, + .vid = 0x00, + .pid = 0x00, + .class_driver = &cdc_data_class_driver +}; diff --git a/components/cherryusb/class/cdc/usbh_cdc_acm.h b/components/cherryusb/class/cdc/usbh_cdc_acm.h index eda1ea93..92daf7bf 100644 --- a/components/cherryusb/class/cdc/usbh_cdc_acm.h +++ b/components/cherryusb/class/cdc/usbh_cdc_acm.h @@ -32,6 +32,8 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding); int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts); +void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class); +void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class); #ifdef __cplusplus } #endif diff --git a/components/cherryusb/class/hid/usbh_hid.c b/components/cherryusb/class/hid/usbh_hid.c index 1ad95f1f..4fb4a534 100644 --- a/components/cherryusb/class/hid/usbh_hid.c +++ b/components/cherryusb/class/hid/usbh_hid.c @@ -148,7 +148,8 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) USB_LOG_INFO("Register HID Class:%s\r\n", hport->config.intf[intf].devname); - return 0; + usbh_hid_run(hid_class); + return ret; } int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) @@ -168,6 +169,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_pipe_free(hid_class->intout); } + usbh_hid_stop(hid_class); memset(hid_class, 0, sizeof(struct usbh_hid)); usb_free(hid_class); @@ -178,27 +180,27 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } +__WEAK void usbh_hid_run(struct usbh_hid *hid_class) +{ + +} + +__WEAK void usbh_hid_stop(struct usbh_hid *hid_class) +{ + +} + const struct usbh_class_driver hid_class_driver = { .driver_name = "hid", .connect = usbh_hid_connect, .disconnect = usbh_hid_disconnect }; -CLASS_INFO_DEFINE const struct usbh_class_info hid_keyboard_class_info = { - .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, +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 = HID_SUBCLASS_BOOTIF, - .protocol = HID_PROTOCOL_KEYBOARD, - .vid = 0x00, - .pid = 0x00, - .class_driver = &hid_class_driver -}; - -CLASS_INFO_DEFINE const struct usbh_class_info hid_mouse_class_info = { - .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_HID, - .subclass = HID_SUBCLASS_BOOTIF, - .protocol = HID_PROTOCOL_MOUSE, + .subclass = 0x00, + .protocol = 0x00, .vid = 0x00, .pid = 0x00, .class_driver = &hid_class_driver diff --git a/components/cherryusb/class/hid/usbh_hid.h b/components/cherryusb/class/hid/usbh_hid.h index 74e8b408..b2b41fb3 100644 --- a/components/cherryusb/class/hid/usbh_hid.h +++ b/components/cherryusb/class/hid/usbh_hid.h @@ -25,6 +25,8 @@ extern "C" { int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration); int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer); +void usbh_hid_run(struct usbh_hid *hid_class); +void usbh_hid_stop(struct usbh_hid *hid_class); #ifdef __cplusplus } #endif diff --git a/components/cherryusb/class/hub/usbh_hub.c b/components/cherryusb/class/hub/usbh_hub.c index b6211217..8677320d 100644 --- a/components/cherryusb/class/hub/usbh_hub.c +++ b/components/cherryusb/class/hub/usbh_hub.c @@ -5,35 +5,37 @@ */ #include "usbh_hub.h" -#define DEV_FORMAT "/dev/hub%d" +#define DEV_FORMAT "/dev/hub%d" -#define DEBOUNCE_TIMEOUT 400 -#define DEBOUNCE_TIME_STEP 25 +#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 100 #define DELAY_TIME_AFTER_RESET 200 -#define EXTHUB_FIRST_INDEX 2 +#define EXTHUB_FIRST_INDEX 2 static uint32_t g_devinuse = 0; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32]; -usb_slist_t hub_event_head = USB_SLIST_OBJECT_INIT(hub_event_head); usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head); -usb_osal_sem_t hub_event_wait; usb_osal_thread_t hub_thread; +usb_osal_mq_t hub_mq; USB_NOCACHE_RAM_SECTION struct usbh_hub roothub; -struct usbh_hubport roothub_parent_port; +#if CONFIG_USBHOST_MAX_EXTHUBS > 0 USB_NOCACHE_RAM_SECTION struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS]; - +#endif extern int usbh_hport_activate_ep0(struct usbh_hubport *hport); extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport); extern int usbh_enumerate(struct usbh_hubport *hport); +static void usbh_hub_thread_wakeup(struct usbh_hub *hub); static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" }; +#if CONFIG_USBHOST_MAX_EXTHUBS > 0 static int usbh_hub_devno_alloc(void) { int devno; @@ -55,6 +57,17 @@ static void usbh_hub_devno_free(uint8_t devno) g_devinuse &= ~(1 << devno); } } +#endif + +static void usbh_hub_register(struct usbh_hub *hub) +{ + usb_slist_add_tail(&hub_class_head, &hub->list); +} + +static void usbh_hub_unregister(struct usbh_hub *hub) +{ + usb_slist_remove(&hub_class_head, &hub->list); +} static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer) { @@ -225,12 +238,7 @@ static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t fe } } -static void usbh_hub_thread_wakeup(struct usbh_hub *hub) -{ - usb_slist_add_tail(&hub_event_head, &hub->hub_event_list); - usb_osal_sem_give(hub_event_wait); -} - +#if CONFIG_USBHOST_MAX_EXTHUBS > 0 static void hub_int_complete_callback(void *arg, int nbytes) { struct usbh_hub *hub = (struct usbh_hub *)arg; @@ -326,7 +334,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_hport_deactivate_ep0(child); for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { - ret = CLASS_DISCONNECT(child, i); + CLASS_DISCONNECT(child, i); } } @@ -342,20 +350,20 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) } return ret; } +#endif -static void usbh_roothub_register(void) +static void usbh_hubport_release(struct usbh_hubport *child) { - memset(&roothub, 0, sizeof(struct usbh_hub)); - memset(&roothub_parent_port, 0, sizeof(struct usbh_hubport)); - roothub_parent_port.port = 1; - roothub_parent_port.dev_addr = 1; - roothub.connected = true; - roothub.index = 1; - roothub.is_roothub = true; - roothub.parent = &roothub_parent_port; - roothub.hub_addr = roothub_parent_port.dev_addr; - roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS; - usbh_hub_register(&roothub); + if (child->connected) { + child->connected = false; + usbh_hport_deactivate_ep0(child); + for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { + if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { + CLASS_DISCONNECT(child, i); + } + } + child->config.config_desc.bNumInterfaces = 0; + } } static void usbh_hub_events(struct usbh_hub *hub) @@ -419,8 +427,7 @@ static void usbh_hub_events(struct usbh_hub *hub) if (portchange & HUB_PORT_STATUS_C_CONNECTION) { uint16_t connection = 0; uint16_t debouncestable = 0; - for (uint32_t debouncetime = 0; debouncetime < DEBOUNCE_TIMEOUT; debouncetime += DEBOUNCE_TIME_STEP) { - usb_osal_msleep(DEBOUNCE_TIME_STEP); + for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) { /* Read hub port status */ ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); if (ret < 0) { @@ -432,21 +439,29 @@ static void usbh_hub_events(struct usbh_hub *hub) portchange = port_status.wPortChange; USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange); - if ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection) { - if (connection) { - if (++debouncestable == 4) { - break; - } + + if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) && + ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) { + debouncestable += HUB_DEBOUNCE_STEP; + if (debouncestable >= HUB_DEBOUNCE_STABLE) { + break; } } else { debouncestable = 0; + connection = portstatus & HUB_PORT_STATUS_CONNECTION; } - connection = portstatus & HUB_PORT_STATUS_CONNECTION; - if (portchange & HUB_PORT_STATUS_C_CONNECTION) { usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION); } + + usb_osal_msleep(HUB_DEBOUNCE_STEP); + } + + /** check if debounce ok */ + if (debouncestable < HUB_DEBOUNCE_STABLE) { + USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1); + break; } /* Last, check connect status */ @@ -484,6 +499,8 @@ static void usbh_hub_events(struct usbh_hub *hub) } child = &hub->child[port]; + /** release child sources first */ + usbh_hubport_release(child); memset(child, 0, sizeof(struct usbh_hubport)); child->parent = hub; @@ -498,25 +515,22 @@ static void usbh_hub_events(struct usbh_hub *hub) } } else { USB_LOG_ERR("Failed to enable port %u\r\n", port + 1); + + child = &hub->child[port]; + /** release child sources */ + usbh_hubport_release(child); + continue; } } else { child = &hub->child[port]; - child->connected = false; - usbh_hport_deactivate_ep0(child); - for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { - if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { - CLASS_DISCONNECT(child, i); - } - } - - USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1); - usbh_device_unmount_done_callback(child); - child->config.config_desc.bNumInterfaces = 0; + /** release child sources */ + usbh_hubport_release(child); } } } + hub->int_buffer[0] = 0; /* Start next hub int transfer */ if (!hub->is_roothub && hub->connected) { usbh_submit_urb(&hub->intin_urb); @@ -525,48 +539,49 @@ static void usbh_hub_events(struct usbh_hub *hub) static void usbh_hub_thread(void *argument) { - size_t flags; + struct usbh_hub *hub; int ret = 0; usb_hc_init(); while (1) { - ret = usb_osal_sem_take(hub_event_wait, 0xffffffff); + ret = usb_osal_mq_recv(hub_mq, (uint32_t *)&hub, 0xffffffff); if (ret < 0) { continue; } - - while (!usb_slist_isempty(&hub_event_head)) { - struct usbh_hub *hub = usb_slist_first_entry(&hub_event_head, struct usbh_hub, hub_event_list); - flags = usb_osal_enter_critical_section(); - usb_slist_remove(&hub_event_head, &hub->hub_event_list); - usb_osal_leave_critical_section(flags); - usbh_hub_events(hub); - } + usbh_hub_events(hub); } } +static void usbh_roothub_register(void) +{ + memset(&roothub, 0, sizeof(struct usbh_hub)); + + roothub.connected = true; + roothub.index = 1; + roothub.is_roothub = true; + roothub.parent = NULL; + roothub.hub_addr = 1; + roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS; + usbh_hub_register(&roothub); +} + +static void usbh_hub_thread_wakeup(struct usbh_hub *hub) +{ + usb_osal_mq_send(hub_mq, (uint32_t)hub); +} + void usbh_roothub_thread_wakeup(uint8_t port) { roothub.int_buffer[0] |= (1 << port); usbh_hub_thread_wakeup(&roothub); } -void usbh_hub_register(struct usbh_hub *hub) -{ - usb_slist_add_tail(&hub_class_head, &hub->list); -} - -void usbh_hub_unregister(struct usbh_hub *hub) -{ - usb_slist_remove(&hub_class_head, &hub->list); -} - int usbh_hub_initialize(void) { usbh_roothub_register(); - hub_event_wait = usb_osal_sem_create(0); - if (hub_event_wait == NULL) { + hub_mq = usb_osal_mq_create(7); + if (hub_mq == NULL) { return -1; } @@ -576,19 +591,20 @@ int usbh_hub_initialize(void) } return 0; } - -const struct usbh_class_driver hub_driver = { +#if CONFIG_USBHOST_MAX_EXTHUBS > 0 +const struct usbh_class_driver hub_class_driver = { .driver_name = "hub", .connect = usbh_hub_connect, .disconnect = usbh_hub_disconnect }; -CLASS_INFO_DEFINE const struct usbh_class_info hub_info = { +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, .vid = 0x00, .pid = 0x00, - .class_driver = &hub_driver + .class_driver = &hub_class_driver }; +#endif diff --git a/components/cherryusb/class/hub/usbh_hub.h b/components/cherryusb/class/hub/usbh_hub.h index 41807de0..f46750d9 100644 --- a/components/cherryusb/class/hub/usbh_hub.h +++ b/components/cherryusb/class/hub/usbh_hub.h @@ -19,8 +19,6 @@ extern usb_slist_t hub_class_head; extern "C" { #endif void usbh_roothub_thread_wakeup(uint8_t port); -void usbh_hub_register(struct usbh_hub *hub); -void usbh_hub_unregister(struct usbh_hub *hub); int usbh_hub_initialize(void); #ifdef __cplusplus } diff --git a/components/cherryusb/class/msc/usbd_msc.c b/components/cherryusb/class/msc/usbd_msc.c index 9655c951..395bb90f 100644 --- a/components/cherryusb/class/msc/usbd_msc.c +++ b/components/cherryusb/class/msc/usbd_msc.c @@ -6,13 +6,6 @@ #include "usbd_core.h" #include "usbd_msc.h" #include "usb_scsi.h" -#ifdef CONFIG_USBDEV_MSC_THREAD -#include "usb_osal.h" -#endif - -#define MSC_THREAD_OP_READ_MEM 1 -#define MSC_THREAD_OP_WRITE_MEM 2 -#define MSC_THREAD_OP_WRITE_DONE 3 #define MSD_OUT_EP_IDX 0 #define MSD_IN_EP_IDX 1 @@ -49,13 +42,6 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv { uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE]; } usbd_msc_cfg; -#ifdef CONFIG_USBDEV_MSC_THREAD -static volatile uint8_t thread_op; -static usb_osal_sem_t msc_sem; -static usb_osal_thread_t msc_thread; -static volatile uint32_t current_byte_read; -#endif - static void usbd_msc_reset(void) { usbd_msc_cfg.stage = MSC_READ_CBW; @@ -635,17 +621,11 @@ static bool SCSI_processRead(void) transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE); - /* Start reading one sector */ -#ifdef CONFIG_USBDEV_MSC_THREAD - thread_op = MSC_THREAD_OP_READ_MEM; - usb_osal_sem_give(msc_sem); - return true; -#else if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) { SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA); return false; } -#endif + usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len); usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size); @@ -659,47 +639,15 @@ static bool SCSI_processRead(void) return true; } -#ifdef CONFIG_USBDEV_MSC_THREAD -static void usbd_msc_thread_memory_read_done(void) -{ - size_t flags; - uint32_t transfer_len; - - flags = usb_osal_enter_critical_section(); - - transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE); - - usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, - usbd_msc_cfg.block_buffer, transfer_len); - - usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size); - usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size); - usbd_msc_cfg.csw.dDataResidue -= transfer_len; - - if (usbd_msc_cfg.nsectors == 0) { - usbd_msc_cfg.stage = MSC_SEND_CSW; - } - usb_osal_leave_critical_section(flags); -} -#endif - static bool SCSI_processWrite(uint32_t nbytes) { uint32_t data_len = 0; USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector); - /* Start writing one sector */ -#ifdef CONFIG_USBDEV_MSC_THREAD - thread_op = MSC_THREAD_OP_WRITE_MEM; - current_byte_read = nbytes; - usb_osal_sem_give(msc_sem); - return true; -#else if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) { SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT); return false; } -#endif usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size); usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size); @@ -715,29 +663,6 @@ static bool SCSI_processWrite(uint32_t nbytes) return true; } -#ifdef CONFIG_USBDEV_MSC_THREAD -static void usbd_msc_thread_memory_write_done() -{ - size_t flags; - uint32_t data_len = 0; - - flags = usb_osal_enter_critical_section(); - - usbd_msc_cfg.start_sector += (current_byte_read / usbd_msc_cfg.scsi_blk_size); - usbd_msc_cfg.nsectors -= (current_byte_read / usbd_msc_cfg.scsi_blk_size); - usbd_msc_cfg.csw.dDataResidue -= current_byte_read; - - if (usbd_msc_cfg.nsectors == 0) { - usbd_msc_send_csw(CSW_STATUS_CMD_PASSED); - } else { - data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE); - usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len); - } - - usb_osal_leave_critical_section(flags); -} -#endif - static bool SCSI_CBWDecode(uint32_t nbytes) { uint8_t *buf2send = usbd_msc_cfg.block_buffer; @@ -883,35 +808,6 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes) } } -#ifdef CONFIG_USBDEV_MSC_THREAD -static void usbd_msc_thread(void *argument) -{ - uint32_t data_len = 0; - while (1) { - usb_osal_sem_take(msc_sem, 0xffffffff); - - switch (thread_op) { - case MSC_THREAD_OP_READ_MEM: - data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE); - if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) { - SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA); - } - usbd_msc_thread_memory_read_done(); - break; - case MSC_THREAD_OP_WRITE_MEM: - data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE); - if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) { - SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT); - } - usbd_msc_thread_memory_write_done(); - break; - default: - break; - } - } -} -#endif - struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep) { intf->class_interface_handler = msc_storage_class_interface_request_handler; @@ -935,14 +831,6 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin USB_LOG_ERR("msc block buffer overflow\r\n"); return NULL; } -#ifdef CONFIG_USBDEV_MSC_THREAD - msc_sem = usb_osal_sem_create(1); - msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbd_msc_thread, NULL); - if (msc_thread == NULL) { - USB_LOG_ERR("no enough memory to alloc msc thread\r\n"); - return NULL; - } -#endif return intf; } @@ -950,4 +838,4 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin void usbd_msc_set_readonly(bool readonly) { usbd_msc_cfg.readonly = readonly; -} \ No newline at end of file +} diff --git a/components/cherryusb/class/msc/usbd_msc.h b/components/cherryusb/class/msc/usbd_msc.h index 85453e60..824b4844 100644 --- a/components/cherryusb/class/msc/usbd_msc.h +++ b/components/cherryusb/class/msc/usbd_msc.h @@ -13,7 +13,9 @@ extern "C" { #endif /* Init msc interface driver */ -struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep); +struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, + const uint8_t out_ep, + const uint8_t in_ep); void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size); int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length); diff --git a/components/cherryusb/class/msc/usbh_msc.c b/components/cherryusb/class/msc/usbh_msc.c index 550b0c25..5c644322 100644 --- a/components/cherryusb/class/msc/usbh_msc.c +++ b/components/cherryusb/class/msc/usbh_msc.c @@ -371,6 +371,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname); + usbh_msc_run(msc_class); return ret; } @@ -391,6 +392,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_pipe_free(msc_class->bulkout); } + usbh_msc_stop(msc_class); memset(msc_class, 0, sizeof(struct usbh_msc)); usb_free(msc_class); @@ -401,6 +403,16 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } +__WEAK void usbh_msc_run(struct usbh_msc *msc_class) +{ + +} + +__WEAK void usbh_msc_stop(struct usbh_msc *msc_class) +{ + +} + const struct usbh_class_driver msc_class_driver = { .driver_name = "msc", .connect = usbh_msc_connect, diff --git a/components/cherryusb/class/msc/usbh_msc.h b/components/cherryusb/class/msc/usbh_msc.h index 5a61de7d..22b94d3b 100644 --- a/components/cherryusb/class/msc/usbh_msc.h +++ b/components/cherryusb/class/msc/usbh_msc.h @@ -25,6 +25,8 @@ struct usbh_msc { int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors); int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors); +void usbh_msc_run(struct usbh_msc *msc_class); +void usbh_msc_stop(struct usbh_msc *msc_class); #ifdef __cplusplus extern "C" { #endif diff --git a/components/cherryusb/class/video/usbd_video.c b/components/cherryusb/class/video/usbd_video.c index 156a81a8..be27bba5 100644 --- a/components/cherryusb/class/video/usbd_video.c +++ b/components/cherryusb/class/video/usbd_video.c @@ -742,7 +742,10 @@ void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_ usbd_video_cfg.commit.bMaxVersion = 0; } -struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize) +struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf, + uint32_t dwFrameInterval, + uint32_t dwMaxVideoFrameSize, + uint32_t dwMaxPayloadTransferSize) { intf->class_interface_handler = video_class_interface_request_handler; intf->class_endpoint_handler = NULL; diff --git a/components/cherryusb/class/video/usbh_video.c b/components/cherryusb/class/video/usbh_video.c index e6952ca2..eb64d0ab 100644 --- a/components/cherryusb/class/video/usbh_video.c +++ b/components/cherryusb/class/video/usbh_video.c @@ -6,16 +6,16 @@ #include "usbh_core.h" #include "usbh_video.h" -#define DEV_FORMAT "/dev/video%d" +#define DEV_FORMAT "/dev/video%d" /* general descriptor field offsets */ -#define DESC_bLength 0 /** Length offset */ -#define DESC_bDescriptorType 1 /** Descriptor type offset */ -#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */ -#define DESC_bNumFormats 3 /** Descriptor numformat offset */ -#define DESC_bNumFrameDescriptors 4 /** Descriptor numframe offset */ -#define DESC_bFormatIndex 3 /** Descriptor format index offset */ -#define DESC_bFrameIndex 3 /** Descriptor frame index offset */ +#define DESC_bLength 0 /** Length offset */ +#define DESC_bDescriptorType 1 /** Descriptor type offset */ +#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */ +#define DESC_bNumFormats 3 /** Descriptor numformat offset */ +#define DESC_bNumFrameDescriptors 4 /** Descriptor numframe offset */ +#define DESC_bFormatIndex 3 /** Descriptor format index offset */ +#define DESC_bFrameIndex 3 /** Descriptor frame index offset */ /* interface descriptor field offsets */ #define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */ @@ -32,7 +32,7 @@ static int __s_b_1732446u[256] = { 0 }; static int __s_g_337633u[256] = { 0 }; static int __s_g_698001v[256] = { 0 }; -static void inityuyv2rgb_table(void) +void usbh_video_inityuyv2rgb_table(void) { for (int i = 0; i < 256; i++) { __s_r_1370705v[i] = (1.370705 * (i - 128)); @@ -42,7 +42,7 @@ static void inityuyv2rgb_table(void) } } -static void yuyv2rgb565(void *input, void *output, uint32_t len) +void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len) { int y0, u, y1, v; uint8_t r, g, b; @@ -134,47 +134,84 @@ int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class) return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26); } -int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize) +int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex) { video_class->probe.bFormatIndex = formatindex; video_class->probe.bFrameIndex = frameindex; - video_class->probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize; - video_class->probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize; + video_class->probe.dwMaxPayloadTransferSize = 0; return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26); } -int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize) +int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex) { + memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls)); video_class->commit.bFormatIndex = formatindex; video_class->commit.bFrameIndex = frameindex; - video_class->commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize; - video_class->commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize; return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26); } -int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting) +int usbh_video_open(struct usbh_video *video_class, + uint8_t format_type, + uint16_t wWidth, + uint16_t wHeight, + uint8_t altsetting) { struct usb_setup_packet *setup = &video_class->hport->setup; struct usb_endpoint_descriptor *ep_desc; uint8_t mult; uint16_t mps; int ret; + bool found = false; + uint8_t formatidx = 0; + uint8_t frameidx = 0; if (video_class->is_opened) { return -EMFILE; } + for (uint8_t i = 0; i < video_class->num_of_formats; i++) { + if (format_type == video_class->format[i].format_type) { + formatidx = i + 1; + for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) { + if ((wWidth == video_class->format[i].frame[j].wWidth) && + (wHeight == video_class->format[i].frame[j].wHeight)) { + frameidx = j + 1; + found = true; + break; + } + } + } + } + + if (found == false) { + return -ENODEV; + } + if (altsetting > (video_class->num_of_intf_altsettings - 1)) { return -EINVAL; } - setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = USB_REQUEST_SET_INTERFACE; - setup->wValue = altsetting; - setup->wIndex = video_class->data_intf; - setup->wLength = 0; - - ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL); + ret = usbh_videostreaming_get_cur_probe(video_class); + if (ret < 0) { + return ret; + } + ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx); + if (ret < 0) { + return ret; + } + ret = usbh_videostreaming_get_cur_probe(video_class); + if (ret < 0) { + return ret; + } + ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx); + if (ret < 0) { + return ret; + } + ret = usbh_videostreaming_get_cur_probe(video_class); + if (ret < 0) { + return ret; + } + ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx); if (ret < 0) { return ret; } @@ -189,15 +226,46 @@ int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting) video_class->isoout_mps = mps * (mult + 1); usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc); } - USB_LOG_INFO("Open video and select altsetting:%u\r\n", altsetting); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = USB_REQUEST_SET_INTERFACE; + setup->wValue = altsetting; + setup->wIndex = video_class->data_intf; + setup->wLength = 0; + + ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting); video_class->is_opened = true; + video_class->current_format = format_type; return ret; } int usbh_video_close(struct usbh_video *video_class) { struct usb_setup_packet *setup = &video_class->hport->setup; - int ret; + int ret = 0; + + USB_LOG_INFO("Close video device\r\n"); + + if (video_class->is_opened == false) { + return 0; + } + + video_class->is_opened = false; + + if (video_class->isoin) { + usbh_pipe_free(video_class->isoin); + video_class->isoin = NULL; + } + + if (video_class->isoout) { + usbh_pipe_free(video_class->isoout); + video_class->isoout = NULL; + } setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = USB_REQUEST_SET_INTERFACE; @@ -209,24 +277,11 @@ int usbh_video_close(struct usbh_video *video_class) if (ret < 0) { return ret; } - if (video_class->isoin) { - usbh_pipe_free(video_class->isoin); - video_class->isoin = NULL; - } - - if (video_class->isoout) { - usbh_pipe_free(video_class->isoout); - video_class->isoout = NULL; - } - - USB_LOG_INFO("Close video device\r\n"); - video_class->is_opened = false; return ret; } void usbh_video_list_info(struct usbh_video *video_class) { - struct usbh_hubport *hport; struct usb_endpoint_descriptor *ep_desc; uint8_t mult; uint16_t mps; @@ -235,8 +290,6 @@ void usbh_video_list_info(struct usbh_video *video_class) USB_LOG_INFO("bcdVDC:%04x\r\n", video_class->bcdVDC); USB_LOG_INFO("Num of altsettings:%02x\r\n", video_class->num_of_intf_altsettings); - hport = video_class->hport; - for (uint8_t i = 1; i < video_class->num_of_intf_altsettings; i++) { ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc; @@ -266,18 +319,14 @@ void usbh_video_list_info(struct usbh_video *video_class) } } - usbh_videostreaming_get_cur_probe(video_class); - - USB_LOG_INFO("dwMaxVideoFrameSize:%u,dwMaxPayloadTransferSize:%u\r\n", (int)video_class->probe.dwMaxVideoFrameSize, (int)video_class->probe.dwMaxPayloadTransferSize); - USB_LOG_INFO("============= Video device information ===================\r\n"); } -static int usbh_video_ctrl_intf_connect(struct usbh_hubport *hport, uint8_t intf) +static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) { int ret; uint8_t cur_iface = 0xff; - uint8_t cur_alt_setting = 0xff; + // uint8_t cur_alt_setting = 0xff; uint8_t frame_index = 0xff; uint8_t format_index = 0xff; uint8_t num_of_frames = 0xff; @@ -378,14 +427,16 @@ static int usbh_video_ctrl_intf_connect(struct usbh_hubport *hport, uint8_t intf usbh_video_list_info(video_class); snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, video_class->minor); - +#ifdef CONFIG_USBHOST_UVC_YUV2RGB inityuyv2rgb_table(); +#endif USB_LOG_INFO("Register Video Class:%s\r\n", hport->config.intf[intf].devname); - return 0; + usbh_video_run(video_class); + return ret; } -static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t intf) +static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf) { int ret = 0; @@ -402,6 +453,7 @@ static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t i usbh_pipe_free(video_class->isoout); } + usbh_video_stop(video_class); memset(video_class, 0, sizeof(struct usbh_video)); usb_free(video_class); @@ -412,13 +464,12 @@ static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t i return ret; } -static int usbh_video_data_intf_connect(struct usbh_hubport *hport, uint8_t intf) +static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf) { - USB_LOG_WRN("Ignore video data intf\r\n"); return 0; } -static int usbh_video_data_intf_disconnect(struct usbh_hubport *hport, uint8_t intf) +static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf) { return 0; } @@ -427,9 +478,9 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre { struct usbh_iso_frame_packet *iso_packet; uint32_t num_of_iso_packets; - uint8_t *tmp_buf; uint8_t data_offset; uint32_t data_len; + uint8_t header_len = 0; num_of_iso_packets = urb->num_of_iso_packets; iso_packet = urb->iso_packet; @@ -448,11 +499,10 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre if (iso_packet[i].actual_length == 0) { /* skip no data */ continue; } - if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */ - while (1) { - } - } - if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */ + + header_len = iso_packet[i].transfer_buffer[0]; + + if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */ while (1) { } } @@ -461,20 +511,20 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre continue; } - data_offset = iso_packet[i].transfer_buffer[0]; - data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0]; - - tmp_buf = stream->bufbase + stream->bufoffset; - stream->bufoffset += data_len; - - memcpy(tmp_buf, &iso_packet[i].transfer_buffer[data_offset], data_len); - if ((stream->bufbase[0] != 0xff) && (stream->bufbase[1] != 0xd8)) { + if ((stream->bufoffset == 0) && (iso_packet[i].transfer_buffer[header_len] != 0xff) && (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8)) { stream->bufoffset = 0; continue; } + data_offset = iso_packet[i].transfer_buffer[0]; + data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0]; + + usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len); + + stream->bufoffset += data_len; + if (iso_packet[i].transfer_buffer[1] & (1 << 1)) { - if ((stream->bufbase[stream->bufoffset - 2] != 0xff) && (stream->bufbase[stream->bufoffset - 1] != 0xd9)) { + if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) && (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) { stream->bufoffset = 0; continue; } @@ -486,13 +536,13 @@ void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostre } } -void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream) +void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream) { struct usbh_iso_frame_packet *iso_packet; uint32_t num_of_iso_packets; - uint8_t *tmp_buf; uint8_t data_offset; uint32_t data_len; + uint8_t header_len = 0; num_of_iso_packets = urb->num_of_iso_packets; iso_packet = urb->iso_packet; @@ -512,11 +562,10 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid if (iso_packet[i].actual_length == 0) { /* skip no data */ continue; } - if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */ - while (1) { - } - } - if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */ + + header_len = iso_packet[i].transfer_buffer[0]; + + if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */ while (1) { } } @@ -528,10 +577,9 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid data_offset = iso_packet[i].transfer_buffer[0]; data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0]; - tmp_buf = stream->bufbase + stream->bufoffset; + usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len); stream->bufoffset += data_len; - yuyv2rgb565(&iso_packet[i].transfer_buffer[data_offset], tmp_buf, data_len); if (iso_packet[i].transfer_buffer[1] & (1 << 1)) { if (stream->video_one_frame_callback) { stream->video_one_frame_callback(stream); @@ -541,34 +589,46 @@ void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_vid } } -const struct usbh_class_driver video_class_ctrl_intf_driver = { - .driver_name = "video", - .connect = usbh_video_ctrl_intf_connect, - .disconnect = usbh_video_ctrl_intf_disconnect +__WEAK void usbh_video_run(struct usbh_video *video_class) +{ +} + +__WEAK void usbh_video_stop(struct usbh_video *video_class) +{ +} + +__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len) +{ +} + +const struct usbh_class_driver video_ctrl_class_driver = { + .driver_name = "video_ctrl", + .connect = usbh_video_ctrl_connect, + .disconnect = usbh_video_ctrl_disconnect }; -const struct usbh_class_driver video_class_data_intf_driver = { - .driver_name = "video", - .connect = usbh_video_data_intf_connect, - .disconnect = usbh_video_data_intf_disconnect +const struct usbh_class_driver video_streaming_class_driver = { + .driver_name = "video_streaming", + .connect = usbh_video_streaming_connect, + .disconnect = usbh_video_streaming_disconnect }; -CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_intf_class_info = { +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, .vid = 0x00, .pid = 0x00, - .class_driver = &video_class_ctrl_intf_driver + .class_driver = &video_ctrl_class_driver }; -CLASS_INFO_DEFINE const struct usbh_class_info video_data_intf_class_info = { +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, .vid = 0x00, .pid = 0x00, - .class_driver = &video_class_data_intf_driver + .class_driver = &video_streaming_class_driver }; \ No newline at end of file diff --git a/components/cherryusb/class/video/usbh_video.h b/components/cherryusb/class/video/usbh_video.h index 4cc0933a..34b986f3 100644 --- a/components/cherryusb/class/video/usbh_video.h +++ b/components/cherryusb/class/video/usbh_video.h @@ -41,6 +41,7 @@ struct usbh_video { uint16_t isoin_mps; uint16_t isoout_mps; bool is_opened; + uint8_t current_format; uint16_t bcdVDC; uint8_t num_of_intf_altsettings; uint8_t num_of_formats; @@ -51,19 +52,30 @@ struct usbh_video { extern "C" { #endif +void usbh_video_inityuyv2rgb_table(void); +void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len); + int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len); int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len); int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class); -int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize); -int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize); +int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex); +int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex); -int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting); +int usbh_video_open(struct usbh_video *video_class, + uint8_t format_type, + uint16_t wWidth, + uint16_t wHeight, + uint8_t altsetting); int usbh_video_close(struct usbh_video *video_class); void usbh_video_list_info(struct usbh_video *video_class); void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream); -void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream); +void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream); +void usbh_videostreaming_output(uint8_t *input, uint32_t input_len); + +void usbh_video_run(struct usbh_video *video_class); +void usbh_video_stop(struct usbh_video *video_class); #ifdef __cplusplus } diff --git a/components/cherryusb/common/usb_dc.h b/components/cherryusb/common/usb_dc.h index b11f8a68..ca45150a 100644 --- a/components/cherryusb/common/usb_dc.h +++ b/components/cherryusb/common/usb_dc.h @@ -21,6 +21,7 @@ struct usbd_endpoint_cfg { uint8_t ep_addr; /* Endpoint addr with direction */ uint8_t ep_type; /* Endpoint type */ uint16_t ep_mps; /* Endpoint max packet size */ + uint8_t ep_mult; /* Endpoint additional transcations in micro frame */ }; /** @@ -44,6 +45,15 @@ int usb_dc_deinit(void); */ int usbd_set_address(const uint8_t addr); +/** + * @brief Get USB device speed + * + * @param[in] port port index + * + * @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH + */ +uint8_t usbd_get_port_speed(const uint8_t port); + /** * @brief configure and enable endpoint. * diff --git a/components/cherryusb/common/usb_def.h b/components/cherryusb/common/usb_def.h index fdb17fb6..8ac691f7 100644 --- a/components/cherryusb/common/usb_def.h +++ b/components/cherryusb/common/usb_def.h @@ -548,6 +548,14 @@ struct usb_bos_header_descriptor { uint8_t bNumDeviceCaps; } __PACKED; +/* BOS Capability extension Descriptor*/ +struct usb_bos_capability_extension_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint32_t bmAttributes; +} __PACKED; + /* BOS Capability platform Descriptor */ struct usb_bos_capability_platform_descriptor { uint8_t bLength; @@ -557,6 +565,18 @@ struct usb_bos_capability_platform_descriptor { uint8_t PlatformCapabilityUUID[16]; } __PACKED; +/* BOS Capability superspeed Descriptor */ +struct usb_bos_capability_superspeed_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bmAttributes; + uint16_t wSpeedsSupported; + uint8_t bFunctionalitySupport; + uint8_t bU1DevExitLat; + uint16_t wU2DevExitLat; +} __PACKED; + /* BOS Capability MS OS Descriptors version 2 */ struct usb_bos_capability_msosv2_descriptor { uint32_t dwWindowsVersion; @@ -572,14 +592,6 @@ struct usb_bos_capability_webusb_descriptor { uint8_t iLandingPage; } __PACKED; -/* BOS Capability extension Descriptor*/ -struct usb_bos_capability_extension_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDevCapabilityType; - uint32_t bmAttributes; -} __PACKED; - /* Microsoft OS 2.0 Platform Capability Descriptor * See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/ * microsoft-defined-usb-descriptors diff --git a/components/cherryusb/common/usb_hc.h b/components/cherryusb/common/usb_hc.h index 9a2d4cd1..880149fe 100644 --- a/components/cherryusb/common/usb_hc.h +++ b/components/cherryusb/common/usb_hc.h @@ -56,6 +56,7 @@ struct usbh_urb { uint32_t timeout; int errorcode; uint32_t num_of_iso_packets; + uint32_t start_frame; usbh_complete_callback_t complete; void *arg; struct usbh_iso_frame_packet iso_packet[0]; @@ -68,6 +69,12 @@ struct usbh_urb { */ int usb_hc_init(void); +/** + * @brief Get frame number. + * + * @return frame number. + */ +uint16_t usbh_get_frame_number(void); /** * @brief control roothub. * diff --git a/components/cherryusb/common/usb_util.h b/components/cherryusb/common/usb_util.h index 790dfe54..f19c5079 100644 --- a/components/cherryusb/common/usb_util.h +++ b/components/cherryusb/common/usb_util.h @@ -44,12 +44,12 @@ #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif -#elif defined(__ICCARM__) +#elif defined(__ICCARM__) || defined(__ICCRX__) #ifndef __USED #if __ICCARM_V8 #define __USED __attribute__((used)) #else -#define __USED _Pragma("__root") +#define __USED __root #endif #endif diff --git a/components/cherryusb/core/usbd_core.c b/components/cherryusb/core/usbd_core.c index 612e7951..1d4e57b3 100644 --- a/components/cherryusb/core/usbd_core.c +++ b/components/cherryusb/core/usbd_core.c @@ -6,6 +6,9 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "usbd_core.h" +#ifdef CONFIG_USBDEV_TX_RX_THREAD +#include "usb_osal.h" +#endif /* general descriptor field offsets */ #define DESC_bLength 0 /** Length offset */ @@ -23,6 +26,12 @@ #define USB_EP_OUT_NUM 8 #define USB_EP_IN_NUM 8 +struct usbd_tx_rx_msg { + uint8_t ep; + uint32_t nbytes; + usbd_endpoint_callback cb; +}; + USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv { /** Setup packet */ USB_MEM_ALIGNX struct usb_setup_packet setup; @@ -35,17 +44,19 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv { /** Zero length packet flag of control transfer */ bool zlp_flag; /** Pointer to registered descriptors */ +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) + struct usb_descriptor *descriptors; +#else const uint8_t *descriptors; +#endif /* Buffer used for storing standard, class and vendor request data */ USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN]; - usbd_endpoint_callback in_ep_cb[USB_EP_IN_NUM]; - usbd_endpoint_callback out_ep_cb[USB_EP_OUT_NUM]; - /** Variable to check whether the usb has been configured */ bool configured; /** Currently selected configuration */ uint8_t configuration; + uint8_t speed; #ifdef CONFIG_USBDEV_TEST_MODE bool test_mode; #endif @@ -58,6 +69,14 @@ static struct usb_msosv1_descriptor *msosv1_desc; static struct usb_msosv2_descriptor *msosv2_desc; static struct usb_bos_descriptor *bos_desc; +struct usbd_tx_rx_msg tx_msg[USB_EP_IN_NUM]; +struct usbd_tx_rx_msg rx_msg[USB_EP_OUT_NUM]; + +#ifdef CONFIG_USBDEV_TX_RX_THREAD +usb_osal_mq_t usbd_tx_rx_mq; +usb_osal_thread_t usbd_tx_rx_thread; +#endif + static void usbd_class_event_notify_handler(uint8_t event, void *arg); static void usbd_print_setup(struct usb_setup_packet *setup) @@ -135,6 +154,119 @@ static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep_desc) * * @return true if the descriptor was found, false otherwise */ +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) +static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len) +{ + uint8_t type = 0U; + uint8_t index = 0U; + bool found = true; + uint8_t str_len = 0; + + type = HI_BYTE(type_index); + index = LO_BYTE(type_index); + + switch (type) { + case USB_DESCRIPTOR_TYPE_DEVICE: + *data = (uint8_t *)usbd_core_cfg.descriptors->device_descriptor; + *len = usbd_core_cfg.descriptors->device_descriptor[0]; + break; + case USB_DESCRIPTOR_TYPE_CONFIGURATION: + usbd_core_cfg.speed = usbd_get_port_speed(0); + if (usbd_core_cfg.speed == USB_SPEED_HIGH) { + if (usbd_core_cfg.descriptors->hs_config_descriptor[index]) { + *data = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[index]; + *len = (usbd_core_cfg.descriptors->hs_config_descriptor[index][CONF_DESC_wTotalLength] | + (usbd_core_cfg.descriptors->hs_config_descriptor[index][CONF_DESC_wTotalLength + 1] << 8)); + } else { + found = false; + } + } else { + if (usbd_core_cfg.descriptors->fs_config_descriptor[index]) { + *data = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[index]; + *len = (usbd_core_cfg.descriptors->fs_config_descriptor[index][CONF_DESC_wTotalLength] | + (usbd_core_cfg.descriptors->fs_config_descriptor[index][CONF_DESC_wTotalLength + 1] << 8)); + } else { + found = false; + } + } + + break; + case USB_DESCRIPTOR_TYPE_STRING: + if (index == USB_STRING_LANGID_INDEX) { + (*data)[0] = 0x04; + (*data)[1] = 0x03; + (*data)[2] = 0x09; + (*data)[3] = 0x04; + *len = 4; + } else if (index == USB_OSDESC_STRING_DESC_INDEX) { + if (usbd_core_cfg.descriptors->msosv1_descriptor) { + USB_LOG_INFO("read MS OS 1.0 descriptor string\r\n"); + *data = usbd_core_cfg.descriptors->msosv1_descriptor->string; + *len = usbd_core_cfg.descriptors->msosv1_descriptor->string_len; + } else { + } + } else { + if (usbd_core_cfg.descriptors->string_descriptor[index - 1]) { + str_len = strlen((const char *)usbd_core_cfg.descriptors->string_descriptor[index - 1]); + + (*data)[0] = str_len * 2 + 2; + (*data)[1] = 0x03; + for (uint16_t i = 0; i < str_len; i++) { + (*data)[i * 2 + 2] = usbd_core_cfg.descriptors->string_descriptor[index - 1][i]; + (*data)[i * 2 + 3] = 0; + } + + *len = str_len * 2 + 2; + } else { + found = false; + } + } + break; + case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: + if (usbd_core_cfg.descriptors->device_quality_descriptor) { + *data = (uint8_t *)usbd_core_cfg.descriptors->device_quality_descriptor; + *len = usbd_core_cfg.descriptors->device_quality_descriptor[0]; + } else { + found = false; + } + + break; + case USB_DESCRIPTOR_TYPE_OTHER_SPEED: + if (usbd_core_cfg.speed == USB_SPEED_HIGH) { + if (usbd_core_cfg.descriptors->fs_other_speed_descriptor) { + *data = (uint8_t *)usbd_core_cfg.descriptors->fs_other_speed_descriptor; + *len = (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] | + (usbd_core_cfg.descriptors->fs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8)); + } else { + found = false; + } + } else { + if (usbd_core_cfg.descriptors->hs_other_speed_descriptor) { + *data = (uint8_t *)usbd_core_cfg.descriptors->hs_other_speed_descriptor; + *len = (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] | + (usbd_core_cfg.descriptors->hs_other_speed_descriptor[CONF_DESC_wTotalLength] << 8)); + } else { + found = false; + } + } + break; + + case USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE: + USB_LOG_INFO("read BOS descriptor string\r\n"); + break; + + default: + found = false; + break; + } + + if (found == false) { + /* nothing found */ + USB_LOG_ERR("descriptor not found!\r\n", type, index); + } + return found; +} +#else static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len) { uint8_t type = 0U; @@ -220,6 +352,7 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l return found; } +#endif /** * @brief set USB configuration @@ -235,11 +368,19 @@ static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *l */ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting) { - uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors; uint8_t cur_alt_setting = 0xFF; uint8_t cur_config = 0xFF; bool found = false; - + uint8_t *p; +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) + if (usbd_core_cfg.speed == USB_SPEED_HIGH) { + p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[0]; + } else { + p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[0]; + } +#else + p = (uint8_t *)usbd_core_cfg.descriptors; +#endif /* configure endpoints for this configuration/altsetting */ while (p[DESC_bLength] != 0U) { switch (p[DESC_bDescriptorType]) { @@ -289,13 +430,21 @@ static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting) */ static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting) { - const uint8_t *p = usbd_core_cfg.descriptors; const uint8_t *if_desc = NULL; struct usb_endpoint_descriptor *ep_desc; uint8_t cur_alt_setting = 0xFF; uint8_t cur_iface = 0xFF; bool ret = false; - + uint8_t *p; +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) + if (usbd_core_cfg.speed == USB_SPEED_HIGH) { + p = (uint8_t *)usbd_core_cfg.descriptors->hs_config_descriptor[0]; + } else { + p = (uint8_t *)usbd_core_cfg.descriptors->fs_config_descriptor[0]; + } +#else + p = (uint8_t *)usbd_core_cfg.descriptors; +#endif USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting); while (p[DESC_bLength] != 0U) { @@ -638,6 +787,40 @@ static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t ** */ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) { +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) + if (usbd_core_cfg.descriptors->msosv1_descriptor) { + if (setup->bRequest == usbd_core_cfg.descriptors->msosv1_descriptor->vendor_code) { + switch (setup->wIndex) { + case 0x04: + USB_LOG_INFO("get Compat ID\r\n"); + *data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->compat_id; + *len = usbd_core_cfg.descriptors->msosv1_descriptor->compat_id_len; + return 0; + case 0x05: + USB_LOG_INFO("get Compat id properties\r\n"); + *data = (uint8_t *)usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property; + *len = usbd_core_cfg.descriptors->msosv1_descriptor->comp_id_property_len; + return 0; + default: + USB_LOG_ERR("unknown vendor code\r\n"); + return -1; + } + } + } else if (usbd_core_cfg.descriptors->msosv2_descriptor) { + if (setup->bRequest == usbd_core_cfg.descriptors->msosv2_descriptor->vendor_code) { + switch (setup->wIndex) { + case WINUSB_REQUEST_GET_DESCRIPTOR_SET: + USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n"); + *data = (uint8_t *)usbd_core_cfg.descriptors->msosv2_descriptor->compat_id; + *len = usbd_core_cfg.descriptors->msosv2_descriptor->compat_id_len; + return 0; + default: + USB_LOG_ERR("unknown vendor code\r\n"); + return -1; + } + } + } +#else if (msosv1_desc) { if (setup->bRequest == msosv1_desc->vendor_code) { switch (setup->wIndex) { @@ -672,7 +855,7 @@ static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t * } } } - +#endif usb_slist_t *i; usb_slist_for_each(i, &usbd_intf_head) @@ -766,6 +949,7 @@ void usbd_event_reset_handler(void) usbd_set_address(0); usbd_core_cfg.configured = 0; usbd_core_cfg.configuration = 0; + #ifdef CONFIG_USBDEV_TEST_MODE usbd_core_cfg.test_mode = false; #endif @@ -823,9 +1007,10 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup) } #endif /* Send smallest of requested and offered length */ - usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, - setup->wLength); + usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, setup->wLength); +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) +#else /* check if the data buf addr matches align size,if not, copy into align buf */ #ifndef CONFIG_USBDEV_ALIGN_CHECK_DISABLE if (((unsigned long)usbd_core_cfg.ep0_data_buf) & (CONFIG_USB_ALIGN_SIZE - 1)) { @@ -837,12 +1022,14 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup) memcpy(usbd_core_cfg.req_data, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; } +#endif #endif /* Send data or status to host */ usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); /* - * Set ZLP flag when host asks for a bigger length and the data size is multiplier of USB_CTRL_EP_MPS, - * to indicate the transfer done after zlp sent. + * Set ZLP flag when host asks for a bigger length and the data size is + * multiplier of USB_CTRL_EP_MPS, to indicate the transfer done after zlp + * sent. */ if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) { usbd_core_cfg.zlp_flag = true; @@ -850,84 +1037,130 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup) } } -void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes) +void usbd_event_ep0_in_complete_handler(uint8_t ep, uint32_t nbytes) { - if (ep == USB_CONTROL_IN_EP0) { - struct usb_setup_packet *setup = &usbd_core_cfg.setup; + struct usb_setup_packet *setup = &usbd_core_cfg.setup; - usbd_core_cfg.ep0_data_buf += nbytes; - usbd_core_cfg.ep0_data_buf_residue -= nbytes; + usbd_core_cfg.ep0_data_buf += nbytes; + usbd_core_cfg.ep0_data_buf_residue -= nbytes; - USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue); + USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue); - if (usbd_core_cfg.ep0_data_buf_residue != 0) { - /* Start sending the remain data */ - usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); + if (usbd_core_cfg.ep0_data_buf_residue != 0) { + /* Start sending the remain data */ + usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); + } else { + if (usbd_core_cfg.zlp_flag == true) { + usbd_core_cfg.zlp_flag = false; + /* Send zlp to host */ + USB_LOG_DBG("EP0 Send zlp\r\n"); + usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0); } else { - if (usbd_core_cfg.zlp_flag == true) { - usbd_core_cfg.zlp_flag = false; - /* Send zlp to host */ - USB_LOG_DBG("EP0 Send zlp\r\n"); - usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0); - } else { - /* Satisfying three conditions will jump here. + /* Satisfying three conditions will jump here. * 1. send status completely * 2. send zlp completely * 3. send last data completely. */ - if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN)) { - /* if all data has sent completely, start reading out status */ - usbd_ep_start_read(USB_CONTROL_OUT_EP0, NULL, 0); - } + if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN)) { + /* if all data has sent completely, start reading out status */ + usbd_ep_start_read(USB_CONTROL_OUT_EP0, NULL, 0); } } - } else { - if (usbd_core_cfg.in_ep_cb[ep & 0x7f]) { - usbd_core_cfg.in_ep_cb[ep & 0x7f](ep, nbytes); - } } } +void usbd_event_ep0_out_complete_handler(uint8_t ep, uint32_t nbytes) +{ + struct usb_setup_packet *setup = &usbd_core_cfg.setup; + + if (nbytes > 0) { + usbd_core_cfg.ep0_data_buf += nbytes; + usbd_core_cfg.ep0_data_buf_residue -= nbytes; + + USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue); + + if (usbd_core_cfg.ep0_data_buf_residue == 0) { + /* Received all, send data to handler */ + usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; + if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) { + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + + /*Send status to host*/ + usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0); + } else { + /* Start reading the remain data */ + usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); + } + } else { + /* Read out status completely, do nothing */ + USB_LOG_DBG("EP0 recv out status\r\n"); + } +} + +void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes) +{ +#ifndef CONFIG_USBDEV_TX_RX_THREAD + if (tx_msg[ep & 0x7f].cb) { + tx_msg[ep & 0x7f].cb(ep, nbytes); + } +#else + tx_msg[ep & 0x7f].nbytes = nbytes; + usb_osal_mq_send(usbd_tx_rx_mq, (uint32_t)&tx_msg[ep & 0x7f]); +#endif +} + void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes) { - if (ep == USB_CONTROL_OUT_EP0) { - struct usb_setup_packet *setup = &usbd_core_cfg.setup; +#ifndef CONFIG_USBDEV_TX_RX_THREAD + if (rx_msg[ep & 0x7f].cb) { + rx_msg[ep & 0x7f].cb(ep, nbytes); + } +#else + rx_msg[ep & 0x7f].nbytes = nbytes; + usb_osal_mq_send(usbd_tx_rx_mq, (uint32_t)&rx_msg[ep & 0x7f]); +#endif +} - if (nbytes > 0) { - usbd_core_cfg.ep0_data_buf += nbytes; - usbd_core_cfg.ep0_data_buf_residue -= nbytes; +#ifdef CONFIG_USBDEV_TX_RX_THREAD +static void usbdev_tx_rx_thread(void *argument) +{ + struct usbd_tx_rx_msg *msg; + int ret; - USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue); - - if (usbd_core_cfg.ep0_data_buf_residue == 0) { - /* Received all, send data to handler */ - usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; - if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) { - usbd_ep_set_stall(USB_CONTROL_IN_EP0); - return; - } - - /*Send status to host*/ - usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0); - } else { - /* Start reading the remain data */ - usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue); - } - } else { - /* Read out status completely, do nothing */ - USB_LOG_DBG("EP0 recv out status\r\n"); + while (1) { + ret = usb_osal_mq_recv(usbd_tx_rx_mq, (uint32_t *)&msg, 0xffffffff); + if (ret < 0) { + continue; } - } else { - if (usbd_core_cfg.out_ep_cb[ep & 0x7f]) { - usbd_core_cfg.out_ep_cb[ep & 0x7f](ep, nbytes); + + if (msg->cb) { + msg->cb(msg->ep, msg->nbytes); } } } +#endif +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) +void usbd_desc_register(struct usb_descriptor *desc) +{ + usbd_core_cfg.descriptors = desc; + usbd_core_cfg.intf_offset = 0; + tx_msg[0].ep = 0x80; + tx_msg[0].cb = usbd_event_ep0_in_complete_handler; + rx_msg[0].ep = 0x00; + rx_msg[0].cb = usbd_event_ep0_out_complete_handler; +} +#else void usbd_desc_register(const uint8_t *desc) { usbd_core_cfg.descriptors = desc; usbd_core_cfg.intf_offset = 0; + tx_msg[0].ep = 0x80; + tx_msg[0].cb = usbd_event_ep0_in_complete_handler; + rx_msg[0].ep = 0x00; + rx_msg[0].cb = usbd_event_ep0_out_complete_handler; } /* Register MS OS Descriptors version 1 */ @@ -946,6 +1179,7 @@ void usbd_bos_desc_register(struct usb_bos_descriptor *desc) { bos_desc = desc; } +#endif void usbd_add_interface(struct usbd_interface *intf) { @@ -957,9 +1191,11 @@ void usbd_add_interface(struct usbd_interface *intf) void usbd_add_endpoint(struct usbd_endpoint *ep) { if (ep->ep_addr & 0x80) { - usbd_core_cfg.in_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb; + tx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr; + tx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb; } else { - usbd_core_cfg.out_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb; + rx_msg[ep->ep_addr & 0x7f].ep = ep->ep_addr; + rx_msg[ep->ep_addr & 0x7f].cb = ep->ep_cb; } } @@ -970,6 +1206,16 @@ bool usb_device_is_configured(void) int usbd_initialize(void) { +#ifdef CONFIG_USBDEV_TX_RX_THREAD + usbd_tx_rx_mq = usb_osal_mq_create(32); + if (usbd_tx_rx_mq == NULL) { + return -1; + } + usbd_tx_rx_thread = usb_osal_thread_create("usbd_tx_rx", CONFIG_USBDEV_TX_RX_STACKSIZE, CONFIG_USBDEV_TX_RX_PRIO, usbdev_tx_rx_thread, NULL); + if (usbd_tx_rx_thread == NULL) { + return -1; + } +#endif return usb_dc_init(); } @@ -978,5 +1224,7 @@ int usbd_deinitialize(void) usbd_core_cfg.intf_offset = 0; usb_slist_init(&usbd_intf_head); usb_dc_deinit(); +#ifdef CONFIG_USBDEV_TX_RX_THREAD +#endif return 0; } diff --git a/components/cherryusb/core/usbd_core.h b/components/cherryusb/core/usbd_core.h index 2583fc91..049fa25b 100644 --- a/components/cherryusb/core/usbd_core.h +++ b/components/cherryusb/core/usbd_core.h @@ -62,10 +62,25 @@ struct usbd_interface { uint8_t intf_num; }; +struct usb_descriptor { + const uint8_t *device_descriptor; + const uint8_t **fs_config_descriptor; + const uint8_t **hs_config_descriptor; + const uint8_t *device_quality_descriptor; + const uint8_t *other_speed_descriptor; + const char **string_descriptor; + struct usb_msosv1_descriptor *msosv1_descriptor; + struct usb_msosv2_descriptor *msosv2_descriptor; + struct usb_bos_descriptor *bos_descriptor; +}; +#if defined(CHERRYUSB_VERSION) && (CHERRYUSB_VERSION > 0x000700) +void usbd_desc_register(struct usb_descriptor *desc); +#else void usbd_desc_register(const uint8_t *desc); void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc); void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc); void usbd_bos_desc_register(struct usb_bos_descriptor *desc); +#endif void usbd_add_interface(struct usbd_interface *intf); void usbd_add_endpoint(struct usbd_endpoint *ep); diff --git a/components/cherryusb/core/usbh_core.c b/components/cherryusb/core/usbh_core.c index b90eb2f5..c7199921 100644 --- a/components/cherryusb/core/usbh_core.c +++ b/components/cherryusb/core/usbh_core.c @@ -12,8 +12,8 @@ struct usbh_class_info *usbh_class_info_table_end = NULL; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN]; /* general descriptor field offsets */ -#define DESC_bLength 0 /** Length offset */ -#define DESC_bDescriptorType 1 /** Descriptor type offset */ +#define DESC_bLength 0 /** Length offset */ +#define DESC_bDescriptorType 1 /** Descriptor type offset */ #define USB_DEV_ADDR_MAX 0x7f #define USB_DEV_ADDR_MARK_OFFSET 5 @@ -109,7 +109,11 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin if (index->vid == vid && index->pid == pid && index->class == class) { return index->class_driver; } - } else if (index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) { + } else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) == (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) { + if (index->class == class && index->subclass == subclass) { + return index->class_driver; + } + } else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) == USB_CLASS_MATCH_INTF_CLASS) { if (index->class == class) { return index->class_driver; } @@ -618,14 +622,14 @@ int usbh_enumerate(struct usbh_hubport *hport) USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name); ret = CLASS_CONNECT(hport, i); if (ret < 0) { - ret = CLASS_DISCONNECT(hport, i); + CLASS_DISCONNECT(hport, i); goto errout; } } - usbh_device_mount_done_callback(hport); errout: if (ret < 0) { + hport->config.config_desc.bNumInterfaces = 0; usbh_hport_deactivate_ep0(hport); } if (hport->raw_config_desc) { @@ -689,6 +693,9 @@ int usbh_initialize(void) extern uint32_t __usbh_class_info_end__; usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__; usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__; +#elif defined(__ICCARM__) || defined(__ICCRX__) + usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin("usbh_class_info"); + usbh_class_info_table_end = (struct usbh_class_info *)__section_end("usbh_class_info"); #endif /* devaddr 1 is for roothub */ @@ -794,12 +801,4 @@ int lsusb(int argc, char **argv) } return 0; -} - -__WEAK void usbh_device_mount_done_callback(struct usbh_hubport *hport) -{ -} - -__WEAK void usbh_device_unmount_done_callback(struct usbh_hubport *hport) -{ -} +} \ No newline at end of file diff --git a/components/cherryusb/core/usbh_core.h b/components/cherryusb/core/usbh_core.h index ce5090e7..9c83fba5 100644 --- a/components/cherryusb/core/usbh_core.h +++ b/components/cherryusb/core/usbh_core.h @@ -39,6 +39,9 @@ extern "C" { #define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) #elif defined(__GNUC__) #define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1) +#elif defined(__ICCARM__) || defined(__ICCRX__) +#pragma section="usbh_class_info" +#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) #endif static inline void usbh_control_urb_fill(struct usbh_urb *urb, @@ -160,7 +163,6 @@ struct usbh_hub { struct usb_hub_descriptor hub_desc; struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS]; struct usbh_hubport *parent; - usb_slist_t hub_event_list; }; int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc); @@ -181,8 +183,6 @@ int usbh_initialize(void); struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr); void *usbh_find_class_instance(const char *devname); -void usbh_device_mount_done_callback(struct usbh_hubport *hport); -void usbh_device_unmount_done_callback(struct usbh_hubport *hport); int lsusb(int argc, char **argv); #ifdef __cplusplus diff --git a/components/cherryusb/osal/usb_osal.h b/components/cherryusb/osal/usb_osal.h index 89b67dd8..d730b74e 100644 --- a/components/cherryusb/osal/usb_osal.h +++ b/components/cherryusb/osal/usb_osal.h @@ -12,12 +12,11 @@ typedef void *usb_osal_thread_t; typedef void *usb_osal_sem_t; typedef void *usb_osal_mutex_t; +typedef void *usb_osal_mq_t; typedef void (*usb_thread_entry_t)(void *argument); usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args); -void usb_osal_timer_init(uint32_t poll_ms, void (*hub_poll_callback)(void)); - usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count); void usb_osal_sem_delete(usb_osal_sem_t sem); int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout); @@ -28,10 +27,13 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex); int usb_osal_mutex_take(usb_osal_mutex_t mutex); int usb_osal_mutex_give(usb_osal_mutex_t mutex); +usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs); +int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr); +int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout); + size_t usb_osal_enter_critical_section(void); void usb_osal_leave_critical_section(size_t flag); void usb_osal_msleep(uint32_t delay); #endif /* USB_OSAL_H */ - diff --git a/components/cherryusb/osal/usb_osal_freertos.c b/components/cherryusb/osal/usb_osal_freertos.c index 8ca31c98..65d9f1c3 100644 --- a/components/cherryusb/osal/usb_osal_freertos.c +++ b/components/cherryusb/osal/usb_osal_freertos.c @@ -8,6 +8,7 @@ #include #include "semphr.h" #include "timers.h" +#include "event_groups.h" usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args) { @@ -17,13 +18,6 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, return (usb_osal_thread_t)htask; } -void usb_osal_timer_init(uint32_t poll_ms, void (*hub_poll_callback)(void)) -{ - TimerHandle_t handle = xTimerCreate("usbh_hub_poll", poll_ms, pdTRUE, 0, (TimerCallbackFunction_t)hub_poll_callback); - - xTimerStart(handle, 1000); -} - usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count) { return (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count); @@ -49,7 +43,7 @@ int usb_osal_sem_give(usb_osal_sem_t sem) portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } - return (ret == pdPASS) ? 0 : -EINVAL; + return (ret == pdPASS) ? 0 : -ETIMEDOUT; } usb_osal_mutex_t usb_osal_mutex_create(void) @@ -69,7 +63,30 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex) int usb_osal_mutex_give(usb_osal_mutex_t mutex) { - return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -EINVAL; + return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -ETIMEDOUT; +} + +usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) +{ + return (usb_osal_mq_t)xQueueCreate(max_msgs, 4); +} + +int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + int ret; + + ret = xQueueSendFromISR((usb_osal_mq_t)mq, &addr, &xHigherPriorityTaskWoken); + if (ret == pdPASS) { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + + return (ret == pdPASS) ? 0 : -ETIMEDOUT; +} + +int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout) +{ + return (xQueueReceive((usb_osal_mq_t)mq, addr, timeout) == pdPASS) ? 0 : -ETIMEDOUT; } size_t usb_osal_enter_critical_section(void) diff --git a/components/cherryusb/osal/usb_osal_rtthread.c b/components/cherryusb/osal/usb_osal_rtthread.c index e9e7b2aa..f2f830e7 100644 --- a/components/cherryusb/osal/usb_osal_rtthread.c +++ b/components/cherryusb/osal/usb_osal_rtthread.c @@ -32,9 +32,9 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) rt_err_t result = RT_EOK; result = rt_sem_take((rt_sem_t)sem, rt_tick_from_millisecond(timeout)); - if (result == RT_ETIMEOUT) { + if (result == -RT_ETIMEOUT) { ret = -ETIMEDOUT; - } else if (result == RT_ERROR) { + } else if (result == -RT_ERROR) { ret = -EINVAL; } else { ret = 0; @@ -68,6 +68,33 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex) return (int)rt_mutex_release((rt_mutex_t)mutex); } +usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) +{ + return (usb_osal_mq_t)rt_mq_create("usbh_mq", 4, max_msgs, RT_IPC_FLAG_FIFO); +} + +int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr) +{ + return rt_mq_send((rt_mq_t)mq, &addr, 4); +} + +int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout) +{ + int ret = 0; + rt_err_t result = RT_EOK; + + result = rt_mq_recv((rt_mq_t)mq, addr, 4, rt_tick_from_millisecond(timeout)); + if (result == -RT_ETIMEOUT) { + ret = -ETIMEDOUT; + } else if (result == -RT_ERROR) { + ret = -EINVAL; + } else { + ret = 0; + } + + return (int)ret; +} + size_t usb_osal_enter_critical_section(void) { return rt_hw_interrupt_disable(); diff --git a/components/cherryusb/port/ehci/usb_hc_ehci.c b/components/cherryusb/port/ehci/usb_hc_ehci.c index 11cefc72..c35a98ed 100644 --- a/components/cherryusb/port/ehci/usb_hc_ehci.c +++ b/components/cherryusb/port/ehci/usb_hc_ehci.c @@ -11,8 +11,8 @@ #define USBH_IRQHandler USBH_IRQHandler #endif -#define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE) -#define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE) +#define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE) +#define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE) #define EHCI_PTR2ADDR(x) ((uint32_t)x) #define EHCI_ADDRALIGN32(x) ((uint32_t)(x) & ~0x1F) @@ -31,7 +31,7 @@ #define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM #define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM * 3) -#define CONFIG_USB_EHCI_ITD_NUM 256 +#define CONFIG_USB_EHCI_ITD_NUM 10 extern uint8_t usbh_get_port_speed(const uint8_t port); @@ -53,9 +53,9 @@ struct ehci_pipe { struct usbh_hubport *hport; struct ehci_qh_hw *qh; struct usbh_urb *urb; - struct ehci_itd_hw *itdpool; - uint32_t itd_num; - uint32_t used_itd_num; + uint16_t current_itd; + uint16_t used_itd_num; + uint16_t start_frame; usb_slist_t iso_list; }; @@ -71,14 +71,12 @@ struct ehci_qtd_hw { struct ehci_itd_hw { struct ehci_itd hw; - struct usbh_iso_frame_packet *iso_packet; - uint32_t start_frame; - usb_slist_t list; } __attribute__((aligned(32))); struct ehci_hcd { bool ehci_qh_used[CONFIG_USB_EHCI_QH_NUM]; bool ehci_qtd_used[CONFIG_USB_EHCI_QTD_NUM]; + bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM]; struct ehci_pipe pipe_pool[CONFIG_USB_EHCI_QH_NUM]; } g_ehci_hcd; @@ -155,7 +153,31 @@ static void ehci_qtd_free(struct ehci_qtd_hw *qtd) } } } +#if 0 +static struct ehci_itd_hw *ehci_itd_alloc(void) +{ + struct ehci_itd_hw *itd; + for (uint32_t i = 0; i < CONFIG_USB_EHCI_ITD_NUM; i++) { + if (!g_ehci_hcd.ehci_itd_used[i]) { + g_ehci_hcd.ehci_itd_used[i] = true; + itd = &ehci_itd_pool[i]; + memset(itd, 0, sizeof(struct ehci_itd_hw)); + return itd; + } + } + return NULL; +} +static void ehci_itd_free(struct ehci_itd_hw *itd) +{ + for (uint32_t i = 0; i < CONFIG_USB_EHCI_ITD_NUM; i++) { + if (&ehci_itd_pool[i] == itd) { + g_ehci_hcd.ehci_itd_used[i] = false; + return; + } + } +} +#endif static struct ehci_pipe *ehci_pipe_alloc(void) { int pipe; @@ -203,18 +225,18 @@ static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n) } } -static inline void ehci_itd_add_head(struct ehci_itd_hw *itd) +static inline void ehci_itd_add_head(struct ehci_itd_hw *itd, uint32_t sched_frame) { - itd->hw.nlp = g_framelist[itd->start_frame]; - g_framelist[itd->start_frame] = ITD_NLP_ITD(itd); + itd->hw.nlp = g_framelist[sched_frame]; + g_framelist[sched_frame] = ITD_NLP_ITD(itd); } -static inline void ehci_itd_remove(struct ehci_itd_hw *itd) +static inline void ehci_itd_remove(struct ehci_itd_hw *itd, uint32_t sched_frame) { - if (g_framelist[itd->start_frame] == ITD_NLP_ITD(itd)) { - g_framelist[itd->start_frame] = itd->hw.nlp; + if (g_framelist[sched_frame] == ITD_NLP_ITD(itd)) { + g_framelist[sched_frame] = itd->hw.nlp; } else { - struct ehci_itd_hw *tmp_itd = EHCI_ADDR2ITD(g_framelist[itd->start_frame]); + struct ehci_itd_hw *tmp_itd = EHCI_ADDR2ITD(g_framelist[sched_frame]); while ((EHCI_ADDR2ITD(tmp_itd->hw.nlp) != itd) && tmp_itd) { tmp_itd = EHCI_ADDR2ITD(tmp_itd->hw.nlp); } @@ -405,11 +427,6 @@ static void ehci_itd_tscl_fill(struct ehci_itd_hw *itd, ITD_TSCL_STATUS_ACTIVE; /* Status */ } -static uint16_t ehci_get_frame_id(void) -{ - return (EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3; -} - static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { struct ehci_qh_hw *qh = NULL; @@ -678,59 +695,53 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b static int ehci_iso_pipe_init(struct ehci_pipe *pipe, struct usbh_iso_frame_packet *iso_packet, uint32_t num_of_iso_packets) { struct ehci_itd_hw *itd; + struct usbh_urb *urb; uint32_t start_addr; - uint16_t next_frame; + uint16_t sched_frame; uint32_t bufaddr_in_uframe; uint32_t buflen_in_uframe; uint32_t itd_nums; - uint32_t num_of_used_iso_packets = 0; - size_t flags; + uint32_t used_iso_packets; + + //EHCI_HCOR->usbcmd &= ~EHCI_USBCMD_PSEN; if (pipe->speed == USB_SPEED_HIGH) { itd_nums = (num_of_iso_packets + 7) / 8; - next_frame = (ehci_get_frame_id() + 2) & 0x3ff; + used_iso_packets = 0; - if (itd_nums > pipe->itd_num) { - return -ENOMEM; - } + urb = pipe->urb; + sched_frame = urb->start_frame; + pipe->current_itd = 0; pipe->used_itd_num = itd_nums; - ehci_iso_pipe_add_tail(pipe); for (uint32_t i = 0; i < itd_nums; i++) { - itd = &pipe->itdpool[i]; - + itd = &ehci_itd_pool[i]; memset(itd, 0, sizeof(struct ehci_itd_hw)); + start_addr = ((uint32_t)iso_packet[used_iso_packets].transfer_buffer); + /* fill itd bpl */ - start_addr = ((uint32_t)iso_packet[num_of_used_iso_packets].transfer_buffer); - - itd->iso_packet = &iso_packet[num_of_used_iso_packets]; - ehci_itd_bpl_fill(itd, pipe, start_addr); /* fill itd tscl for micro-frame */ for (uint8_t mf = 0; mf < 8; mf++) { - bufaddr_in_uframe = ((uint32_t)iso_packet[num_of_used_iso_packets].transfer_buffer); - buflen_in_uframe = iso_packet[num_of_used_iso_packets].transfer_buffer_length; + bufaddr_in_uframe = ((uint32_t)iso_packet[used_iso_packets].transfer_buffer); + buflen_in_uframe = iso_packet[used_iso_packets].transfer_buffer_length; ehci_itd_tscl_fill(itd, pipe, mf, start_addr, bufaddr_in_uframe, buflen_in_uframe); - num_of_used_iso_packets++; - if (num_of_used_iso_packets == num_of_iso_packets) { + used_iso_packets++; + if (used_iso_packets == num_of_iso_packets) { itd->hw.tscl[mf] |= ITD_TSCL_IOC; - break; } } - flags = usb_osal_enter_critical_section(); - - itd->start_frame = next_frame; - ehci_itd_add_head(itd); - next_frame = (next_frame + 1) & 0x3ff; - usb_osal_leave_critical_section(flags); + ehci_itd_add_head(itd, sched_frame); + sched_frame = (sched_frame + 1) & 0x3ff; } - + ehci_iso_pipe_add_tail(pipe); } else { } + //EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN; return 0; } @@ -837,27 +848,18 @@ static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh) ehci_qh_free(qh); } -static void ehci_check_itd(struct ehci_itd_hw *itd) +static int ehci_check_itd(struct ehci_itd_hw *itd, struct usbh_iso_frame_packet *iso_packet) { - struct usbh_iso_frame_packet *iso_packet; - - iso_packet = itd->iso_packet; - for (uint8_t mf = 0; mf < 8; mf++) { if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_MASK) { - if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_XACTERR) { - iso_packet[mf].errorcode = -EIO; - } else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_BABBLE) { - iso_packet[mf].errorcode = -EPERM; - } else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_DBERROR) { - iso_packet[mf].errorcode = -EIO; - } else if (itd->hw.tscl[mf] & ITD_TSCL_STATUS_ACTIVE) { - } + iso_packet[mf].errorcode = -EIO; + return -EIO; } else { iso_packet[mf].actual_length = ((itd->hw.tscl[mf] & ITD_TSCL_LENGTH_MASK) >> ITD_TSCL_LENGTH_SHIFT); iso_packet[mf].errorcode = 0; } } + return 0; } static int usbh_reset_port(const uint8_t port) @@ -992,7 +994,7 @@ int usb_hc_init(void) #error Unsupported frame size list size #endif - regval |= EHCI_USBCMD_ITHRE_1MF; + regval |= EHCI_USBCMD_ITHRE_8MF; regval |= EHCI_USBCMD_ASEN; regval |= EHCI_USBCMD_PSEN; regval |= EHCI_USBCMD_RUN; @@ -1023,6 +1025,11 @@ int usb_hc_init(void) return 0; } +uint16_t usbh_get_frame_number(void) +{ + return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff); +} + int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) { uint8_t nports; @@ -1202,11 +1209,6 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) ppipe->dev_addr = ep_cfg->hport->dev_addr; ppipe->hport = ep_cfg->hport; - if (ppipe->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { - ppipe->itdpool = ehci_itd_pool; - ppipe->itd_num = CONFIG_USB_EHCI_ITD_NUM; - } - /* restore variable */ ppipe->inuse = true; ppipe->waitsem = waitsem; @@ -1257,8 +1259,6 @@ int usbh_submit_urb(struct usbh_urb *urb) return -EINVAL; } - flags = usb_osal_enter_critical_section(); - if (!pipe->hport->connected) { return -ENODEV; } @@ -1267,6 +1267,8 @@ int usbh_submit_urb(struct usbh_urb *urb) return -EBUSY; } + flags = usb_osal_enter_critical_section(); + pipe->waiter = false; pipe->xfrd = 0; pipe->qh = NULL; @@ -1298,12 +1300,7 @@ int usbh_submit_urb(struct usbh_urb *urb) } break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: - ret = ehci_iso_pipe_init(pipe, urb->iso_packet, urb->num_of_iso_packets); - if (ret < 0) { - pipe->urb = NULL; - pipe->waiter = false; - return ret; - } + ehci_iso_pipe_init(pipe, urb->iso_packet, urb->num_of_iso_packets); break; default: break; @@ -1315,9 +1312,7 @@ int usbh_submit_urb(struct usbh_urb *urb) if (ret < 0) { goto errout_timeout; } - if (pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) { - ret = urb->errorcode; - } + ret = urb->errorcode; } return ret; errout_timeout: @@ -1333,6 +1328,7 @@ int usbh_kill_urb(struct usbh_urb *urb) struct ehci_pipe *iso_pipe; struct ehci_qh_hw *qh = NULL; struct ehci_itd_hw *itd; + uint32_t sched_frame; usb_slist_t *i; size_t flags; @@ -1378,11 +1374,12 @@ int usbh_kill_urb(struct usbh_urb *urb) iso_pipe = usb_slist_entry(i, struct ehci_pipe, iso_list); if (pipe == iso_pipe) { + sched_frame = urb->start_frame; for (uint32_t j = 0; j < pipe->used_itd_num; j++) { - itd = &pipe->itdpool[j]; - ehci_check_itd(itd); + itd = &ehci_itd_pool[j]; /* remove itd from list */ - ehci_itd_remove(itd); + ehci_itd_remove(itd, sched_frame); + urb->start_frame = (sched_frame + 1) & 0x3ff; } pipe->used_itd_num = 0; ehci_iso_pipe_remove(pipe); @@ -1437,19 +1434,27 @@ static void ehci_scan_isochronous_list(void) { struct ehci_itd_hw *itd; struct ehci_pipe *pipe; + struct usbh_urb *urb; + uint32_t sched_frame; usb_slist_t *i; + int errorcode = 0; usb_slist_for_each(i, &iso_pipe_list_head) { pipe = usb_slist_entry(i, struct ehci_pipe, iso_list); + urb = pipe->urb; + + sched_frame = urb->start_frame; for (uint32_t j = 0; j < pipe->used_itd_num; j++) { - itd = &pipe->itdpool[j]; - ehci_check_itd(itd); + itd = &ehci_itd_pool[j]; + errorcode = ehci_check_itd(itd, &urb->iso_packet[j * 8]); /* remove itd from list */ - ehci_itd_remove(itd); + ehci_itd_remove(itd, sched_frame); + urb->start_frame = (sched_frame + 1) & 0x3ff; + urb->errorcode = errorcode; } - pipe->used_itd_num = 0; + ehci_iso_pipe_remove(pipe); ehci_pipe_waitup(pipe); } @@ -1490,6 +1495,16 @@ void USBH_IRQHandler(void) usb_osal_sem_give(pipe->waitsem); } } + + for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) { + g_ehci_hcd.ehci_qh_used[index] = false; + } + for (uint8_t index = 0; index < CONFIG_USB_EHCI_QTD_NUM; index++) { + g_ehci_hcd.ehci_qtd_used[index] = false; + } + for (uint8_t index = 0; index < CONFIG_USB_EHCI_ITD_NUM; index++) { + g_ehci_hcd.ehci_itd_used[index] = false; + } } usbh_roothub_thread_wakeup(port + 1); } diff --git a/examples/peripherals/usbhost/usb_host.c b/examples/peripherals/usbhost/usb_host.c index c1257b53..d7c57050 100644 --- a/examples/peripherals/usbhost/usb_host.c +++ b/examples/peripherals/usbhost/usb_host.c @@ -195,25 +195,42 @@ int hid_test(void) return ret; } -void usbh_device_mount_done_callback(struct usbh_hubport *hport) -{ -} - -void usbh_device_unmount_done_callback(struct usbh_hubport *hport) -{ -} - static void usbh_class_test_thread(void *argument) { while (1) { - printf("helloworld\r\n"); + //printf("helloworld\r\n"); usb_osal_msleep(1000); cdc_acm_test(); msc_test(); hid_test(); + //video_test(); } } +void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) +{ +} + +void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) +{ +} + +void usbh_hid_run(struct usbh_hid *hid_class) +{ +} + +void usbh_hid_stop(struct usbh_hid *hid_class) +{ +} + +void usbh_msc_run(struct usbh_msc *msc_class) +{ +} + +void usbh_msc_stop(struct usbh_msc *msc_class) +{ +} + void usbh_class_test(void) { usb_osal_thread_create("usbh_test", 4096, CONFIG_USBHOST_PSC_PRIO + 1, usbh_class_test_thread, NULL);