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