add usb tx rx thread for device

This commit is contained in:
sakimisu
2022-12-11 21:19:48 +08:00
parent 52edc32521
commit 43a45fc2fc
8 changed files with 379 additions and 199 deletions

View File

@@ -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;
@@ -43,9 +52,6 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
/* 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 */
@@ -63,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)
@@ -1023,90 +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 */
@@ -1137,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;
}
}
@@ -1150,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();
}
@@ -1158,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;
}