mirror of
https://github.com/sakumisu/CherryUSB.git
synced 2025-05-09 00:21:44 +08:00
refactor urb, add ep & hport in urb to make hardware pipe more reusable
This commit is contained in:
parent
c1435548e7
commit
5bbe2a97f2
@ -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') {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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') {
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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') {
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
127
core/usbh_core.c
127
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;
|
||||
|
138
core/usbh_core.h
138
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.
|
||||
|
138
demo/usb_host.c
138
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
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
#endif
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user