refactor urb, add ep & hport in urb to make hardware pipe more reusable

This commit is contained in:
sakumisu
2023-11-15 22:08:26 +08:00
parent c1435548e7
commit 5bbe2a97f2
26 changed files with 1072 additions and 1172 deletions

View File

@@ -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') {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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') {

View File

@@ -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

View File

@@ -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];

View File

@@ -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)
{
}

View File

@@ -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 {

View File

@@ -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') {

View File

@@ -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;

View File

@@ -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];

View File

@@ -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)
{
}

View File

@@ -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