diff --git a/class/audio/usbh_audio.c b/class/audio/usbh_audio.c index a27cd456..eda75716 100644 --- a/class/audio/usbh_audio.c +++ b/class/audio/usbh_audio.c @@ -89,7 +89,7 @@ freq_found: setup->wIndex = intf; setup->wLength = 0; - ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL); + ret = usbh_control_transfer(audio_class->hport, setup, NULL); if (ret < 0) { return ret; } @@ -103,7 +103,7 @@ freq_found: setup->wLength = 3; memcpy(g_audio_buf, &samp_freq, 3); - ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf); + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); if (ret < 0) { return ret; } @@ -112,10 +112,10 @@ freq_found: mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; if (ep_desc->bEndpointAddress & 0x80) { audio_class->isoin_mps = mps * (mult + 1); - usbh_hport_activate_epx(&audio_class->isoin, audio_class->hport, ep_desc); + USBH_EP_INIT(audio_class->isoin, ep_desc); } else { audio_class->isoout_mps = mps * (mult + 1); - usbh_hport_activate_epx(&audio_class->isoout, audio_class->hport, ep_desc); + USBH_EP_INIT(audio_class->isoout, ep_desc); } USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting); @@ -147,12 +147,10 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name) ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { if (audio_class->isoin) { - usbh_pipe_free(audio_class->isoin); audio_class->isoin = NULL; } } else { if (audio_class->isoout) { - usbh_pipe_free(audio_class->isoout); audio_class->isoout = NULL; } } @@ -163,7 +161,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name) setup->wIndex = intf; setup->wLength = 0; - ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL); + ret = usbh_control_transfer(audio_class->hport, setup, NULL); return ret; } @@ -196,7 +194,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint volume_hex = -0xDB00 / 100 * volume + 0xdb00; memcpy(g_audio_buf, &volume_hex, 2); - ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL); + ret = usbh_control_transfer(audio_class->hport, setup, NULL); return ret; } @@ -226,7 +224,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ setup->wLength = 1; memcpy(g_audio_buf, &mute, 1); - ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf); + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); return ret; } @@ -416,11 +414,9 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf) if (audio_class) { if (audio_class->isoin) { - usbh_pipe_free(audio_class->isoin); } if (audio_class->isoout) { - usbh_pipe_free(audio_class->isoout); } if (hport->config.intf[intf].devname[0] != '\0') { diff --git a/class/audio/usbh_audio.h b/class/audio/usbh_audio.h index dcfed604..f963dd0b 100644 --- a/class/audio/usbh_audio.h +++ b/class/audio/usbh_audio.h @@ -40,11 +40,11 @@ struct usbh_audio_module { struct usbh_audio { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */ + struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */ uint8_t ctrl_intf; /* interface number */ uint8_t minor; - usbh_pipe_t isoin; /* ISO IN endpoint */ - usbh_pipe_t isoout; /* ISO OUT endpoint */ uint16_t isoin_mps; uint16_t isoout_mps; bool is_opened; diff --git a/class/cdc/usbd_cdc_ecm.c b/class/cdc/usbd_cdc_ecm.c index 1ebdecf6..4a2dac00 100644 --- a/class/cdc/usbd_cdc_ecm.c +++ b/class/cdc/usbd_cdc_ecm.c @@ -19,9 +19,9 @@ static struct usbd_endpoint cdc_ecm_ep_data[3]; #define CDC_ECM_MAX_PACKET_SIZE 64 #endif -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16]; volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL; volatile uint32_t g_cdc_ecm_rx_data_length = 0; diff --git a/class/cdc/usbh_cdc_acm.c b/class/cdc/usbh_cdc_acm.c index a86c1298..faadd841 100644 --- a/class/cdc/usbh_cdc_acm.c +++ b/class/cdc/usbh_cdc_acm.c @@ -50,7 +50,7 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_ memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding)); - return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding); + return usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding); } int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding) @@ -64,7 +64,7 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_ setup->wIndex = cdc_acm_class->ctrl_intf; setup->wLength = 7; - ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding); + ret = usbh_control_transfer(cdc_acm_class->hport, setup, (uint8_t *)&g_cdc_line_coding); if (ret < 0) { return ret; } @@ -85,7 +85,7 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo cdc_acm_class->dtr = dtr; cdc_acm_class->rts = rts; - return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL); + return usbh_control_transfer(cdc_acm_class->hport, setup, NULL); } static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) @@ -124,15 +124,15 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) #ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc; - usbh_hport_activate_epx(&cdc_acm_class->intin, hport, ep_desc); + USBH_EP_INIT(cdc_acm_class->intin, ep_desc); #endif for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&cdc_acm_class->bulkin, hport, ep_desc); + USBH_EP_INIT(cdc_acm_class->bulkin, ep_desc); } else { - usbh_hport_activate_epx(&cdc_acm_class->bulkout, hport, ep_desc); + USBH_EP_INIT(cdc_acm_class->bulkout, ep_desc); } } @@ -152,13 +152,19 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) if (cdc_acm_class) { if (cdc_acm_class->bulkin) { - usbh_pipe_free(cdc_acm_class->bulkin); + usbh_kill_urb(&cdc_acm_class->bulkin_urb); } if (cdc_acm_class->bulkout) { - usbh_pipe_free(cdc_acm_class->bulkout); + usbh_kill_urb(&cdc_acm_class->bulkout_urb); } +#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY + if (cdc_acm_class->intin) { + usbh_kill_urb(&cdc_acm_class->intin_urb); + } +#endif + if (hport->config.intf[intf].devname[0] != '\0') { USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname); usbh_cdc_acm_stop(cdc_acm_class); @@ -170,6 +176,32 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } +int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &cdc_acm_class->bulkin_urb; + + usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + int ret; + struct usbh_urb *urb = &cdc_acm_class->bulkout_urb; + + usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buffer, buflen, timeout, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf) { return 0; diff --git a/class/cdc/usbh_cdc_acm.h b/class/cdc/usbh_cdc_acm.h index 3ffa64d0..f06b0ab3 100644 --- a/class/cdc/usbh_cdc_acm.h +++ b/class/cdc/usbh_cdc_acm.h @@ -10,6 +10,12 @@ struct usbh_cdc_acm { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */ + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + struct usbh_urb intin_urb; struct cdc_line_coding linecoding; uint8_t ctrl_intf; /* Control interface number */ @@ -17,11 +23,6 @@ struct usbh_cdc_acm { bool dtr; bool rts; uint8_t minor; - usbh_pipe_t bulkin; /* Bulk IN endpoint */ - usbh_pipe_t bulkout; /* Bulk OUT endpoint */ -#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY - usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */ -#endif }; #ifdef __cplusplus @@ -32,6 +33,9 @@ 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); +int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); +int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class); void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class); diff --git a/class/cdc/usbh_cdc_ecm.c b/class/cdc/usbh_cdc_ecm.c index d4546927..6ca59a38 100644 --- a/class/cdc/usbh_cdc_ecm.c +++ b/class/cdc/usbh_cdc_ecm.c @@ -20,9 +20,9 @@ #define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C #define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16]; static struct usbh_cdc_ecm g_cdc_ecm_class; @@ -36,21 +36,25 @@ static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class setup->wIndex = cdc_ecm_class->ctrl_intf; setup->wLength = 0; - return usbh_control_transfer(cdc_ecm_class->hport->ep0, setup, NULL); + return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL); } int usbh_cdc_ecm_get_notification(struct usbh_cdc_ecm *cdc_ecm_class) { int ret; - usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL); + usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->hport, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL); ret = usbh_submit_urb(&cdc_ecm_class->intin_urb); if (ret < 0) { return ret; } if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) { - cdc_ecm_class->connect_status = g_cdc_ecm_inttx_buffer[2]; + if (g_cdc_ecm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) { + cdc_ecm_class->connect_status = true; + } else { + cdc_ecm_class->connect_status = false; + } } else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) { memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8); } @@ -69,6 +73,8 @@ static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf) struct usbh_cdc_ecm *cdc_ecm_class = &g_cdc_ecm_class; + memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm)); + cdc_ecm_class->hport = hport; cdc_ecm_class->ctrl_intf = intf; cdc_ecm_class->data_intf = intf + 1; @@ -105,7 +111,7 @@ get_mac: return -1; } - memset(mac_buffer, 0, 8); + memset(mac_buffer, 0, 12); ret = usbh_get_string_desc(cdc_ecm_class->hport, mac_str_idx, (uint8_t *)mac_buffer); if (ret < 0) { return ret; @@ -137,7 +143,7 @@ get_mac: /* enable int ep */ ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc; - usbh_hport_activate_epx(&cdc_ecm_class->intin, hport, ep_desc); + USBH_EP_INIT(cdc_ecm_class->intin, ep_desc); if (hport->config.intf[intf + 1].altsetting_num > 1) { altsetting = hport->config.intf[intf + 1].altsetting_num - 1; @@ -146,9 +152,9 @@ get_mac: ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc); + USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc); } else { - usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc); + USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc); } } @@ -159,9 +165,9 @@ get_mac: ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&cdc_ecm_class->bulkin, hport, ep_desc); + USBH_EP_INIT(cdc_ecm_class->bulkin, ep_desc); } else { - usbh_hport_activate_epx(&cdc_ecm_class->bulkout, hport, ep_desc); + USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc); } } } @@ -194,15 +200,15 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf) if (cdc_ecm_class) { if (cdc_ecm_class->bulkin) { - usbh_pipe_free(cdc_ecm_class->bulkin); + usbh_kill_urb(&cdc_ecm_class->bulkin_urb); } if (cdc_ecm_class->bulkout) { - usbh_pipe_free(cdc_ecm_class->bulkout); + usbh_kill_urb(&cdc_ecm_class->bulkout_urb); } if (cdc_ecm_class->intin) { - usbh_pipe_free(cdc_ecm_class->intin); + usbh_kill_urb(&cdc_ecm_class->intin_urb); } if (hport->config.intf[intf].devname[0] != '\0') { @@ -223,30 +229,25 @@ static void usbh_cdc_ecm_rx_thread(void *argument) err_t err; struct pbuf *p; struct netif *netif = (struct netif *)argument; - uint16_t ep_mps; // clang-format off find_class: // clang-format on + g_cdc_ecm_class.connect_status = false; while (usbh_find_class_instance("/dev/cdc_ether") == NULL) { usb_osal_msleep(1000); } - while (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) { + while (g_cdc_ecm_class.connect_status == false) { ret = usbh_cdc_ecm_get_notification(&g_cdc_ecm_class); if (ret < 0) { goto find_class; } } - if (g_cdc_ecm_class.hport->speed == USB_SPEED_FULL) { - ep_mps = 64; - } else { - ep_mps = 512; - } g_cdc_ecm_rx_length = 0; while (1) { - usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); + usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL); ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb); if (ret < 0) { goto find_class; @@ -254,13 +255,14 @@ find_class: g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length; - if (g_cdc_ecm_rx_length % ep_mps) { + if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) { USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length); p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL); if (p != NULL) { memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length); g_cdc_ecm_rx_length = 0; + err = netif->input(p, netif); if (err != ERR_OK) { pbuf_free(p); @@ -280,7 +282,7 @@ err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p) struct pbuf *q; uint8_t *buffer = g_cdc_ecm_tx_buffer; - if (g_cdc_ecm_class.connect_status == CDC_ECM_NET_DISCONNECTED) { + if (g_cdc_ecm_class.connect_status == false) { return ERR_BUF; } @@ -291,7 +293,7 @@ err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p) USB_LOG_DBG("txlen:%d\r\n", p->tot_len); - usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL); + usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL); ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb); if (ret < 0) { return ERR_BUF; diff --git a/class/cdc/usbh_cdc_ecm.h b/class/cdc/usbh_cdc_ecm.h index 7e0e96c3..7d65da0b 100644 --- a/class/cdc/usbh_cdc_ecm.h +++ b/class/cdc/usbh_cdc_ecm.h @@ -13,20 +13,21 @@ struct usbh_cdc_ecm { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */ + struct usbh_urb bulkout_urb; /* Bulk out endpoint */ + struct usbh_urb bulkin_urb; /* Bulk IN endpoint */ + struct usbh_urb intin_urb; /* Interrupt IN endpoint */ uint8_t ctrl_intf; /* Control interface number */ uint8_t data_intf; /* Data interface number */ uint8_t minor; + uint8_t mac[6]; - uint32_t max_segment_size; - uint8_t connect_status; + bool connect_status; + uint16_t max_segment_size; uint32_t speed[2]; - usbh_pipe_t bulkin; /* Bulk IN endpoint */ - usbh_pipe_t bulkout; /* Bulk OUT endpoint */ - usbh_pipe_t intin; /* Interrupt IN endpoint */ - struct usbh_urb bulkout_urb; - struct usbh_urb bulkin_urb; - struct usbh_urb intin_urb; ip_addr_t ipaddr; ip_addr_t netmask; diff --git a/class/hid/usbh_hid.c b/class/hid/usbh_hid.c index 8152af5f..b64ecab5 100644 --- a/class/hid/usbh_hid.c +++ b/class/hid/usbh_hid.c @@ -49,7 +49,7 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b setup->wIndex = hid_class->intf; setup->wLength = 128; - ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf); + ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf); if (ret < 0) { return ret; } @@ -67,7 +67,7 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur setup->wIndex = hid_class->intf; setup->wLength = 0; - return usbh_control_transfer(hid_class->hport->ep0, setup, NULL); + return usbh_control_transfer(hid_class->hport, setup, NULL); } int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) @@ -81,7 +81,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) setup->wIndex = hid_class->intf; setup->wLength = 1; - ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf); + ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf); if (ret < 0) { return ret; } @@ -99,7 +99,7 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol) setup->wIndex = 0; setup->wLength = 0; - return usbh_control_transfer(hid_class->hport->ep0, setup, NULL); + return usbh_control_transfer(hid_class->hport, setup, NULL); } int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) @@ -137,9 +137,9 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&hid_class->intin, hport, ep_desc); + USBH_EP_INIT(hid_class->intin, ep_desc); } else { - usbh_hport_activate_epx(&hid_class->intout, hport, ep_desc); + USBH_EP_INIT(hid_class->intout, ep_desc); } } @@ -159,11 +159,11 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) if (hid_class) { if (hid_class->intin) { - usbh_pipe_free(hid_class->intin); + usbh_kill_urb(&hid_class->intin_urb); } if (hid_class->intout) { - usbh_pipe_free(hid_class->intout); + usbh_kill_urb(&hid_class->intout_urb); } if (hport->config.intf[intf].devname[0] != '\0') { diff --git a/class/hid/usbh_hid.h b/class/hid/usbh_hid.h index 9faf2023..72571dd2 100644 --- a/class/hid/usbh_hid.h +++ b/class/hid/usbh_hid.h @@ -10,12 +10,14 @@ struct usbh_hid { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */ + struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */ + struct usbh_urb intin_urb; /* INTR IN urb */ + struct usbh_urb intout_urb; /* INTR OUT urb */ uint8_t report_desc[128]; uint8_t intf; /* interface number */ uint8_t minor; - usbh_pipe_t intin; /* INTR IN endpoint */ - usbh_pipe_t intout; /* INTR OUT endpoint */ }; #ifdef __cplusplus diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c index 930a9ffd..6c8020dd 100644 --- a/class/hub/usbh_hub.c +++ b/class/hub/usbh_hub.c @@ -5,14 +5,14 @@ */ #include "usbh_hub.h" -#define DEV_FORMAT "/dev/hub%d" +#define DEV_FORMAT "/dev/hub%d" #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 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE]; @@ -24,10 +24,8 @@ usb_osal_mq_t hub_mq; struct usbh_hub roothub; -extern int usbh_hport_activate_ep0(struct usbh_hubport *hport); -extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport); +extern int usbh_free_devaddr(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" }; @@ -101,7 +99,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer) setup->wIndex = 0; setup->wLength = USB_SIZEOF_HUB_DESC; - ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + ret = usbh_control_transfer(hub->parent, setup, g_hub_buf); if (ret < 0) { return ret; } @@ -122,7 +120,7 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer) setup->wIndex = 0; setup->wLength = 2; - ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + ret = usbh_control_transfer(hub->parent, setup, g_hub_buf); if (ret < 0) { return ret; } @@ -145,7 +143,7 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h setup->wIndex = port; setup->wLength = 4; - ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + ret = usbh_control_transfer(hub->parent, setup, g_hub_buf); if (ret < 0) { return ret; } @@ -165,7 +163,7 @@ static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t fea setup->wIndex = port; setup->wLength = 0; - return usbh_control_transfer(hub->parent->ep0, setup, NULL); + return usbh_control_transfer(hub->parent, setup, NULL); } static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) @@ -180,7 +178,7 @@ static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t f setup->wIndex = port; setup->wLength = 0; - return usbh_control_transfer(hub->parent->ep0, setup, NULL); + return usbh_control_transfer(hub->parent, setup, NULL); } static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth) @@ -195,7 +193,7 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth) setup->wIndex = 0; setup->wLength = 0; - return usbh_control_transfer(hub->parent->ep0, setup, NULL); + return usbh_control_transfer(hub->parent, setup, NULL); } #if CONFIG_USBHOST_MAX_EXTHUBS > 0 @@ -294,13 +292,31 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth) } } +static void usbh_hub_thread_wakeup(struct usbh_hub *hub) +{ + usb_osal_mq_send(hub_mq, (uintptr_t)hub); +} + +static void usbh_hubport_release(struct usbh_hubport *child) +{ + if (child->connected) { + child->connected = false; + usbh_free_devaddr(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; + } +} + #if CONFIG_USBHOST_MAX_EXTHUBS > 0 static void hub_int_complete_callback(void *arg, int nbytes) { struct usbh_hub *hub = (struct usbh_hub *)arg; - if (nbytes > 0) - { + if (nbytes > 0) { usbh_hub_thread_wakeup(hub); } } @@ -336,7 +352,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf) ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&hub->intin, hport, ep_desc); + USBH_EP_INIT(hub->intin, ep_desc); } else { return -1; } @@ -376,7 +392,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf) USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname); hub->int_buffer = g_hub_intbuf[hub->index - 1]; - usbh_int_urb_fill(&hub->intin_urb, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub); + usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub); usbh_submit_urb(&hub->intin_urb); return 0; } @@ -390,19 +406,12 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) if (hub) { if (hub->intin) { - usbh_pipe_free(hub->intin); + usbh_kill_urb(&hub->intin_urb); } for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { child = &hub->child[port]; - 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; + usbh_hubport_release(child); child->parent = NULL; } @@ -417,27 +426,10 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) } #endif -static void usbh_hubport_release(struct usbh_hubport *child) -{ - 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_hubport_enumerate_thread(void *argument) { struct usbh_hubport *child = (struct usbh_hubport *)argument; - /* Configure EP0 with the default maximum packet size */ - usbh_hport_activate_ep0(child); - if (usbh_enumerate(child) < 0) { /** release child sources */ usbh_hubport_release(child); @@ -662,11 +654,6 @@ static void usbh_roothub_register(void) usbh_hub_register(&roothub); } -static void usbh_hub_thread_wakeup(struct usbh_hub *hub) -{ - usb_osal_mq_send(hub_mq, (uintptr_t)hub); -} - void usbh_roothub_thread_wakeup(uint8_t port) { roothub.int_buffer = g_hub_intbuf[roothub.index - 1]; diff --git a/class/msc/usbh_msc.c b/class/msc/usbh_msc.c index d492be29..3ac62377 100644 --- a/class/msc/usbh_msc.c +++ b/class/msc/usbh_msc.c @@ -50,7 +50,7 @@ static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer) setup->wIndex = msc_class->intf; setup->wLength = 1; - return usbh_control_transfer(msc_class->hport->ep0, setup, buffer); + return usbh_control_transfer(msc_class->hport, setup, buffer); } static void usbh_msc_cbw_dump(struct CBW *cbw) @@ -87,9 +87,8 @@ static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t { int ret; struct usbh_urb *urb = &msc_class->bulkin_urb; - memset(urb, 0, sizeof(struct usbh_urb)); - usbh_bulk_urb_fill(urb, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL); + usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL); ret = usbh_submit_urb(urb); if (ret == 0) { ret = urb->actual_length; @@ -101,9 +100,8 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t { int ret; struct usbh_urb *urb = &msc_class->bulkout_urb; - memset(urb, 0, sizeof(struct usbh_urb)); - usbh_bulk_urb_fill(urb, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL); + usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL); ret = usbh_submit_urb(urb); if (ret == 0) { ret = urb->actual_length; @@ -111,7 +109,7 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t return ret; } -int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer) +static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer) { int nbytes; @@ -236,55 +234,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class) return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf); } -int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors) -{ - struct CBW *cbw; - - /* Construct the CBW */ - cbw = (struct CBW *)g_msc_buf; - memset(cbw, 0, USB_SIZEOF_MSC_CBW); - cbw->dSignature = MSC_CBW_Signature; - - cbw->dDataLength = (msc_class->blocksize * nsectors); - cbw->bCBLength = SCSICMD_WRITE10_SIZEOF; - cbw->CB[0] = SCSI_CMD_WRITE10; - - SET_BE32(&cbw->CB[2], start_sector); - SET_BE16(&cbw->CB[7], nsectors); - - return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer); -} - -int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors) -{ - struct CBW *cbw; - - /* Construct the CBW */ - cbw = (struct CBW *)g_msc_buf; - memset(cbw, 0, USB_SIZEOF_MSC_CBW); - cbw->dSignature = MSC_CBW_Signature; - - cbw->dDataLength = (msc_class->blocksize * nsectors); - cbw->bmFlags = 0x80; - cbw->bCBLength = SCSICMD_READ10_SIZEOF; - cbw->CB[0] = SCSI_CMD_READ10; - - SET_BE32(&cbw->CB[2], start_sector); - SET_BE16(&cbw->CB[7], nsectors); - - return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer); -} - -void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config) -{ - if (config) { - g_msc_modeswitch_config = config; - } else { - g_msc_modeswitch_config = NULL; - } -} - -void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message) +static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message) { struct CBW *cbw; @@ -323,9 +273,9 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&msc_class->bulkin, hport, ep_desc); + USBH_EP_INIT(msc_class->bulkin, ep_desc); } else { - usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc); + USBH_EP_INIT(msc_class->bulkout, ep_desc); } } @@ -390,11 +340,11 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) if (msc_class) { if (msc_class->bulkin) { - usbh_pipe_free(msc_class->bulkin); + usbh_kill_urb(&msc_class->bulkin_urb); } if (msc_class->bulkout) { - usbh_pipe_free(msc_class->bulkout); + usbh_kill_urb(&msc_class->bulkout_urb); } if (hport->config.intf[intf].devname[0] != '\0') { @@ -408,6 +358,55 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } + +int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors) +{ + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)g_msc_buf; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = (msc_class->blocksize * nsectors); + cbw->bCBLength = SCSICMD_WRITE10_SIZEOF; + cbw->CB[0] = SCSI_CMD_WRITE10; + + SET_BE32(&cbw->CB[2], start_sector); + SET_BE16(&cbw->CB[7], nsectors); + + return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer); +} + +int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors) +{ + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)g_msc_buf; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = (msc_class->blocksize * nsectors); + cbw->bmFlags = 0x80; + cbw->bCBLength = SCSICMD_READ10_SIZEOF; + cbw->CB[0] = SCSI_CMD_READ10; + + SET_BE32(&cbw->CB[2], start_sector); + SET_BE16(&cbw->CB[7], nsectors); + + return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer); +} + +void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config) +{ + if (config) { + g_msc_modeswitch_config = config; + } else { + g_msc_modeswitch_config = NULL; + } +} + __WEAK void usbh_msc_run(struct usbh_msc *msc_class) { } diff --git a/class/msc/usbh_msc.h b/class/msc/usbh_msc.h index 04cc9ceb..93c99f1a 100644 --- a/class/msc/usbh_msc.h +++ b/class/msc/usbh_msc.h @@ -11,15 +11,15 @@ struct usbh_msc { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usbh_urb bulkin_urb; /* Bulk IN urb */ + struct usbh_urb bulkout_urb; /* Bulk OUT urb */ uint8_t intf; /* Data interface number */ uint8_t sdchar; - usbh_pipe_t bulkin; /* Bulk IN endpoint */ - usbh_pipe_t bulkout; /* Bulk OUT endpoint */ - struct usbh_urb bulkin_urb; /* Bulk IN urb */ - struct usbh_urb bulkout_urb; /* Bulk OUT urb */ - uint32_t blocknum; /* Number of blocks on the USB mass storage device */ - uint16_t blocksize; /* Block size of USB mass storage device */ + uint32_t blocknum; /* Number of blocks on the USB mass storage device */ + uint16_t blocksize; /* Block size of USB mass storage device */ }; struct usbh_msc_modeswitch_config { diff --git a/class/video/usbh_video.c b/class/video/usbh_video.c index 8521d26c..d3404c0d 100644 --- a/class/video/usbh_video.c +++ b/class/video/usbh_video.c @@ -67,7 +67,7 @@ int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf retry = 0; while (1) { - ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf); + ret = usbh_control_transfer(video_class->hport, setup, g_video_buf); if (ret > 0) { break; } @@ -98,7 +98,7 @@ int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf memcpy(g_video_buf, buf, len); - ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf); + ret = usbh_control_transfer(video_class->hport, setup, g_video_buf); usb_osal_msleep(50); return ret; } @@ -233,7 +233,7 @@ int usbh_video_open(struct usbh_video *video_class, setup->wIndex = video_class->data_intf; setup->wLength = 0; - ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL); + ret = usbh_control_transfer(video_class->hport, setup, NULL); if (ret < 0) { goto errout; } @@ -243,10 +243,10 @@ int usbh_video_open(struct usbh_video *video_class, mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; if (ep_desc->bEndpointAddress & 0x80) { video_class->isoin_mps = mps * (mult + 1); - usbh_hport_activate_epx(&video_class->isoin, video_class->hport, ep_desc); + USBH_EP_INIT(video_class->isoin, ep_desc); } else { video_class->isoout_mps = mps * (mult + 1); - usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc); + USBH_EP_INIT(video_class->isoout, ep_desc); } USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting); @@ -269,12 +269,10 @@ int usbh_video_close(struct usbh_video *video_class) 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; } @@ -284,7 +282,7 @@ int usbh_video_close(struct usbh_video *video_class) setup->wIndex = video_class->data_intf; setup->wLength = 0; - ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL); + ret = usbh_control_transfer(video_class->hport, setup, NULL); if (ret < 0) { return ret; } @@ -455,11 +453,9 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf) if (video_class) { if (video_class->isoin) { - usbh_pipe_free(video_class->isoin); } if (video_class->isoout) { - usbh_pipe_free(video_class->isoout); } if (hport->config.intf[intf].devname[0] != '\0') { diff --git a/class/video/usbh_video.h b/class/video/usbh_video.h index 3357c14c..f4e06d78 100644 --- a/class/video/usbh_video.h +++ b/class/video/usbh_video.h @@ -32,12 +32,12 @@ struct usbh_videostreaming { struct usbh_video { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */ + struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */ uint8_t ctrl_intf; /* interface number */ uint8_t data_intf; /* interface number */ uint8_t minor; - usbh_pipe_t isoin; /* ISO IN endpoint */ - usbh_pipe_t isoout; /* ISO OUT endpoint */ struct video_probe_and_commit_controls probe; struct video_probe_and_commit_controls commit; uint16_t isoin_mps; diff --git a/class/wireless/usbd_rndis.c b/class/wireless/usbd_rndis.c index ea00cbf5..5ddc3f24 100644 --- a/class/wireless/usbd_rndis.c +++ b/class/wireless/usbd_rndis.c @@ -45,8 +45,8 @@ struct usbd_rndis_priv { #define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156 #endif -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8]; diff --git a/class/wireless/usbh_rndis.c b/class/wireless/usbh_rndis.c index 762fc6e9..2437da78 100644 --- a/class/wireless/usbh_rndis.c +++ b/class/wireless/usbh_rndis.c @@ -11,8 +11,33 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096]; +#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514 +#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44) + +/* eth rx size must be a multiple of 512 or 64 */ +#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048) +#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048) + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE]; +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE]; +// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16]; + static struct usbh_rndis g_rndis_class; +static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class) +{ + // int ret; + // struct usbh_urb *urb = &rndis_class->intin_urb; + + // usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL); + // ret = usbh_submit_urb(urb); + // if (ret == 0) { + // ret = urb->actual_length; + // } + // return ret; + return 0; +} + static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) { struct usb_setup_packet *setup = rndis_class->hport->setup; @@ -35,13 +60,13 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) setup->wIndex = 0; setup->wLength = sizeof(rndis_initialize_msg_t); - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret); return ret; } - //ret = usbh_ep_intr_transfer() + usbh_rndis_get_notification(rndis_class); resp = (rndis_initialize_cmplt_t *)g_rndis_buf; @@ -51,7 +76,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) setup->wIndex = 0; setup->wLength = 4096; - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); if (ret < 0) { USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret); return ret; @@ -83,13 +108,13 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, setup->wIndex = 0; setup->wLength = query_len + sizeof(rndis_query_msg_t); - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret); return ret; } - //ret = usbh_ep_intr_transfer() + usbh_rndis_get_notification(rndis_class); resp = (rndis_query_cmplt_t *)g_rndis_buf; @@ -99,7 +124,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, setup->wIndex = 0; setup->wLength = 4096; - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); if (ret < 0) { USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret); return ret; @@ -135,13 +160,13 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t setup->wIndex = 0; setup->wLength = info_len + sizeof(rndis_set_msg_t); - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret); return ret; } - //ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500); + usbh_rndis_get_notification(rndis_class); resp = (rndis_set_cmplt_t *)g_rndis_buf; @@ -151,7 +176,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t setup->wIndex = 0; setup->wLength = 4096; - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); if (ret < 0) { USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret); return ret; @@ -160,32 +185,22 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t return ret; } -int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +static int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class) { int ret; - struct usbh_urb *urb = &rndis_class->bulkout_urb; - memset(urb, 0, sizeof(struct usbh_urb)); + uint8_t data[32]; + uint32_t data_len; - usbh_bulk_urb_fill(urb, rndis_class->bulkout, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len); + if (ret < 0) { + return ret; } - return ret; -} - -int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usbh_urb *urb = &rndis_class->bulkin_urb; - memset(urb, 0, sizeof(struct usbh_urb)); - - usbh_bulk_urb_fill(urb, rndis_class->bulkin, buffer, buflen, timeout, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; + if (NDIS_MEDIA_STATE_CONNECTED == data[0]) { + rndis_class->link_status = true; + } else { + rndis_class->link_status = false; } - return ret; + return 0; } int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) @@ -207,13 +222,13 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) setup->wIndex = 0; setup->wLength = sizeof(rndis_keepalive_msg_t); - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret); return ret; } - //ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500); + usbh_rndis_get_notification(rndis_class); resp = (rndis_keepalive_cmplt_t *)g_rndis_buf; @@ -223,7 +238,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) setup->wIndex = 0; setup->wLength = 4096; - ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp); + ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); if (ret < 0) { USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret); return ret; @@ -254,17 +269,16 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) hport->config.intf[intf].priv = rndis_class; hport->config.intf[intf + 1].priv = NULL; -#ifdef CONFIG_USBHOST_RNDIS_NOTIFY - ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc; - usbh_hport_activate_epx(&rndis_class->intin, hport, ep_desc); -#endif + // ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc; + // USBH_EP_INIT(rndis_class->intin, ep_desc); + for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { - usbh_hport_activate_epx(&rndis_class->bulkin, hport, ep_desc); + USBH_EP_INIT(rndis_class->bulkin, ep_desc); } else { - usbh_hport_activate_epx(&rndis_class->bulkout, hport, ep_desc); + USBH_EP_INIT(rndis_class->bulkout, ep_desc); } } @@ -360,6 +374,14 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) } USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n"); + USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n", + rndis_class->mac[0], + rndis_class->mac[1], + rndis_class->mac[2], + rndis_class->mac[3], + rndis_class->mac[4], + rndis_class->mac[5]); + memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN); USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname); @@ -378,13 +400,17 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf) if (rndis_class) { if (rndis_class->bulkin) { - usbh_pipe_free(rndis_class->bulkin); + usbh_kill_urb(&rndis_class->bulkin_urb); } if (rndis_class->bulkout) { - usbh_pipe_free(rndis_class->bulkout); + usbh_kill_urb(&rndis_class->bulkout_urb); } + // if (rndis_class->intin) { + // usbh_kill_urb(&rndis_class->intin_urb); + // } + if (hport->config.intf[intf].devname[0] != '\0') { USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname); usbh_rndis_stop(rndis_class); @@ -396,6 +422,123 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } +static void usbh_rndis_rx_thread(void *argument) +{ + uint32_t g_rndis_rx_length; + uint32_t pmg_offset; + uint32_t payload_offset; + int ret; + err_t err; + struct pbuf *p, *q; + rndis_data_packet_t *pmsg; + rndis_data_packet_t temp; + struct netif *netif = (struct netif *)argument; + + // clang-format off +find_class: + // clang-format on + g_rndis_class.link_status = false; + while (usbh_find_class_instance("/dev/rndis") == NULL) { + usb_osal_msleep(1000); + } + + while (g_rndis_class.link_status == false) { + ret = usbh_rndis_get_connect_status(&g_rndis_class); + if (ret < 0) { + goto find_class; + } + } + + while (1) { + g_rndis_rx_length = 0; + usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&g_rndis_class.bulkin_urb); + if (ret < 0) { + goto find_class; + } + + g_rndis_rx_length = g_rndis_class.bulkin_urb.actual_length; + pmg_offset = 0; + while (g_rndis_rx_length > 0) { + USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length); + + pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset); + + /* Not word-aligned case */ + if (pmg_offset & 0x3) { + memcpy(&temp, pmsg, sizeof(rndis_data_packet_t)); + pmsg = &temp; + } + + if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) { + p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL); + if (p != NULL) { + payload_offset = 0; + for (q = p; q != NULL; q = q->next) { + void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset); + memcpy(q->payload, src, q->len); + payload_offset += q->len; + } + + err = netif->input(p, netif); + if (err != ERR_OK) { + pbuf_free(p); + } + pmg_offset += pmsg->MessageLength; + g_rndis_rx_length -= pmsg->MessageLength; + } else { + USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n"); + } + } + } + } +} + +err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p) +{ + int ret; + struct pbuf *q; + uint8_t *buffer; + rndis_data_packet_t *hdr; + + if (g_rndis_class.link_status == false) { + return ERR_BUF; + } + + hdr = (rndis_data_packet_t *)g_rndis_tx_buffer; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t); + hdr->DataLength = p->tot_len; + + buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t)); + for (q = p; q != NULL; q = q->next) { + memcpy(buffer, q->payload, q->len); + buffer += q->len; + } + /* send */ + if ((hdr->MessageLength & 0x1FF) == 0) { + /* pad a dummy. */ + hdr->MessageLength += 1; + } + + USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength); + + usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&g_rndis_class.bulkout_urb); + if (ret < 0) { + return ERR_BUF; + } + + return ERR_OK; +} + +void usbh_rndis_lwip_thread_init(struct netif *netif) +{ + usb_osal_thread_create("usbh_rndis_rx", 2560, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, netif); +} + __WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class) { } diff --git a/class/wireless/usbh_rndis.h b/class/wireless/usbh_rndis.h index 8f3e2244..c55c113f 100644 --- a/class/wireless/usbh_rndis.h +++ b/class/wireless/usbh_rndis.h @@ -8,36 +8,45 @@ #include "usb_cdc.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + struct usbh_rndis { struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + struct usb_endpoint_descriptor *intin; /* INTR endpoint */ + struct usbh_urb bulkin_urb; /* Bulk IN urb */ + struct usbh_urb bulkout_urb; /* Bulk OUT urb */ + struct usbh_urb intin_urb; /* INTR IN urb */ uint8_t ctrl_intf; /* Control interface number */ uint8_t data_intf; /* Data interface number */ uint8_t minor; - usbh_pipe_t bulkin; /* Bulk IN endpoint */ - usbh_pipe_t bulkout; /* Bulk OUT endpoint */ - usbh_pipe_t intin; /* Notify endpoint */ - struct usbh_urb bulkin_urb; /* Bulk IN urb */ - struct usbh_urb bulkout_urb; /* Bulk OUT urb */ + uint32_t request_id; uint32_t link_speed; bool link_status; uint8_t mac[6]; + + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gateway; }; #ifdef __cplusplus extern "C" { #endif -int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); -int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - int usbh_rndis_keepalive(struct usbh_rndis *rndis_class); void usbh_rndis_run(struct usbh_rndis *rndis_class); void usbh_rndis_stop(struct usbh_rndis *rndis_class); +err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p); +void usbh_rndis_lwip_thread_init(struct netif *netif); + #ifdef __cplusplus } #endif diff --git a/common/usb_def.h b/common/usb_def.h index 31cb2b8e..8fc76d17 100644 --- a/common/usb_def.h +++ b/common/usb_def.h @@ -221,6 +221,7 @@ #define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT) #define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT) #define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT) +#define USB_GET_ENDPOINT_TYPE(x) ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT) #define USB_ENDPOINT_SYNC_SHIFT 2 #define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT) @@ -245,6 +246,8 @@ #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT) #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT) #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT) +#define USB_GET_MAXPACKETSIZE(x) ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT) +#define USB_GET_MULT(x) ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT) /* bDevCapabilityType in Device Capability Descriptor */ #define USB_DEVICE_CAPABILITY_WIRELESS_USB 1 diff --git a/common/usb_hc.h b/common/usb_hc.h index 95215841..2596a50c 100644 --- a/common/usb_hc.h +++ b/common/usb_hc.h @@ -13,21 +13,6 @@ extern "C" { #endif typedef void (*usbh_complete_callback_t)(void *arg, int nbytes); -typedef void *usbh_pipe_t; - -/** - * @brief USB Endpoint Configuration. - * - * Structure containing the USB endpoint configuration. - */ -struct usbh_endpoint_cfg { - struct usbh_hubport *hport; - 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_interval; /* Endpoint interval */ - uint8_t mult; /* Endpoint additional transcation */ -}; /** * @brief USB Iso Configuration. @@ -47,7 +32,10 @@ struct usbh_iso_frame_packet { * Structure containing the USB Urb configuration. */ struct usbh_urb { - usbh_pipe_t pipe; + void *hcpriv; + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *ep; + uint8_t data_toggle; struct usb_setup_packet *setup; uint8_t *transfer_buffer; uint32_t transfer_buffer_length; @@ -88,34 +76,6 @@ uint16_t usbh_get_frame_number(void); */ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf); -/** - * @brief reconfig endpoint pipe. - * - * @param pipe A memory allocated for pipe. - * @param dev_addr device address. - * @param ep_mps endpoint max packet size. - * @param mult endpoint additional transcation - * @return On success will return 0, and others indicate fail. - */ -int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult); - -/** - * @brief Allocate pipe for endpoint - * - * @param pipe A memory location provided by the caller in which to save the allocated pipe. - * @param ep_cfg Describes the endpoint info to be allocated. - * @return On success will return 0, and others indicate fail. - */ -int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg); - -/** - * @brief Free a pipe in which saves endpoint info. - * - * @param pipe A memory location provided by the caller in which to free the allocated endpoint info. - * @return On success will return 0, and others indicate fail. - */ -int usbh_pipe_free(usbh_pipe_t pipe); - /** * @brief Submit a usb transfer request to an endpoint. * diff --git a/core/usbh_core.c b/core/usbh_core.c index baecb438..025d0ecf 100644 --- a/core/usbh_core.c +++ b/core/usbh_core.c @@ -64,7 +64,7 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen) } } -static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr) +static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr) { int index; int bitno; @@ -340,57 +340,18 @@ static int usbh_get_default_mps(int speed) } } -int usbh_hport_activate_ep0(struct usbh_hubport *hport) -{ - struct usbh_endpoint_cfg ep0_cfg = { 0 }; - - ep0_cfg.ep_addr = 0x00; - ep0_cfg.ep_interval = 0x00; - ep0_cfg.ep_mps = usbh_get_default_mps(hport->speed); - ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL; - ep0_cfg.hport = hport; - - usbh_pipe_alloc(&hport->ep0, &ep0_cfg); - return 0; -} - -int usbh_hport_deactivate_ep0(struct usbh_hubport *hport) +int usbh_free_devaddr(struct usbh_hubport *hport) { #ifndef CONFIG_USBHOST_XHCI if (hport->dev_addr > 0) { - usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr); + __usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr); } #endif - if (hport->ep0) { - usbh_pipe_free(hport->ep0); - } - hport->ep0 = NULL; hport->dev_addr = 0; return 0; } -int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc) -{ - struct usbh_endpoint_cfg ep_cfg = { 0 }; - - ep_cfg.ep_addr = ep_desc->bEndpointAddress; - ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; - ep_cfg.ep_interval = ep_desc->bInterval; - ep_cfg.mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT; - ep_cfg.hport = hport; - - USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", - ep_cfg.ep_addr, - ep_desc->bmAttributes, - ep_cfg.ep_mps, - ep_cfg.ep_interval, - ep_cfg.mult); - - return usbh_pipe_alloc(pipe, &ep_cfg); -} - int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output) { struct usb_setup_packet *setup = hport->setup; @@ -408,7 +369,7 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out setup->wIndex = 0x0409; setup->wLength = 255; - ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); + ret = usbh_control_transfer(hport, setup, ep0_request_buffer); if (ret < 0) { return ret; } @@ -436,7 +397,7 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett setup->wIndex = altsetting; setup->wLength = 0; - return usbh_control_transfer(hport->ep0, setup, NULL); + return usbh_control_transfer(hport, setup, NULL); } int usbh_enumerate(struct usbh_hubport *hport) @@ -444,12 +405,25 @@ int usbh_enumerate(struct usbh_hubport *hport) struct usb_interface_descriptor *intf_desc; struct usb_setup_packet *setup; struct usb_device_descriptor *dev_desc; + struct usb_endpoint_descriptor *ep; int dev_addr; uint16_t ep_mps; int ret; hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1]; setup = hport->setup; + ep = &hport->ep0; + + /* Config EP0 mps from speed */ + ep->bEndpointAddress = 0x00; + ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT; + ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL; + ep->wMaxPacketSize = usbh_get_default_mps(hport->speed); + ep->bInterval = 0; + ep->bLength = 7; + + /* Configure EP0 with zero address */ + hport->dev_addr = 0; /* Read the first 8 bytes of the device descriptor */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -458,7 +432,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = 8; - ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); + ret = usbh_control_transfer(hport, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret); goto errout; @@ -479,7 +453,7 @@ int usbh_enumerate(struct usbh_hubport *hport) dev_desc->bDeviceProtocol, ep_mps); /* Reconfigure EP0 with the correct maximum packet size */ - usbh_ep_pipe_reconfigure(hport->ep0, 0, ep_mps, 0); + ep->wMaxPacketSize = ep_mps; #ifdef CONFIG_USBHOST_XHCI extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe); @@ -506,7 +480,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = 0; - ret = usbh_control_transfer(hport->ep0, setup, NULL); + ret = usbh_control_transfer(hport, setup, NULL); if (ret < 0) { USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret); goto errout; @@ -515,12 +489,9 @@ int usbh_enumerate(struct usbh_hubport *hport) /* Wait device set address completely */ usb_osal_msleep(2); - /* Assign the function address to the port */ + /*Reconfigure EP0 with the correct address */ hport->dev_addr = dev_addr; - /* And reconfigure EP0 with the correct address */ - usbh_ep_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, 0); - /* Read the full device descriptor */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; @@ -528,7 +499,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = USB_SIZEOF_DEVICE_DESC; - ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); + ret = usbh_control_transfer(hport, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret); goto errout; @@ -547,7 +518,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = USB_SIZEOF_CONFIG_DESC; - ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); + ret = usbh_control_transfer(hport, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret); goto errout; @@ -564,7 +535,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = wTotalLength; - ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); + ret = usbh_control_transfer(hport, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret); goto errout; @@ -623,7 +594,7 @@ int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = 0; - ret = usbh_control_transfer(hport->ep0, setup, NULL); + ret = usbh_control_transfer(hport, setup, NULL); if (ret < 0) { USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret); goto errout; @@ -670,27 +641,6 @@ errout: return ret; } -void *usbh_find_class_instance(const char *devname) -{ - struct usbh_hubport *hport; - usb_slist_t *hub_list; - - usb_slist_for_each(hub_list, &hub_class_head) - { - struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list); - for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { - hport = &hub->child[port]; - if (hport->connected) { - for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { - if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv) - return hport->config.intf[itf].priv; - } - } - } - } - return NULL; -} - int usbh_initialize(void) { memset(&g_usbh_bus, 0, sizeof(struct usbh_bus)); @@ -717,7 +667,7 @@ int usbh_initialize(void) return 0; } -int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer) +int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer) { struct usbh_urb *urb; int ret; @@ -725,7 +675,7 @@ int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint urb = usb_malloc(sizeof(struct usbh_urb)); memset(urb, 0, sizeof(struct usbh_urb)); - usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL); + usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL); ret = usbh_submit_urb(urb); if (ret == 0) { @@ -735,6 +685,27 @@ int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint return ret; } +void *usbh_find_class_instance(const char *devname) +{ + struct usbh_hubport *hport; + usb_slist_t *hub_list; + + usb_slist_for_each(hub_list, &hub_class_head) + { + struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port]; + if (hport->connected) { + for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { + if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv) + return hport->config.intf[itf].priv; + } + } + } + } + return NULL; +} + int lsusb(int argc, char **argv) { usb_slist_t *i; diff --git a/core/usbh_core.h b/core/usbh_core.h index d5a7c6ea..5f538329 100644 --- a/core/usbh_core.h +++ b/core/usbh_core.h @@ -32,8 +32,8 @@ extern "C" { #define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008 #define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010 -#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i)) -#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) +#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i)) +#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) #ifdef __ARMCC_VERSION /* ARM C Compiler */ #define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) @@ -44,57 +44,16 @@ extern "C" { #define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) #endif -static inline void usbh_control_urb_fill(struct usbh_urb *urb, - usbh_pipe_t pipe, - struct usb_setup_packet *setup, - uint8_t *transfer_buffer, - uint32_t transfer_buffer_length, - uint32_t timeout, - usbh_complete_callback_t complete, - void *arg) -{ - urb->pipe = pipe; - urb->setup = setup; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = transfer_buffer_length; - urb->timeout = timeout; - urb->complete = complete; - urb->arg = arg; -} - -static inline void usbh_bulk_urb_fill(struct usbh_urb *urb, - usbh_pipe_t pipe, - uint8_t *transfer_buffer, - uint32_t transfer_buffer_length, - uint32_t timeout, - usbh_complete_callback_t complete, - void *arg) -{ - urb->pipe = pipe; - urb->setup = NULL; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = transfer_buffer_length; - urb->timeout = timeout; - urb->complete = complete; - urb->arg = arg; -} - -static inline void usbh_int_urb_fill(struct usbh_urb *urb, - usbh_pipe_t pipe, - uint8_t *transfer_buffer, - uint32_t transfer_buffer_length, - uint32_t timeout, - usbh_complete_callback_t complete, - void *arg) -{ - urb->pipe = pipe; - urb->setup = NULL; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = transfer_buffer_length; - urb->timeout = timeout; - urb->complete = complete; - urb->arg = arg; -} +#define USBH_EP_INIT(ep, ep_desc) \ + do { \ + ep = ep_desc; \ + USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \ + ep_desc->bEndpointAddress, \ + USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \ + USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \ + ep_desc->bInterval, \ + USB_GET_MULT(ep_desc->bmAttributes)); \ + } while (0) struct usbh_class_info { uint8_t match_flags; /* Used for product specific matches; range is inclusive */ @@ -140,7 +99,7 @@ struct usbh_hubport { uint8_t port; /* Hub port index */ uint8_t dev_addr; /* device address */ uint8_t speed; /* device speed */ - usbh_pipe_t ep0; /* control ep pipe info */ + struct usb_endpoint_descriptor ep0; struct usb_device_descriptor device_desc; struct usbh_configuration config; const char *iManufacturer; @@ -161,7 +120,7 @@ struct usbh_hub { bool is_roothub; uint8_t index; uint8_t hub_addr; - usbh_pipe_t intin; + struct usb_endpoint_descriptor *intin; uint8_t *int_buffer; struct usbh_urb intin_urb; struct usb_hub_descriptor hub_desc; @@ -169,17 +128,62 @@ struct usbh_hub { struct usbh_hubport *parent; }; -/** - * @brief Activates an endpoint for a USB host pipe on a specific hub port. - * - * This function is responsible for activating the specified endpoint - * described by the given endpoint descriptor on the USB host pipe. - * @param pipe Pointer to the USB host pipe structure. - * @param hport Pointer to the USB hub port structure. - * @param ep_desc Pointer to the USB endpoint descriptor. - * @return On success will return 0, and others indicate fail. - */ -int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc); +static inline void usbh_control_urb_fill(struct usbh_urb *urb, + struct usbh_hubport *hport, + struct usb_setup_packet *setup, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->hport = hport; + urb->ep = &hport->ep0; + urb->setup = setup; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} + +static inline void usbh_bulk_urb_fill(struct usbh_urb *urb, + struct usbh_hubport *hport, + struct usb_endpoint_descriptor *ep, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->hport = hport; + urb->ep = ep; + urb->setup = NULL; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} + +static inline void usbh_int_urb_fill(struct usbh_urb *urb, + struct usbh_hubport *hport, + struct usb_endpoint_descriptor *ep, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->hport = hport; + urb->ep = ep; + urb->setup = NULL; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} /** * @brief Submit an control transfer to an endpoint. @@ -191,7 +195,7 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc * @param buffer buffer used for sending the request and for returning any responses. * @return On success will return 0, and others indicate fail. */ -int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer); +int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer); /** * @brief Retrieves a USB string descriptor from a specific hub port. diff --git a/demo/usb_host.c b/demo/usb_host.c index 9d156fc3..e25764d4 100644 --- a/demo/usb_host.c +++ b/demo/usb_host.c @@ -12,13 +12,11 @@ #define TEST_USBH_AUDIO 0 #define TEST_USBH_VIDEO 0 #define TEST_USBH_CDC_ECM 0 +#define TEST_USBH_RNDIS 0 #if TEST_USBH_CDC_ACM USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[512]; -struct usbh_urb cdc_bulkin_urb; -struct usbh_urb cdc_bulkout_urb; - void usbh_cdc_acm_callback(void *arg, int nbytes) { //struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg; @@ -48,31 +46,19 @@ find_class: } memset(cdc_buffer, 0, 512); - usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, NULL, NULL); - ret = usbh_submit_urb(&cdc_bulkin_urb); - if (ret < 0) { - USB_LOG_RAW("bulk in error,ret:%d\r\n", ret); - } else { - USB_LOG_RAW("recv over:%d\r\n", cdc_bulkin_urb.actual_length); - for (size_t i = 0; i < cdc_bulkin_urb.actual_length; i++) { - USB_LOG_RAW("0x%02x ", cdc_buffer[i]); - } - } - - USB_LOG_RAW("\r\n"); const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 }; - memcpy(cdc_buffer, data1, 8); - usbh_bulk_urb_fill(&cdc_bulkout_urb, cdc_acm_class->bulkout, cdc_buffer, 8, 3000, NULL, NULL); - ret = usbh_submit_urb(&cdc_bulkout_urb); + memcpy(cdc_buffer, data1, 10); + usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, cdc_buffer, 10, 3000, NULL, NULL); + ret = usbh_submit_urb(&cdc_acm_class->bulkout_urb); if (ret < 0) { USB_LOG_RAW("bulk out error,ret:%d\r\n", ret); } else { - USB_LOG_RAW("send over:%d\r\n", cdc_bulkout_urb.actual_length); + USB_LOG_RAW("send over:%d\r\n", cdc_acm_class->bulkout_urb.actual_length); } - usbh_bulk_urb_fill(&cdc_bulkin_urb, cdc_acm_class->bulkin, cdc_buffer, 64, 3000, usbh_cdc_acm_callback, cdc_acm_class); - ret = usbh_submit_urb(&cdc_bulkin_urb); + usbh_bulk_urb_fill(&cdc_acm_class->bulkin_urb, cdc_acm_class->hport, cdc_acm_class->bulkin, cdc_buffer, cdc_acm_class->bulkin->wMaxPacketSize, 3000, usbh_cdc_acm_callback, cdc_acm_class); + ret = usbh_submit_urb(&cdc_acm_class->bulkin_urb); if (ret < 0) { USB_LOG_RAW("bulk in error,ret:%d\r\n", ret); } else { @@ -92,18 +78,16 @@ find_class: #if TEST_USBH_HID USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_buffer[128]; -struct usbh_urb hid_intin_urb; - void usbh_hid_callback(void *arg, int nbytes) { - //struct usbh_hid *hid_class = (struct usbh_hid *)arg; + struct usbh_hid *hid_class = (struct usbh_hid *)arg; if (nbytes > 0) { for (size_t i = 0; i < nbytes; i++) { USB_LOG_RAW("0x%02x ", hid_buffer[i]); } USB_LOG_RAW("nbytes:%d\r\n", nbytes); - usbh_submit_urb(&hid_intin_urb); + usbh_submit_urb(&hid_class->intin_urb); } } @@ -122,8 +106,8 @@ find_class: usb_osal_msleep(1500); continue; } - usbh_int_urb_fill(&hid_intin_urb, hid_class->intin, hid_buffer, 8, 0, usbh_hid_callback, hid_class); - ret = usbh_submit_urb(&hid_intin_urb); + usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_buffer, hid_class->intin->wMaxPacketSize, 0, usbh_hid_callback, hid_class); + ret = usbh_submit_urb(&hid_class->intin_urb); if (ret < 0) { usb_osal_msleep(1500); goto find_class; @@ -441,6 +425,98 @@ void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class) } #endif +#if TEST_USBH_RNDIS + +#include "usbh_rndis.h" + +#include "netif/etharp.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif + +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "timers.h" + +struct netif g_rndis_netif; + +TimerHandle_t timer_handle; + +static void rndis_dev_keepalive_timeout(TimerHandle_t xTimer) +{ + struct usbh_rndis *rndis_class = (struct usbh_rndis *)pvTimerGetTimerID(xTimer); + usbh_rndis_keepalive(rndis_class); +} + +void timer_init(struct usbh_rndis *rndis_class) +{ + timer_handle = xTimerCreate((const char *)NULL, (TickType_t)3000, (UBaseType_t)pdTRUE, (void *const)rndis_class, (TimerCallbackFunction_t)rndis_dev_keepalive_timeout); + if (NULL != timer_handle) { + xTimerStart(timer_handle, 0); + } else { + printf("timer creation failed!.\n"); + for (;;) { + ; + } + } +} + +static err_t usbh_rndis_if_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->output = etharp_output; + netif->linkoutput = usbh_rndis_linkoutput; + return ERR_OK; +} + +void usbh_rndis_run(struct usbh_rndis *rndis_class) +{ + struct netif *netif = &g_rndis_netif; + + netif->hwaddr_len = 6; + memcpy(netif->hwaddr, rndis_class->mac, 6); + + IP4_ADDR(&rndis_class->ipaddr, 0, 0, 0, 0); + IP4_ADDR(&rndis_class->netmask, 0, 0, 0, 0); + IP4_ADDR(&rndis_class->gateway, 0, 0, 0, 0); + + netif = netif_add(netif, &rndis_class->ipaddr, &rndis_class->netmask, &rndis_class->gateway, NULL, usbh_rndis_if_init, tcpip_input); + netif_set_default(netif); + while (!netif_is_up(netif)) { + } + + timer_init(rndis_class); + +#if LWIP_DHCP + dhcp_start(netif); +#endif +} + +void usbh_rndis_stop(struct usbh_rndis *rndis_class) +{ + struct netif *netif = &g_rndis_netif; +#if LWIP_DHCP + dhcp_stop(netif); + dhcp_cleanup(netif); +#endif + netif_set_down(netif); + netif_remove(netif); + + xTimerStop(timer_handle, 0); + xTimerDelete(timer_handle, 0); +} +#endif + void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) { } @@ -500,10 +576,14 @@ void usbh_class_test(void) #error "if you want to use iso, please contact with me" usb_osal_thread_create("usbh_video", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_video_thread, NULL); #endif -#if TEST_USBH_CDC_ECM +#if TEST_USBH_CDC_ECM || TEST_USBH_RNDIS /* Initialize the LwIP stack */ tcpip_init(NULL, NULL); - +#endif +#if TEST_USBH_CDC_ECM usbh_cdc_ecm_lwip_thread_init(&g_cdc_ecm_netif); #endif +#if TEST_USBH_RNDIS + usbh_rndis_lwip_thread_init(&g_rndis_netif); +#endif } \ No newline at end of file diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c index 440c1139..d276fd19 100644 --- a/port/dwc2/usb_hc_dwc2.c +++ b/port/dwc2/usb_hc_dwc2.c @@ -30,24 +30,13 @@ #define USB_OTG_HC(i) ((USB_OTG_HostChannelTypeDef *)(USB_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE))) #define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE)) -struct dwc2_pipe { - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t ep_type; - uint8_t ep_interval; - uint8_t speed; - uint16_t ep_mps; - uint8_t data_pid; - uint8_t chidx; - volatile uint8_t ep0_state; +struct dwc2_chan { + uint8_t ep0_state; uint16_t num_packets; uint32_t xferlen; + uint8_t chidx; bool inuse; - uint32_t xfrd; - int errorcode; - volatile bool waiter; usb_osal_sem_t waitsem; - struct usbh_hubport *hport; struct usbh_urb *urb; uint32_t iso_frame_idx; }; @@ -56,7 +45,7 @@ struct dwc2_hcd { volatile bool port_csc; volatile bool port_pec; volatile bool port_occ; - struct dwc2_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM]; + struct dwc2_chan chan_pool[CONFIG_USBHOST_PIPE_NUM]; } g_dwc2_hcd; #define DWC2_EP0_STATE_SETUP 0 @@ -173,7 +162,7 @@ static inline void dwc2_drivebus(uint8_t state) } } -static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed) +static void dwc2_chan_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed) { uint32_t regval; @@ -236,7 +225,7 @@ static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin } /* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of ep_mps size.*/ -static inline void dwc2_pipe_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid) +static inline void dwc2_chan_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid) { __IO uint32_t tmpreg; uint8_t is_oddframe; @@ -361,13 +350,13 @@ static inline uint32_t dwc2_get_glb_intstatus(void) return tmpreg; } -static int dwc2_pipe_alloc(void) +static int dwc2_chan_alloc(void) { int chidx; for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { - if (!g_dwc2_hcd.pipe_pool[chidx].inuse) { - g_dwc2_hcd.pipe_pool[chidx].inuse = true; + if (!g_dwc2_hcd.chan_pool[chidx].inuse) { + g_dwc2_hcd.chan_pool[chidx].inuse = true; return chidx; } } @@ -375,9 +364,9 @@ static int dwc2_pipe_alloc(void) return -1; } -static void dwc2_pipe_free(struct dwc2_pipe *pipe) +static void dwc2_chan_free(struct dwc2_chan *chan) { - pipe->inuse = false; + chan->inuse = false; } static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size) @@ -403,46 +392,60 @@ static uint8_t dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, u return num_packets; } -static void dwc2_control_pipe_init(struct dwc2_pipe *chan, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) +static void dwc2_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { + struct dwc2_chan *chan; + + chan = &g_dwc2_hcd.chan_pool[chidx]; + if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */ { - chan->num_packets = dwc2_calculate_packet_num(8, 0x00, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP); + chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP); } else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */ { - chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chan->chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); } else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */ { - chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); } else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */ { - chan->num_packets = dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chan->chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); } else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) /* fill out status */ { - chan->num_packets = dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chan->chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + chan->num_packets = dwc2_calculate_packet_num(0, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); } } -static void dwc2_bulk_intr_pipe_init(struct dwc2_pipe *chan, uint8_t *buffer, uint32_t buflen) +static void dwc2_bulk_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen) { - chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); - dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); + struct dwc2_chan *chan; + + chan = &g_dwc2_hcd.chan_pool[chidx]; + + chan->num_packets = dwc2_calculate_packet_num(buflen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)buffer, chan->xferlen, chan->num_packets, urb->data_toggle); } -static void dwc2_iso_pipe_init(struct dwc2_pipe *chan, struct usbh_iso_frame_packet *iso_packet) +static void dwc2_iso_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usbh_iso_frame_packet *iso_packet) { - chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, chan->ep_addr, chan->ep_mps, &chan->xferlen); - dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0); + struct dwc2_chan *chan; + + chan = &g_dwc2_hcd.chan_pool[chidx]; + + chan->num_packets = dwc2_calculate_packet_num(iso_packet->transfer_buffer_length, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen); + dwc2_chan_init(chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed); + dwc2_chan_transfer(chidx, urb->ep->bEndpointAddress, (uint32_t *)iso_packet->transfer_buffer, chan->xferlen, chan->num_packets, HC_PID_DATA0); } __WEAK void usb_hc_low_level_init(void) @@ -456,7 +459,7 @@ int usb_hc_init(void) memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd)); for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { - g_dwc2_hcd.pipe_pool[chidx].waitsem = usb_osal_sem_create(0); + g_dwc2_hcd.chan_pool[chidx].waitsem = usb_osal_sem_create(0); } usb_hc_low_level_init(); @@ -681,137 +684,58 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) return 0; } -int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult) -{ - struct dwc2_pipe *chan; - - chan = (struct dwc2_pipe *)pipe; - - chan->dev_addr = dev_addr; - chan->ep_mps = ep_mps; - - return 0; -} - -int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) -{ - struct dwc2_pipe *chan; - int chidx; - usb_osal_sem_t waitsem; - - chidx = dwc2_pipe_alloc(); - if (chidx == -1) { - return -ENOMEM; - } - - chan = &g_dwc2_hcd.pipe_pool[chidx]; - - /* store variables */ - waitsem = chan->waitsem; - - memset(chan, 0, sizeof(struct dwc2_pipe)); - - chan->chidx = chidx; - chan->ep_addr = ep_cfg->ep_addr; - chan->ep_type = ep_cfg->ep_type; - chan->ep_mps = ep_cfg->ep_mps; - chan->ep_interval = ep_cfg->ep_interval; - chan->speed = ep_cfg->hport->speed; - chan->dev_addr = ep_cfg->hport->dev_addr; - chan->hport = ep_cfg->hport; - - if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { - chan->data_pid = HC_PID_DATA1; - } else { - dwc2_pipe_init(chidx, chan->dev_addr, ep_cfg->ep_addr, ep_cfg->ep_type, ep_cfg->ep_mps, chan->speed); - chan->data_pid = HC_PID_DATA0; - } - - if (chan->speed == USB_SPEED_HIGH) { - chan->ep_interval = (1 << (chan->ep_interval - 1)); - } - - /* restore variables */ - chan->inuse = true; - chan->waitsem = waitsem; - - *pipe = (usbh_pipe_t)chan; - - return 0; -} - -int usbh_pipe_free(usbh_pipe_t pipe) -{ - struct dwc2_pipe *chan; - struct usbh_urb *urb; - - chan = (struct dwc2_pipe *)pipe; - - if (!chan) { - return -EINVAL; - } - - urb = chan->urb; - - if (urb) { - usbh_kill_urb(urb); - } - - dwc2_pipe_free(chan); - return 0; -} - int usbh_submit_urb(struct usbh_urb *urb) { - struct dwc2_pipe *pipe; + struct dwc2_chan *chan; size_t flags; int ret = 0; + int chidx; - if (!urb || !urb->pipe) { + if (!urb || !urb->hport || !urb->ep) { return -EINVAL; } - pipe = urb->pipe; - /* dma addr must be aligned 4 bytes */ if ((((uint32_t)urb->setup) & 0x03) || (((uint32_t)urb->transfer_buffer) & 0x03)) { return -EINVAL; } - if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !pipe->hport->connected) { + if (!(USB_OTG_HPRT & USB_OTG_HPRT_PCSTS) || !urb->hport->connected) { return -ENODEV; } - if (pipe->urb) { + if (urb->errorcode == -EBUSY) { return -EBUSY; } flags = usb_osal_enter_critical_section(); - pipe->waiter = false; - pipe->xfrd = 0; - pipe->urb = urb; - pipe->errorcode = -EBUSY; + chidx = dwc2_chan_alloc(); + if (chidx == -1) { + usb_osal_leave_critical_section(flags); + return -ENOMEM; + } + + chan = &g_dwc2_hcd.chan_pool[chidx]; + chan->chidx = chidx; + chan->urb = urb; + + urb->hcpriv = chan; urb->errorcode = -EBUSY; urb->actual_length = 0; - if (urb->timeout > 0) { - pipe->waiter = true; - } usb_osal_leave_critical_section(flags); - switch (pipe->ep_type) { + switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) { case USB_ENDPOINT_TYPE_CONTROL: - pipe->ep0_state = DWC2_EP0_STATE_SETUP; - dwc2_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + chan->ep0_state = DWC2_EP0_STATE_SETUP; + dwc2_control_urb_init(chidx, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); break; case USB_ENDPOINT_TYPE_BULK: case USB_ENDPOINT_TYPE_INTERRUPT: - dwc2_bulk_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + dwc2_bulk_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length); break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: - pipe->iso_frame_idx = 0; - dwc2_iso_pipe_init(pipe, &urb->iso_packet[pipe->iso_frame_idx]); break; default: break; @@ -819,41 +743,44 @@ int usbh_submit_urb(struct usbh_urb *urb) if (urb->timeout > 0) { /* wait until timeout or sem give */ - ret = usb_osal_sem_take(pipe->waitsem, urb->timeout); + ret = usb_osal_sem_take(chan->waitsem, urb->timeout); if (ret < 0) { goto errout_timeout; } - + urb->timeout = 0; ret = urb->errorcode; } return ret; errout_timeout: - pipe->waiter = false; usbh_kill_urb(urb); return ret; } int usbh_kill_urb(struct usbh_urb *urb) { - struct dwc2_pipe *pipe; + struct dwc2_chan *chan; size_t flags; - pipe = urb->pipe; - - if (!urb || !pipe) { + if (!urb || !urb->hcpriv) { return -EINVAL; } flags = usb_osal_enter_critical_section(); - dwc2_halt(pipe->chidx); - CLEAR_HC_INT(pipe->chidx, USB_OTG_HCINT_CHH); - pipe->urb = NULL; + chan = (struct dwc2_chan *)urb->hcpriv; - if (pipe->waiter) { - pipe->waiter = false; + dwc2_halt(chan->chidx); + CLEAR_HC_INT(chan->chidx, USB_OTG_HCINT_CHH); + + chan->urb = NULL; + urb->hcpriv = NULL; + + dwc2_chan_free(chan); + + if (urb->timeout) { + urb->timeout = 0; urb->errorcode = -ESHUTDOWN; - usb_osal_sem_give(pipe->waitsem); + usb_osal_sem_give(chan->waitsem); } usb_osal_leave_critical_section(flags); @@ -861,16 +788,19 @@ int usbh_kill_urb(struct usbh_urb *urb) return 0; } -static inline void dwc2_pipe_waitup(struct dwc2_pipe *pipe) +static inline void dwc2_urb_waitup(struct usbh_urb *urb) { - struct usbh_urb *urb; + struct dwc2_chan *chan; - urb = pipe->urb; - pipe->urb = NULL; + chan = (struct dwc2_chan *)urb->hcpriv; + chan->urb = NULL; + urb->hcpriv = NULL; - if (pipe->waiter) { - pipe->waiter = false; - usb_osal_sem_give(pipe->waitsem); + dwc2_chan_free(chan); + + if (urb->timeout) { + urb->timeout = 0; + usb_osal_sem_give(chan->waitsem); } if (urb->complete) { @@ -885,214 +815,191 @@ static inline void dwc2_pipe_waitup(struct dwc2_pipe *pipe) static void dwc2_inchan_irq_handler(uint8_t ch_num) { uint32_t chan_intstatus; - struct dwc2_pipe *chan; + struct dwc2_chan *chan; struct usbh_urb *urb; chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK); - chan = &g_dwc2_hcd.pipe_pool[ch_num]; + chan = &g_dwc2_hcd.chan_pool[ch_num]; urb = chan->urb; //printf("s1:%08x\r\n", chan_intstatus); if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { - chan->errorcode = 0; + urb->errorcode = 0; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { - chan->errorcode = -EPERM; + urb->errorcode = -EPERM; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { - chan->errorcode = -EAGAIN; + urb->errorcode = -EAGAIN; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { - chan->errorcode = -EAGAIN; + urb->errorcode = -EAGAIN; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { - chan->errorcode = -EPIPE; + urb->errorcode = -EPIPE; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { USB_MASK_HALT_HC_INT(ch_num); - - if (urb == NULL) { - goto chhout; - } - - urb->errorcode = chan->errorcode; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); if (urb->errorcode == 0) { uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* how many size has received */ uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */ - chan->xfrd += count; + urb->actual_length += count; if ((has_used_packets % 2) == 1) /* toggle in odd numbers */ { - if (chan->data_pid == HC_PID_DATA0) { - chan->data_pid = HC_PID_DATA1; + if (urb->data_toggle == HC_PID_DATA0) { + urb->data_toggle = HC_PID_DATA1; } else { - chan->data_pid = HC_PID_DATA0; + urb->data_toggle = HC_PID_DATA0; } } - if (chan->ep_type == 0x00) { + if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) { if (chan->ep0_state == DWC2_EP0_STATE_INDATA) { chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS; - dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); } else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) { chan->ep0_state = DWC2_EP0_STATE_SETUP; - urb->actual_length = chan->xfrd; - dwc2_pipe_waitup(chan); - } - } else if (chan->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { - urb->iso_packet[chan->iso_frame_idx].actual_length = chan->xfrd; - urb->iso_packet[chan->iso_frame_idx].errorcode = urb->errorcode; - chan->iso_frame_idx++; - - if (chan->iso_frame_idx == urb->num_of_iso_packets) { - dwc2_pipe_waitup(chan); - } else { - dwc2_iso_pipe_init(chan, &urb->iso_packet[chan->iso_frame_idx]); + dwc2_urb_waitup(urb); } + } else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) { } else { - urb->actual_length = chan->xfrd; - dwc2_pipe_waitup(chan); + dwc2_urb_waitup(urb); } } else if (urb->errorcode == -EAGAIN) { /* re-activate the channel */ - if (chan->ep_type == 0x00) { - dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); - } else if ((chan->ep_type == 0x03) || (chan->ep_type == 0x02)) { - dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length); + if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) { + dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + } else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) { + dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length); } else { } } else { - dwc2_pipe_waitup(chan); + dwc2_urb_waitup(urb); } - chhout: - CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); } } static void dwc2_outchan_irq_handler(uint8_t ch_num) { uint32_t chan_intstatus; - struct dwc2_pipe *chan; + struct dwc2_chan *chan; struct usbh_urb *urb; uint16_t buflen; chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK); - chan = &g_dwc2_hcd.pipe_pool[ch_num]; + chan = &g_dwc2_hcd.chan_pool[ch_num]; urb = chan->urb; //printf("s2:%08x\r\n", chan_intstatus); if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { - chan->errorcode = 0; + urb->errorcode = 0; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); dwc2_halt(ch_num); USB_UNMASK_HALT_HC_INT(ch_num); } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { - chan->errorcode = -EPERM; + urb->errorcode = -EPERM; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { - chan->errorcode = -EAGAIN; + urb->errorcode = -EAGAIN; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { - chan->errorcode = -EAGAIN; + urb->errorcode = -EAGAIN; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { - chan->errorcode = -EPIPE; + urb->errorcode = -EPIPE; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { - chan->errorcode = -EIO; + urb->errorcode = -EIO; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { USB_MASK_HALT_HC_INT(ch_num); - - if (urb == NULL) { - goto chhout; - } - - urb->errorcode = chan->errorcode; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); if (urb->errorcode == 0) { uint32_t count = USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ; /* how many size has sent */ uint32_t has_used_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /* how many packets have used */ - chan->xfrd += count; + urb->actual_length += count; if (has_used_packets % 2) /* toggle in odd numbers */ { - if (chan->data_pid == HC_PID_DATA0) { - chan->data_pid = HC_PID_DATA1; + if (urb->data_toggle == HC_PID_DATA0) { + urb->data_toggle = HC_PID_DATA1; } else { - chan->data_pid = HC_PID_DATA0; + urb->data_toggle = HC_PID_DATA0; } } - if (chan->ep_type == 0x00) { + if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) { if (chan->ep0_state == DWC2_EP0_STATE_SETUP) { if (urb->setup->wLength) { if (urb->setup->bmRequestType & 0x80) { @@ -1103,42 +1010,29 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num) } else { chan->ep0_state = DWC2_EP0_STATE_INSTATUS; } - dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); } else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) { chan->ep0_state = DWC2_EP0_STATE_INSTATUS; - dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); } else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) { chan->ep0_state = DWC2_EP0_STATE_SETUP; - urb->actual_length = chan->xfrd; - dwc2_pipe_waitup(chan); - } - } else if (chan->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { - urb->iso_packet[chan->iso_frame_idx].actual_length = chan->xfrd; - urb->iso_packet[chan->iso_frame_idx].errorcode = urb->errorcode; - chan->iso_frame_idx++; - - if (chan->iso_frame_idx == urb->num_of_iso_packets) { - dwc2_pipe_waitup(chan); - } else { - dwc2_iso_pipe_init(chan, &urb->iso_packet[chan->iso_frame_idx]); + dwc2_urb_waitup(urb); } + } else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) { } else { - urb->actual_length = chan->xfrd; - dwc2_pipe_waitup(chan); + dwc2_urb_waitup(urb); } } else if (urb->errorcode == -EAGAIN) { /* re-activate the channel */ - if (chan->ep_type == 0x00) { - dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); - } else if ((chan->ep_type == 0x03) || (chan->ep_type == 0x02)) { - dwc2_bulk_intr_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length); + if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) { + dwc2_control_urb_init(ch_num, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + } else if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) { + dwc2_bulk_intr_urb_init(ch_num, urb, urb->transfer_buffer, urb->transfer_buffer_length); } else { } } else { - dwc2_pipe_waitup(chan); + dwc2_urb_waitup(urb); } - chhout: - CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); } } diff --git a/port/ehci/usb_ehci_priv.h b/port/ehci/usb_ehci_priv.h index ce968401..5348872c 100644 --- a/port/ehci/usb_ehci_priv.h +++ b/port/ehci/usb_ehci_priv.h @@ -33,34 +33,12 @@ extern uint8_t usbh_get_port_speed(const uint8_t port); -struct ehci_qh_hw; -struct ehci_itd_hw; -struct ehci_pipe { - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t ep_type; - uint8_t ep_interval; - uint8_t speed; - uint8_t mult; - uint16_t ep_mps; - bool toggle; - bool inuse; - uint32_t xfrd; - bool waiter; - usb_osal_sem_t waitsem; - struct usbh_hubport *hport; - struct usbh_urb *urb; - uint8_t mf_unmask; - uint8_t mf_valid; - uint8_t iso_packet_idx; - uint8_t remain_itd_num; -}; - struct ehci_qh_hw { struct ehci_qh hw; uint32_t first_qtd; struct usbh_urb *urb; uint8_t remove_in_iaad; + usb_osal_sem_t waitsem; } __attribute__((aligned(32))); struct ehci_qtd_hw { @@ -72,8 +50,10 @@ struct ehci_qtd_hw { struct ehci_itd_hw { struct ehci_itd hw; struct usbh_urb *urb; - struct ehci_pipe *pipe; uint16_t start_frame; + uint8_t mf_unmask; + uint8_t mf_valid; + uint32_t pkt_idx[8]; usb_slist_t list; } __attribute__((aligned(32))); @@ -81,14 +61,13 @@ 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]; }; extern struct ehci_hcd g_ehci_hcd; extern uint32_t g_framelist[]; -int ehci_iso_pipe_init(struct ehci_pipe *pipe, struct usbh_urb *urb); +int ehci_iso_urb_init(struct usbh_urb *urb); void ehci_remove_itd_urb(struct usbh_urb *urb); void ehci_scan_isochronous_list(void); -#endif \ No newline at end of file +#endif diff --git a/port/ehci/usb_hc_ehci.c b/port/ehci/usb_hc_ehci.c index 7e6e9469..a37226c4 100644 --- a/port/ehci/usb_hc_ehci.c +++ b/port/ehci/usb_hc_ehci.c @@ -27,6 +27,7 @@ USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USB_EHCI_FRAME_LIST_SIZE] __ static struct ehci_qh_hw *ehci_qh_alloc(void) { struct ehci_qh_hw *qh; + usb_osal_sem_t waitsem; size_t flags; for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) { @@ -36,10 +37,12 @@ static struct ehci_qh_hw *ehci_qh_alloc(void) usb_osal_leave_critical_section(flags); qh = &ehci_qh_pool[i]; + waitsem = qh->waitsem; memset(qh, 0, sizeof(struct ehci_qh_hw)); qh->hw.hlp = QTD_LIST_END; qh->hw.overlay.next_qtd = QTD_LIST_END; qh->hw.overlay.alt_next_qtd = QTD_LIST_END; + qh->waitsem = waitsem; return qh; } } @@ -100,24 +103,6 @@ static void ehci_qtd_free(struct ehci_qtd_hw *qtd) } } -static struct ehci_pipe *ehci_pipe_alloc(void) -{ - int pipe; - - for (pipe = 0; pipe < CONFIG_USB_EHCI_QH_NUM; pipe++) { - if (!g_ehci_hcd.pipe_pool[pipe].inuse) { - g_ehci_hcd.pipe_pool[pipe].inuse = true; - return &g_ehci_hcd.pipe_pool[pipe]; - } - } - return NULL; -} - -static void ehci_pipe_free(struct ehci_pipe *pipe) -{ - pipe->inuse = false; -} - static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n) { n->hw.hlp = head->hw.hlp; @@ -312,7 +297,7 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl qtd->total_len = buflen; } -static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) +static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { struct ehci_qh_hw *qh = NULL; struct ehci_qtd_hw *qtd_setup = NULL; @@ -344,15 +329,15 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct } ehci_qh_fill(qh, - pipe->dev_addr, - pipe->ep_addr, - pipe->ep_type, - pipe->ep_mps, + urb->hport->dev_addr, + urb->ep->bEndpointAddress, + USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), + USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), 0, - pipe->ep_interval, - pipe->hport->speed, - pipe->hport->parent->hub_addr, - pipe->hport->port); + 0, + urb->hport->speed, + urb->hport->parent->hub_addr, + urb->hport->port); /* fill setup qtd */ token = QTD_TOKEN_STATUS_ACTIVE | @@ -361,7 +346,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct ((uint32_t)8 << QTD_TOKEN_NBYTES_SHIFT); ehci_qtd_fill(qtd_setup, (uintptr_t)setup, 8, token); - qtd_setup->urb = pipe->urb; + qtd_setup->urb = urb; /* fill data qtd */ if (setup->wLength > 0) { @@ -377,7 +362,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct ((uint32_t)buflen << QTD_TOKEN_NBYTES_SHIFT); ehci_qtd_fill(qtd_data, (uintptr_t)buffer, buflen, token); - qtd_data->urb = pipe->urb; + qtd_data->urb = urb; qtd_setup->hw.next_qtd = EHCI_PTR2ADDR(qtd_data); qtd_data->hw.next_qtd = EHCI_PTR2ADDR(qtd_status); } else { @@ -397,7 +382,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct ((uint32_t)0 << QTD_TOKEN_NBYTES_SHIFT); ehci_qtd_fill(qtd_status, 0, 0, token); - qtd_status->urb = pipe->urb; + qtd_status->urb = urb; qtd_status->hw.next_qtd = QTD_LIST_END; /* update qh first qtd */ @@ -409,7 +394,8 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct flags = usb_osal_enter_critical_section(); - qh->urb = pipe->urb; + qh->urb = urb; + urb->hcpriv = qh; /* add qh into async list */ ehci_qh_add_head(&g_async_qh_head, qh); @@ -419,7 +405,7 @@ static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct return qh; } -static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen) +static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen) { struct ehci_qh_hw *qh = NULL; struct ehci_qtd_hw *qtd = NULL; @@ -447,15 +433,15 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b } ehci_qh_fill(qh, - pipe->dev_addr, - pipe->ep_addr, - pipe->ep_type, - pipe->ep_mps, + urb->hport->dev_addr, + urb->ep->bEndpointAddress, + USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), + USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), 0, - pipe->ep_interval, - pipe->hport->speed, - pipe->hport->parent->hub_addr, - pipe->hport->port); + 0, + urb->hport->speed, + urb->hport->parent->hub_addr, + urb->hport->port); while (buflen >= 0) { qtd = ehci_qtd_alloc(); @@ -468,7 +454,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b buflen = 0; } - if (pipe->ep_addr & 0x80) { + if (urb->ep->bEndpointAddress & 0x80) { token = QTD_TOKEN_PID_IN; } else { token = QTD_TOKEN_PID_OUT; @@ -483,7 +469,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b } ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token); - qtd->urb = pipe->urb; + qtd->urb = urb; qtd->hw.next_qtd = QTD_LIST_END; buffer += xfer_len; @@ -504,7 +490,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd); /* update data toggle */ - if (pipe->toggle) { + if (urb->data_toggle) { qh->hw.overlay.token = QTD_TOKEN_TOGGLE; } else { qh->hw.overlay.token = 0; @@ -515,7 +501,8 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b flags = usb_osal_enter_critical_section(); - qh->urb = pipe->urb; + qh->urb = urb; + urb->hcpriv = qh; /* add qh into async list */ ehci_qh_add_head(&g_async_qh_head, qh); @@ -525,7 +512,7 @@ static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *b return qh; } -static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen) +static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen) { struct ehci_qh_hw *qh = NULL; struct ehci_qtd_hw *qtd = NULL; @@ -553,15 +540,15 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b } ehci_qh_fill(qh, - pipe->dev_addr, - pipe->ep_addr, - pipe->ep_type, - pipe->ep_mps, - pipe->mult + 1, - pipe->ep_interval, - pipe->hport->speed, - pipe->hport->parent->hub_addr, - pipe->hport->port); + urb->hport->dev_addr, + urb->ep->bEndpointAddress, + USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), + USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), + USB_GET_MULT(urb->ep->wMaxPacketSize) + 1, + urb->ep->bInterval, + urb->hport->speed, + urb->hport->parent->hub_addr, + urb->hport->port); while (buflen >= 0) { qtd = ehci_qtd_alloc(); @@ -574,7 +561,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b buflen = 0; } - if (pipe->ep_addr & 0x80) { + if (urb->ep->bEndpointAddress & 0x80) { token = QTD_TOKEN_PID_IN; } else { token = QTD_TOKEN_PID_OUT; @@ -589,7 +576,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b } ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token); - qtd->urb = pipe->urb; + qtd->urb = urb; qtd->hw.next_qtd = QTD_LIST_END; buffer += xfer_len; @@ -610,7 +597,7 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd); /* update data toggle */ - if (pipe->toggle) { + if (urb->data_toggle) { qh->hw.overlay.token = QTD_TOKEN_TOGGLE; } else { qh->hw.overlay.token = 0; @@ -621,12 +608,13 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b flags = usb_osal_enter_critical_section(); - qh->urb = pipe->urb; + qh->urb = urb; + urb->hcpriv = qh; /* add qh into periodic list */ - if (pipe->speed == USB_SPEED_HIGH) { - ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval), qh); + if (urb->hport->speed == USB_SPEED_HIGH) { + ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval), qh); } else { - ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh); + ehci_qh_add_head(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh); } EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN; @@ -635,16 +623,20 @@ static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *b return qh; } -void ehci_pipe_waitup(struct ehci_pipe *pipe) +static void ehci_urb_waitup(struct usbh_urb *urb) { - struct usbh_urb *urb; + struct ehci_qh_hw *qh; - urb = pipe->urb; - pipe->urb = NULL; + qh = (struct ehci_qh_hw *)urb->hcpriv; + qh->urb = NULL; + urb->hcpriv = NULL; - if (pipe->waiter) { - pipe->waiter = false; - usb_osal_sem_give(pipe->waitsem); + qh->remove_in_iaad = 0; + ehci_qh_free(qh); + + if (urb->timeout) { + urb->timeout = 0; + usb_osal_sem_give(qh->waitsem); } if (urb->complete) { @@ -676,7 +668,6 @@ static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh) static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh) { struct usbh_urb *urb; - struct ehci_pipe *pipe; struct ehci_qtd_hw *qtd; uint32_t token; @@ -688,31 +679,30 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh) } urb = qh->urb; - pipe = urb->pipe; if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) { - qtd = EHCI_ADDR2QTD(qh->first_qtd); + qtd = EHCI_ADDR2QTD(qh->first_qtd); - while (qtd) { - if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) { - return; - } - qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd); - } + while (qtd) { + if ((qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) == QTD_TOKEN_STATUS_ACTIVE) { + return; + } + qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd); + } if (token & QTD_TOKEN_TOGGLE) { - pipe->toggle = true; + urb->data_toggle = true; } else { - pipe->toggle = false; + urb->data_toggle = false; } urb->errorcode = 0; } else { if (token & QTD_TOKEN_STATUS_BABBLE) { urb->errorcode = -EPERM; - pipe->toggle = 0; + urb->data_toggle = 0; } else if (token & QTD_TOKEN_STATUS_HALTED) { urb->errorcode = -EPERM; - pipe->toggle = 0; + urb->data_toggle = 0; } else if (token & (QTD_TOKEN_STATUS_DBERR | QTD_TOKEN_STATUS_XACTERR)) { urb->errorcode = -EIO; } @@ -720,10 +710,8 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh) ehci_qh_scan_qtds(qhead, qh); - if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) { - qh->remove_in_iaad = 0; - ehci_qh_free(qh); - ehci_pipe_waitup(pipe); + if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { + ehci_urb_waitup(urb); } else { qh->remove_in_iaad = 1; @@ -806,10 +794,8 @@ int usb_hc_init(void) } for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) { - struct ehci_pipe *pipe; - - pipe = &g_ehci_hcd.pipe_pool[index]; - pipe->waitsem = usb_osal_sem_create(0); + qh = &ehci_qh_pool[index]; + qh->waitsem = usb_osal_sem_create(0); } memset(&g_async_qh_head, 0, sizeof(struct ehci_qh_hw)); @@ -1068,144 +1054,57 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) return 0; } -int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult) -{ - struct ehci_pipe *ppipe = (struct ehci_pipe *)pipe; - - ppipe->dev_addr = dev_addr; - ppipe->ep_mps = ep_mps; - ppipe->mult = mult; - - return 0; -} - -int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) -{ - struct ehci_pipe *ppipe; - usb_osal_sem_t waitsem; - - ppipe = ehci_pipe_alloc(); - if (ppipe == NULL) { - return -ENOMEM; - } - - /* store variables */ - waitsem = ppipe->waitsem; - - memset(ppipe, 0, sizeof(struct ehci_pipe)); - - ppipe->ep_addr = ep_cfg->ep_addr; - ppipe->ep_type = ep_cfg->ep_type; - ppipe->ep_mps = ep_cfg->ep_mps; - ppipe->ep_interval = ep_cfg->ep_interval; - ppipe->mult = ep_cfg->mult; - ppipe->speed = ep_cfg->hport->speed; - ppipe->dev_addr = ep_cfg->hport->dev_addr; - ppipe->hport = ep_cfg->hport; - -#ifdef CONFIG_USB_EHCI_ISO - if ((ppipe->speed == USB_SPEED_HIGH) && (ppipe->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS)) { - if (ep_cfg->ep_interval == 0x01) { /* transfer interval 1 mf */ - ppipe->mf_unmask = 0xff; - ppipe->mf_valid = 8; - } else if (ep_cfg->ep_interval == 0x02) { /* transfer interval 2 mf */ - ppipe->mf_unmask = 0x55; - ppipe->mf_valid = 4; - } else if (ep_cfg->ep_interval == 0x03) { /* transfer interval 4 mf */ - ppipe->mf_unmask = 0x44; - ppipe->mf_valid = 2; - } else if (ep_cfg->ep_interval == 0x04) { /* transfer interval 8 mf */ - ppipe->mf_unmask = 0x01; - ppipe->mf_valid = 1; - } - } -#endif - /* restore variable */ - ppipe->inuse = true; - ppipe->waitsem = waitsem; - - *pipe = (usbh_pipe_t)ppipe; - - return 0; -} - -int usbh_pipe_free(usbh_pipe_t pipe) -{ - struct usbh_urb *urb; - struct ehci_pipe *ppipe; - - ppipe = (struct ehci_pipe *)pipe; - - if (!ppipe) { - return -EINVAL; - } - - urb = ppipe->urb; - - if (urb) { - usbh_kill_urb(urb); - } - - ehci_pipe_free(ppipe); - return 0; -} - int usbh_submit_urb(struct usbh_urb *urb) { - struct ehci_pipe *pipe; struct ehci_qh_hw *qh = NULL; size_t flags; int ret = 0; - if (!urb || !urb->pipe) { + if (!urb || !urb->hport || !urb->ep) { return -EINVAL; } - pipe = urb->pipe; - - if (!pipe->inuse /*|| !(EHCI_HCOR->portsc[pipe->hport->port-1] & EHCI_PORTSC_CCS)*/ || !pipe->hport->connected) { + if (!urb->hport->connected) { return -ENODEV; } - if (pipe->urb && (pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) { + if ((urb->errorcode == -EBUSY) && (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS)) { return -EBUSY; } flags = usb_osal_enter_critical_section(); - pipe->waiter = false; - pipe->xfrd = 0; - pipe->urb = urb; + urb->hcpriv = NULL; urb->errorcode = -EBUSY; urb->actual_length = 0; - if (urb->timeout > 0) { - pipe->waiter = true; - } usb_osal_leave_critical_section(flags); - switch (pipe->ep_type) { + switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) { case USB_ENDPOINT_TYPE_CONTROL: - qh = ehci_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + qh = ehci_control_urb_init(urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); if (qh == NULL) { return -ENOMEM; } + urb->hcpriv = qh; break; case USB_ENDPOINT_TYPE_BULK: - qh = ehci_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + qh = ehci_bulk_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length); if (qh == NULL) { return -ENOMEM; } + urb->hcpriv = qh; break; case USB_ENDPOINT_TYPE_INTERRUPT: - qh = ehci_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + qh = ehci_intr_urb_init(urb, urb->transfer_buffer, urb->transfer_buffer_length); if (qh == NULL) { return -ENOMEM; } + urb->hcpriv = qh; break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: #ifdef CONFIG_USB_EHCI_ISO - ehci_iso_pipe_init(pipe, urb); + ret = ehci_iso_urb_init(urb); #endif break; default: @@ -1214,34 +1113,26 @@ int usbh_submit_urb(struct usbh_urb *urb) if (urb->timeout > 0) { /* wait until timeout or sem give */ - ret = usb_osal_sem_take(pipe->waitsem, urb->timeout); + ret = usb_osal_sem_take(qh->waitsem, urb->timeout); if (ret < 0) { goto errout_timeout; } + urb->timeout = 0; ret = urb->errorcode; } return ret; errout_timeout: /* Timeout will run here */ - pipe->waiter = false; usbh_kill_urb(urb); return ret; } int usbh_kill_urb(struct usbh_urb *urb) { - struct ehci_pipe *pipe; - struct ehci_qh_hw *qh = NULL; - + struct ehci_qh_hw *qh; size_t flags; - if (!urb) { - return -EINVAL; - } - - pipe = urb->pipe; - - if (!pipe) { + if (!urb || !urb->hcpriv) { return -EINVAL; } @@ -1249,7 +1140,7 @@ int usbh_kill_urb(struct usbh_urb *urb) EHCI_HCOR->usbcmd &= ~(EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN); - if ((pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) || (pipe->ep_type == USB_ENDPOINT_TYPE_BULK)) { + if ((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_CONTROL) || (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_BULK)) { qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp); while ((qh != &g_async_qh_head) && qh) { if (qh->urb == urb) { @@ -1257,14 +1148,14 @@ int usbh_kill_urb(struct usbh_urb *urb) } qh = EHCI_ADDR2QH(qh->hw.hlp); } - } else if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) { + } else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp); while (qh) { if (qh->urb == urb) { - if (pipe->speed == USB_SPEED_HIGH) { - ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh); + if (urb->hport->speed == USB_SPEED_HIGH) { + ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval), qh); } else { - ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh); + ehci_kill_qh(ehci_get_periodic_qhead(urb->ep->bInterval * 8), qh); } } qh = EHCI_ADDR2QH(qh->hw.hlp); @@ -1277,12 +1168,14 @@ int usbh_kill_urb(struct usbh_urb *urb) EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN); - pipe->urb = NULL; + qh = (struct ehci_qh_hw *)urb->hcpriv; + urb->hcpriv = NULL; + qh->urb = NULL; - if (pipe->waiter) { - pipe->waiter = false; + if (urb->timeout) { + urb->timeout = 0; urb->errorcode = -ESHUTDOWN; - usb_osal_sem_give(pipe->waitsem); + usb_osal_sem_give(qh->waitsem); } usb_osal_leave_critical_section(flags); @@ -1306,16 +1199,14 @@ static void ehci_scan_async_list(void) static void ehci_scan_periodic_list(void) { struct ehci_qh_hw *qh; - struct ehci_pipe *pipe; qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp); while (qh) { - if (qh->urb && qh->urb->pipe) { - pipe = (struct ehci_pipe *)qh->urb->pipe; - if (pipe->speed == USB_SPEED_HIGH) { - ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh); + if (qh->urb) { + if (qh->urb->hport->speed == USB_SPEED_HIGH) { + ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval), qh); } else { - ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh); + ehci_check_qh(ehci_get_periodic_qhead(qh->urb->ep->bInterval * 8), qh); } } qh = EHCI_ADDR2QH(qh->hw.hlp); @@ -1372,16 +1263,7 @@ void USBH_IRQHandler(void) for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) { struct ehci_qh_hw *qh = &ehci_qh_pool[index]; if (g_ehci_hcd.ehci_qh_used[index] && qh->remove_in_iaad) { - struct usbh_urb *urb; - struct ehci_pipe *pipe; - - urb = qh->urb; - pipe = urb->pipe; - - qh->remove_in_iaad = 0; - ehci_qh_free(qh); - - ehci_pipe_waitup(pipe); + ehci_urb_waitup(qh->urb); } } } diff --git a/port/musb/usb_hc_musb.c b/port/musb/usb_hc_musb.c index d5cd7da4..f19f3264 100644 --- a/port/musb/usb_hc_musb.c +++ b/port/musb/usb_hc_musb.c @@ -151,17 +151,10 @@ typedef enum { } ep0_state_t; struct musb_pipe { - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t ep_type; - uint8_t ep_interval; - uint8_t speed; - uint16_t ep_mps; + uint8_t chidx; bool inuse; uint32_t xfrd; - volatile bool waiter; usb_osal_sem_t waitsem; - struct usbh_hubport *hport; struct usbh_urb *urb; }; @@ -169,7 +162,7 @@ struct musb_hcd { volatile bool port_csc; volatile bool port_pec; volatile bool port_pe; - struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM][2]; /* Support Bidirectional ep */ + struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM]; } g_musb_hcd; static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP; @@ -265,88 +258,115 @@ static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len) } } -void musb_control_pipe_init(struct musb_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) +void musb_control_urb_init(uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { uint8_t old_ep_index; + uint8_t speed; old_ep_index = musb_get_active_ep(); - musb_set_active_ep(0); + musb_set_active_ep(chidx); - HWREGB(USB_TXADDR_BASE(0)) = pipe->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = pipe->speed; - HWREGB(USB_TXHUBADDR_BASE(0)) = 0; - HWREGB(USB_TXHUBPORT_BASE(0)) = 0; + if (urb->hport->speed == USB_SPEED_HIGH) { + speed = USB_TYPE0_SPEED_HIGH; + } else if (urb->hport->speed == USB_SPEED_FULL) { + speed = USB_TYPE0_SPEED_FULL; + } else if (urb->hport->speed == USB_SPEED_LOW) { + speed = USB_TYPE0_SPEED_LOW; + } - musb_write_packet(0, (uint8_t *)setup, 8); + HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = speed; + HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0; + HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0; + + musb_write_packet(chidx, (uint8_t *)setup, 8); HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; musb_set_active_ep(old_ep_index); } -void musb_bulk_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen) +void musb_bulk_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen) { - uint8_t ep_idx; uint8_t old_ep_index; + uint8_t speed; - ep_idx = pipe->ep_addr & 0x7f; old_ep_index = musb_get_active_ep(); - musb_set_active_ep(ep_idx); + musb_set_active_ep(chidx); - if (pipe->ep_addr & 0x80) { - HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK; + if (urb->hport->speed == USB_SPEED_HIGH) { + speed = USB_TXTYPE1_SPEED_HIGH; + } else if (urb->hport->speed == USB_SPEED_FULL) { + speed = USB_TXTYPE1_SPEED_FULL; + } else if (urb->hport->speed == USB_SPEED_LOW) { + speed = USB_TXTYPE1_SPEED_LOW; + } + + if (urb->ep->bEndpointAddress & 0x80) { + HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr; + HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chidx | speed | USB_TXTYPE1_PROTO_BULK; HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = 0; - HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0; + HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0; + HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0; HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - } else { - HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0; - HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0; - if (buflen > pipe->ep_mps) { - buflen = pipe->ep_mps; + HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << chidx); + } else { + HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chidx | speed | USB_TXTYPE1_PROTO_BULK; + HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0; + HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0; + HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0; + + if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } - musb_write_packet(ep_idx, buffer, buflen); + musb_write_packet(chidx, buffer, buflen); HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; + + HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx); } musb_set_active_ep(old_ep_index); } -void musb_intr_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen) +void musb_intr_urb_init(uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen) { - uint8_t ep_idx; uint8_t old_ep_index; + uint8_t speed; - ep_idx = pipe->ep_addr & 0x7f; old_ep_index = musb_get_active_ep(); - musb_set_active_ep(ep_idx); + musb_set_active_ep(chidx); - if (pipe->ep_addr & 0x80) { - HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = pipe->ep_interval; - HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0; + if (urb->hport->speed == USB_SPEED_HIGH) { + speed = USB_TXTYPE1_SPEED_HIGH; + } else if (urb->hport->speed == USB_SPEED_FULL) { + speed = USB_TXTYPE1_SPEED_FULL; + } else if (urb->hport->speed == USB_SPEED_LOW) { + speed = USB_TXTYPE1_SPEED_LOW; + } + + if (urb->ep->bEndpointAddress & 0x80) { + HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr; + HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chidx | speed | USB_TXTYPE1_PROTO_INT; + HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = urb->ep->bInterval; + HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0; + HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0; HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; } else { - HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = pipe->ep_interval; - HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0; + HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chidx | speed | USB_TXTYPE1_PROTO_INT; + HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = urb->ep->bInterval; + HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0; + HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0; - if (buflen > pipe->ep_mps) { - buflen = pipe->ep_mps; + if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } - musb_write_packet(ep_idx, buffer, buflen); + musb_write_packet(chidx, buffer, buflen); HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; @@ -379,6 +399,25 @@ static uint8_t usbh_get_port_speed(const uint8_t port) return speed; } +static int musb_pipe_alloc(void) +{ + int chidx; + + for (chidx = 1; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + if (!g_musb_hcd.pipe_pool[chidx].inuse) { + g_musb_hcd.pipe_pool[chidx].inuse = true; + return chidx; + } + } + + return -1; +} + +static void musb_pipe_free(struct musb_pipe *pipe) +{ + pipe->inuse = false; +} + __WEAK void usb_hc_low_level_init(void) { } @@ -391,8 +430,7 @@ int usb_hc_init(void) memset(&g_musb_hcd, 0, sizeof(struct musb_hcd)); for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) { - g_musb_hcd.pipe_pool[i][0].waitsem = usb_osal_sem_create(0); - g_musb_hcd.pipe_pool[i][1].waitsem = usb_osal_sem_create(0); + g_musb_hcd.pipe_pool[i].waitsem = usb_osal_sem_create(0); } usb_hc_low_level_init(); @@ -551,150 +589,53 @@ int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) return 0; } -int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult) -{ - struct musb_pipe *ppipe = (struct musb_pipe *)pipe; - - ppipe->dev_addr = dev_addr; - ppipe->ep_mps = ep_mps; - - return 0; -} - -int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) -{ - struct musb_pipe *ppipe; - uint8_t old_ep_index; - uint8_t ep_idx; - usb_osal_sem_t waitsem; - - ep_idx = ep_cfg->ep_addr & 0x7f; - - if (ep_idx > CONIFG_USB_MUSB_PIPE_NUM) { - return -ENOMEM; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(ep_idx); - - if (ep_cfg->ep_addr & 0x80) { - ppipe = &g_musb_hcd.pipe_pool[ep_idx][1]; - } else { - ppipe = &g_musb_hcd.pipe_pool[ep_idx][0]; - } - - /* store variables */ - waitsem = ppipe->waitsem; - - memset(ppipe, 0, sizeof(struct musb_pipe)); - - ppipe->ep_addr = ep_cfg->ep_addr; - ppipe->ep_type = ep_cfg->ep_type; - ppipe->ep_mps = ep_cfg->ep_mps; - ppipe->ep_interval = ep_cfg->ep_interval; - ppipe->speed = ep_cfg->hport->speed; - ppipe->dev_addr = ep_cfg->hport->dev_addr; - ppipe->hport = ep_cfg->hport; - - if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { - if (ppipe->speed == USB_SPEED_HIGH) { - ppipe->speed = USB_TYPE0_SPEED_HIGH; - } else if (ppipe->speed == USB_SPEED_FULL) { - ppipe->speed = USB_TYPE0_SPEED_FULL; - } else if (ppipe->speed == USB_SPEED_LOW) { - ppipe->speed = USB_TYPE0_SPEED_LOW; - } - } else { - if (ppipe->speed == USB_SPEED_HIGH) { - ppipe->speed = USB_TXTYPE1_SPEED_HIGH; - } else if (ppipe->speed == USB_SPEED_FULL) { - ppipe->speed = USB_TXTYPE1_SPEED_FULL; - } else if (ppipe->speed == USB_SPEED_LOW) { - ppipe->speed = USB_TXTYPE1_SPEED_LOW; - } - - if (ppipe->ep_addr & 0x80) { - HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << ep_idx); - } else { - HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx); - } - } - /* restore variable */ - ppipe->inuse = true; - ppipe->waitsem = waitsem; - - musb_set_active_ep(old_ep_index); - *pipe = (usbh_pipe_t)ppipe; - return 0; -} - -int usbh_pipe_free(usbh_pipe_t pipe) -{ - struct musb_pipe *ppipe; - struct usbh_urb *urb; - - ppipe = (struct musb_pipe *)pipe; - - if (!ppipe) { - return -EINVAL; - } - - urb = ppipe->urb; - - if (urb) { - usbh_kill_urb(urb); - } - - return 0; -} - int usbh_submit_urb(struct usbh_urb *urb) { struct musb_pipe *pipe; + int chidx; size_t flags; int ret = 0; - if (!urb) { + if (!urb || !urb->hport || !urb->ep) { return -EINVAL; } - pipe = urb->pipe; - - if (!pipe) { - return -EINVAL; - } - - if (!pipe->hport->connected) { + if (!urb->hport->connected) { return -ENODEV; } - if (pipe->urb) { + if (urb->errorcode == -EBUSY) { return -EBUSY; } flags = usb_osal_enter_critical_section(); - pipe->waiter = false; - pipe->xfrd = 0; + chidx = musb_pipe_alloc(); + if (chidx == -1) { + usb_osal_leave_critical_section(flags); + return -ENOMEM; + } + + pipe = &g_musb_hcd.pipe_pool[chidx]; + pipe->chidx = chidx; pipe->urb = urb; + + urb->hcpriv = pipe; urb->errorcode = -EBUSY; urb->actual_length = 0; - if (urb->timeout > 0) { - pipe->waiter = true; - } usb_osal_leave_critical_section(flags); - switch (pipe->ep_type) { + switch (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes)) { case USB_ENDPOINT_TYPE_CONTROL: usb_ep0_state = USB_EP0_STATE_SETUP; - musb_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + musb_control_urb_init(0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); break; case USB_ENDPOINT_TYPE_BULK: - musb_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + musb_bulk_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length); break; case USB_ENDPOINT_TYPE_INTERRUPT: - musb_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + musb_intr_urb_init(chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length); break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: break; @@ -707,12 +648,11 @@ int usbh_submit_urb(struct usbh_urb *urb) if (ret < 0) { goto errout_timeout; } - + urb->timeout = 0; ret = urb->errorcode; } return ret; errout_timeout: - pipe->waiter = false; usbh_kill_urb(urb); return ret; } @@ -720,31 +660,42 @@ errout_timeout: int usbh_kill_urb(struct usbh_urb *urb) { struct musb_pipe *pipe; + size_t flags; - pipe = urb->pipe; - - if (!urb || !pipe) { + if (!urb || !urb->hcpriv) { return -EINVAL; } - if (pipe->waiter) { - pipe->waiter = false; + flags = usb_osal_enter_critical_section(); + + pipe = (struct musb_pipe *)urb->hcpriv; + urb->hcpriv = NULL; + pipe->urb = NULL; + + musb_pipe_free(pipe); + + if (urb->timeout) { + urb->timeout = 0; urb->errorcode = -ESHUTDOWN; usb_osal_sem_give(pipe->waitsem); } + usb_osal_leave_critical_section(flags); return 0; } -static inline void musb_pipe_waitup(struct musb_pipe *pipe) +static void musb_urb_waitup(struct usbh_urb *urb) { - struct usbh_urb *urb; + struct musb_pipe *pipe; - urb = pipe->urb; + pipe = (struct musb_pipe *)urb->hcpriv; pipe->urb = NULL; + urb->hcpriv = NULL; - if (pipe->waiter) { - pipe->waiter = false; + musb_pipe_free(pipe); + + if (urb->timeout) { + urb->timeout = 0; usb_osal_sem_give(pipe->waitsem); } @@ -764,7 +715,7 @@ void handle_ep0(void) struct usbh_urb *urb; uint32_t size; - pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0][0]; + pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0]; urb = pipe->urb; if (urb == NULL) { return; @@ -776,7 +727,7 @@ void handle_ep0(void) HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALLED; usb_ep0_state = USB_EP0_STATE_SETUP; urb->errorcode = -EPERM; - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); return; } if (ep0_status & USB_CSRL0_ERROR) { @@ -784,14 +735,14 @@ void handle_ep0(void) musb_fifo_flush(0); usb_ep0_state = USB_EP0_STATE_SETUP; urb->errorcode = -EIO; - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); return; } if (ep0_status & USB_CSRL0_STALL) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL; usb_ep0_state = USB_EP0_STATE_SETUP; urb->errorcode = -EPERM; - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); return; } @@ -805,8 +756,8 @@ void handle_ep0(void) } else { usb_ep0_state = USB_EP0_STATE_OUT_DATA; size = urb->transfer_buffer_length; - if (size > pipe->ep_mps) { - size = pipe->ep_mps; + if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } musb_write_packet(0, urb->transfer_buffer, size); @@ -824,8 +775,8 @@ void handle_ep0(void) case USB_EP0_STATE_IN_DATA: if (ep0_status & USB_CSRL0_RXRDY) { size = urb->transfer_buffer_length; - if (size > pipe->ep_mps) { - size = pipe->ep_mps; + if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET)); @@ -835,7 +786,7 @@ void handle_ep0(void) urb->transfer_buffer_length -= size; urb->actual_length += size; - if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) { + if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) { usb_ep0_state = USB_EP0_STATE_OUT_STATUS; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_TXRDY | USB_CSRL0_STATUS); } else { @@ -846,8 +797,8 @@ void handle_ep0(void) case USB_EP0_STATE_OUT_DATA: if (urb->transfer_buffer_length > 0) { size = urb->transfer_buffer_length; - if (size > pipe->ep_mps) { - size = pipe->ep_mps; + if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } musb_write_packet(0, urb->transfer_buffer, size); @@ -863,13 +814,13 @@ void handle_ep0(void) break; case USB_EP0_STATE_OUT_STATUS: urb->errorcode = 0; - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); break; case USB_EP0_STATE_IN_STATUS: if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~(USB_CSRL0_RXRDY | USB_CSRL0_STATUS); urb->errorcode = 0; - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); } break; } @@ -939,7 +890,7 @@ void USBH_IRQHandler(void) if (txis & (1 << ep_idx)) { HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx); - pipe = &g_musb_hcd.pipe_pool[ep_idx][0]; + pipe = &g_musb_hcd.pipe_pool[ep_idx]; urb = pipe->urb; musb_set_active_ep(ep_idx); @@ -960,8 +911,8 @@ void USBH_IRQHandler(void) } else { uint32_t size = urb->transfer_buffer_length; - if (size > pipe->ep_mps) { - size = pipe->ep_mps; + if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } urb->transfer_buffer += size; @@ -984,7 +935,7 @@ void USBH_IRQHandler(void) if (rxis & (1 << ep_idx)) { HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx); // clear isr flag - pipe = &g_musb_hcd.pipe_pool[ep_idx][1]; + pipe = &g_musb_hcd.pipe_pool[ep_idx]; urb = pipe->urb; musb_set_active_ep(ep_idx); @@ -1005,8 +956,8 @@ void USBH_IRQHandler(void) goto pipe_wait; } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) { uint32_t size = urb->transfer_buffer_length; - if (size > pipe->ep_mps) { - size = pipe->ep_mps; + if (size > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) { + size = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize); } size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET)); @@ -1018,7 +969,7 @@ void USBH_IRQHandler(void) urb->transfer_buffer_length -= size; urb->actual_length += size; - if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) { + if ((size < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) || (urb->transfer_buffer_length == 0)) { urb->errorcode = 0; goto pipe_wait; } else { @@ -1030,6 +981,11 @@ void USBH_IRQHandler(void) musb_set_active_ep(old_ep_idx); return; pipe_wait: + if (urb->ep->bEndpointAddress & 0x80) { + HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << pipe->chidx); + } else { + HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << pipe->chidx); + } musb_set_active_ep(old_ep_idx); - musb_pipe_waitup(pipe); + musb_urb_waitup(urb); } \ No newline at end of file