diff --git a/firmware/drivers/isp1583.c b/firmware/drivers/isp1583.c index e60339d9fc..6300ccc6b2 100644 --- a/firmware/drivers/isp1583.c +++ b/firmware/drivers/isp1583.c @@ -29,6 +29,9 @@ #include "logf.h" #include "stdio.h" +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; /* filled in usb_drv_init */ +uint8_t usb_drv_ep_specs_flags = 0; + struct usb_endpoint { unsigned char *out_buf; @@ -48,7 +51,6 @@ struct usb_endpoint unsigned char enabled[2]; short max_pkt_size[2]; short type; - char allocation; }; static unsigned char setup_pkt_buf[8]; @@ -470,6 +472,14 @@ void usb_drv_init(void) //tick_add_task(usb_helper); + /* Fill endpoint spec table FIXME: should be done in usb_drv_startup() */ + usb_drv_ep_specs[0].type[DIR_OUT] = USB_ENDPOINT_XFER_CONTROL; + usb_drv_ep_specs[0].type[DIR_IN] = USB_ENDPOINT_XFER_CONTROL; + for(int i = 1; i < USB_NUM_ENDPOINTS; i += 1) { + usb_drv_ep_specs[i].type[DIR_OUT] = USB_ENDPOINT_XFER_BULK; + usb_drv_ep_specs[i].type[DIR_IN] = USB_ENDPOINT_XFER_BULK; + } + logf("usb_init_device() finished"); } @@ -616,29 +626,15 @@ void usb_drv_cancel_all_transfers(void) endpoints[i].halt[0] = endpoints[i].halt[1] = 1; } -int usb_drv_request_endpoint(int type, int dir) +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { - int i, bit; - - if (type != USB_ENDPOINT_XFER_BULK) - return -1; - - bit=(dir & USB_DIR_IN)? 2:1; - - for (i=1; i < USB_NUM_ENDPOINTS; i++) { - if((endpoints[i].allocation & bit)!=0) - continue; - endpoints[i].allocation |= bit; - return i | dir; - } - - return -1; + (void)max_packet_size; /* FIXME: support max packet size override */ + return 0; } -void usb_drv_release_endpoint(int ep) +int usb_drv_deinit_endpoint(int endpoint) { - int mask = (ep & USB_DIR_IN)? ~2:~1; - endpoints[ep & 0x7f].allocation &= mask; + return 0; } static void bus_reset(void) diff --git a/firmware/drivers/m66591.c b/firmware/drivers/m66591.c index 822585d882..3c82fb5d21 100644 --- a/firmware/drivers/m66591.c +++ b/firmware/drivers/m66591.c @@ -59,6 +59,9 @@ * stack visible functions. ******************************************************************************/ +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; /* filled in usb_drv_init */ +uint8_t usb_drv_ep_specs_flags = USB_ENDPOINT_SPEC_IO_EXCLUSIVE; + static volatile unsigned short * pipe_ctrl_addr(int pipe); static void pipe_handshake(int pipe, int handshake); static void pipe_c_select (int pipe, bool dir); @@ -78,7 +81,6 @@ struct M66591_epstat { int length; /* how match data will fit */ volatile int count; /* actual data count */ bool waiting; /* is there data to transfer? */ - bool busy; /* has the pipe been requested for use? */ } ; static struct M66591_epstat M66591_eps[USB_NUM_ENDPOINTS]; @@ -638,82 +640,63 @@ void usb_drv_set_test_mode(int mode) { M66591_TESTMODE |= mode; } -/* Request an unused endpoint */ -int usb_drv_request_endpoint(int type, int dir) { - int ep; - int pipecfg = 0; +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ - if (type == USB_ENDPOINT_XFER_BULK) { + int pipecfg; + + if(type == USB_ENDPOINT_XFER_BULK) { /* Enable double buffer mode (only used for ep 1 and 2) */ pipecfg |= 1<<9 | 1<<8; - - /* Bulk endpoints must be between 1 and 4 inclusive */ - ep=1; - - while(M66591_eps[ep].busy && ep++<5); - - /* If this reached 5 the endpoints were all busy */ - if(ep==5) { - logf("mxx: ep %d busy", ep); - return -1; - } - } else if (type == USB_ENDPOINT_XFER_INT) { - ep=5; - + } else if(type == USB_ENDPOINT_XFER_BULK) { pipecfg |= 1<<13; - - while(M66591_eps[ep].busy && ++ep USB_NUM_ENDPOINTS || M66591_eps[ep].busy == false) - return ; + if (num < 1 || num > USB_NUM_ENDPOINTS) { + return -1; + } - flags = disable_irq_save(); + int flags = disable_irq_save(); - logf("mxx: ep %d release", ep); + logf("mxx: ep %d release", num); - M66591_eps[ep].busy = false; - M66591_eps[ep].dir = -1; + M66591_eps[num].dir = -1; restore_irq(flags); + + return 0; } /* Periodically called to check if a cable was plugged into the device */ @@ -744,6 +727,18 @@ void usb_drv_init(void) { M66591_TRN_CTRL |=0x0001; M66591_INTCFG_MAIN |=0x8000; /* Enable VBUS interrupt */ + + /* Fill endpoint spec table FIXME: should be done in usb_drv_startup() */ + usb_drv_ep_specs[0].type[DIR_OUT] = USB_ENDPOINT_XFER_CONTROL; + usb_drv_ep_specs[0].type[DIR_IN] = USB_ENDPOINT_XFER_CONTROL; + for(int i = 1; i < 5; i += 1) { + usb_drv_ep_specs[i].type[DIR_OUT] = USB_ENDPOINT_XFER_BULK; + usb_drv_ep_specs[i].type[DIR_IN] = USB_ENDPOINT_XFER_BULK; + } + for(int i = 5; i < USB_NUM_ENDPOINTS; i += 1) { + usb_drv_ep_specs[i].type[DIR_OUT] = USB_ENDPOINT_XFER_INT; + usb_drv_ep_specs[i].type[DIR_IN] = USB_ENDPOINT_XFER_INT; + } } /* fully enable driver */ @@ -757,7 +752,6 @@ void usb_attach(void) { M66591_eps[i].length = 0; M66591_eps[i].count = 0; M66591_eps[i].waiting = false; - M66591_eps[i].busy = false; } /* Issue a h/w reset */ diff --git a/firmware/drivers/usb-designware.c b/firmware/drivers/usb-designware.c index 00be10a3fe..8a797eaf73 100644 --- a/firmware/drivers/usb-designware.c +++ b/firmware/drivers/usb-designware.c @@ -144,6 +144,9 @@ struct usb_dw_ep0 struct usb_ctrlrequest pending_req; }; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; /* filled in usb_drv_init */ +uint8_t usb_drv_ep_specs_flags = 0; + static const char* const dw_dir_str[USB_DW_NUM_DIRS] = { [USB_DW_EPDIR_IN] = "IN", @@ -1495,6 +1498,17 @@ static void usb_dw_init(void) /* Soft reconnect */ udelay(3000); DWC_DCTL &= ~SDIS; + + /* Fill endpoint spec table FIXME: should be done in usb_drv_startup() */ + usb_drv_ep_specs[0].type[DIR_OUT] = USB_ENDPOINT_XFER_CONTROL; + usb_drv_ep_specs[0].type[DIR_IN] = USB_ENDPOINT_XFER_CONTROL; + for(int i = 1; i < USB_NUM_ENDPOINTS; i += 1) { + bool out_avail = usb_endpoints & (1 << (i + USB_DW_DIR_OFF(USB_DW_EPDIR_OUT))); + usb_drv_ep_specs[i].type[DIR_OUT] = out_avail ? USB_ENDPOINT_TYPE_ANY : USB_ENDPOINT_TYPE_NONE; + + bool in_avail = usb_endpoints & (1 << (i + USB_DW_DIR_OFF(USB_DW_EPDIR_IN))); + usb_drv_ep_specs[i].type[DIR_IN] = in_avail ? USB_ENDPOINT_TYPE_ANY : USB_ENDPOINT_TYPE_NONE; + } } static void usb_dw_exit(void) @@ -1592,56 +1606,50 @@ void INT_USB_FUNC(void) usb_dw_irq(); } -int usb_drv_request_endpoint(int type, int dir) +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { - int request_ep = -1; - enum usb_dw_epdir epdir = (EP_DIR(dir) == DIR_IN) ? - USB_DW_EPDIR_IN : USB_DW_EPDIR_OUT; + (void)max_packet_size; /* FIXME: support max packet size override */ + + enum usb_dw_epdir epdir = (EP_DIR(endpoint) == DIR_IN) ? USB_DW_EPDIR_IN : USB_DW_EPDIR_OUT; + struct usb_dw_ep* dw_ep = usb_dw_get_ep(EP_NUM(endpoint), epdir); + + int maxpktsize; + if(type == EPTYP_ISOCHRONOUS) + { + maxpktsize = 1023; + } + else + { + maxpktsize = usb_drv_port_speed() ? 512 : 64; + } usb_dw_target_disable_irq(); - for (int ep = 1; ep < USB_NUM_ENDPOINTS; ep++) - { - if (usb_endpoints & (1 << (ep + USB_DW_DIR_OFF(epdir)))) - { - struct usb_dw_ep* dw_ep = usb_dw_get_ep(ep, epdir); - if (!dw_ep->active) - { - int maxpktsize = 64; - if (type == EPTYP_ISOCHRONOUS){ - maxpktsize = 1023; - } else { - maxpktsize = usb_drv_port_speed() ? 512 : 64; - } - - if (usb_dw_configure_ep(ep, epdir, type, - maxpktsize) >= 0) - { - dw_ep->active = true; - request_ep = ep | dir; - } - break; - } - } - } + int res = usb_dw_configure_ep(EP_NUM(endpoint), epdir, type, maxpktsize); usb_dw_target_enable_irq(); - return request_ep; + + if(res >= 0) + { + dw_ep->active = true; + return 0; + } + else + { + return -1; + } } -void usb_drv_release_endpoint(int endpoint) +int usb_drv_deinit_endpoint(int endpoint) { - int epnum = EP_NUM(endpoint); - if (!epnum) return; - enum usb_dw_epdir epdir = (EP_DIR(endpoint) == DIR_IN) ? - USB_DW_EPDIR_IN : USB_DW_EPDIR_OUT; - struct usb_dw_ep* dw_ep = usb_dw_get_ep(epnum, epdir); + enum usb_dw_epdir epdir = (EP_DIR(endpoint) == DIR_IN) ? USB_DW_EPDIR_IN : USB_DW_EPDIR_OUT; + struct usb_dw_ep* dw_ep = usb_dw_get_ep(EP_NUM(endpoint), epdir); usb_dw_target_disable_irq(); - if (dw_ep->active) - { - usb_dw_unconfigure_ep(epnum, epdir); - dw_ep->active = false; - } + usb_dw_unconfigure_ep(EP_NUM(endpoint), epdir); usb_dw_target_enable_irq(); + + dw_ep->active = false; + + return 0; } int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length) diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h index fe1f7459cf..6cee077c0d 100644 --- a/firmware/export/usb_core.h +++ b/firmware/export/usb_core.h @@ -66,9 +66,6 @@ void usb_core_handle_notify(long id, intptr_t data); void usb_core_notify_set_address(uint8_t addr); void usb_core_notify_set_config(uint8_t config); -int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv); -void usb_core_release_endpoint(int dir); - #ifdef HAVE_HOTSWAP void usb_core_hotswap_event(int volume,bool inserted); #endif diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index 35b31a359d..ea048a3cd1 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h @@ -62,6 +62,19 @@ enum usb_control_response { USB_CONTROL_RECEIVE, }; +#define USB_ENDPOINT_TYPE_ANY (-1) +#define USB_ENDPOINT_TYPE_NONE (-2) + +struct usb_drv_ep_spec { + int8_t type[2]; /* USB_ENDPOINT_TYPE_{ANY,NONE} USB_ENDPOINT_XFER_* */ +}; + +extern struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; + +#define USB_ENDPOINT_SPEC_FORCE_IO_TYPE_MATCH (1 << 0) +#define USB_ENDPOINT_SPEC_IO_EXCLUSIVE (1 << 1) +extern uint8_t usb_drv_ep_specs_flags; + /* one-time initialisation of the USB driver */ void usb_drv_startup(void); void usb_drv_int_enable(bool enable); /* Target implemented */ @@ -85,8 +98,8 @@ int usb_drv_port_speed(void); void usb_drv_cancel_all_transfers(void); void usb_drv_set_test_mode(int mode); bool usb_drv_connected(void); -int usb_drv_request_endpoint(int type, int dir); -void usb_drv_release_endpoint(int ep); +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size); +int usb_drv_deinit_endpoint(int endpoint); #ifdef USB_HAS_ISOCHRONOUS /* returns the last received frame number (the 11-bit number contained in the last SOF): * - full-speed: the host sends one SOF every 1ms (so 1000 SOF/s) diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c index d0875ed48c..da165a099a 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525.c +++ b/firmware/target/arm/as3525/usb-drv-as3525.c @@ -36,6 +36,15 @@ #include "usb-drv-as3525.h" +/* OUT EP 2 is an alias for OUT EP 0 on this HW! */ +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_EPS] = { + [0] = {USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_CONTROL}, + [1] = {USB_ENDPOINT_TYPE_ANY, USB_ENDPOINT_TYPE_ANY}, + [2] = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_TYPE_ANY}, + [3] = {USB_ENDPOINT_TYPE_ANY, USB_ENDPOINT_TYPE_ANY}, +}; +uint8_t usb_drv_ep_specs_flags = 0; + static struct usb_endpoint endpoints[USB_NUM_EPS][2]; static int got_set_configuration = 0; static int usb_enum_timeout = -1; @@ -155,16 +164,6 @@ static void reset_endpoints(int init) { int i; - /* - * OUT EP 2 is an alias for OUT EP 0 on this HW! - * - * Resonates with "3 bidirectional- plus 1 in-endpoints in device mode" - * from the datasheet, but why ep2 and not ep3? - * - * Reserve it here so we will skip over it in request_endpoint(). - */ - endpoints[2][1].state |= EP_STATE_ALLOCATED; - for(i = 0; i < USB_NUM_EPS; i++) { /* * MPS sizes depending on speed: @@ -344,62 +343,37 @@ int usb_drv_port_speed(void) return (USB_DEV_STS & USB_DEV_STS_MASK_SPD) ? 0 : 1; } -int usb_drv_request_endpoint(int type, int dir) -{ - int d = dir == USB_DIR_IN ? 0 : 1; - int i = 1; /* skip the control EP */ +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; - for(; i < USB_NUM_EPS; i++) { - if (endpoints[i][d].state & EP_STATE_ALLOCATED) - continue; + int i = EP_NUM(endpoint); + int d = EP_DIR(endpoint) == DIR_IN ? 0 : 1; - endpoints[i][d].state |= EP_STATE_ALLOCATED; - - if (dir == USB_DIR_IN) { - USB_IEP_CTRL(i) = USB_EP_CTRL_FLUSH | - USB_EP_CTRL_SNAK | - USB_EP_CTRL_ACT | - (type << 4); - USB_DEV_EP_INTR_MASK &= ~(1<= USB_NUM_EPS) - return; - /* - * Check for control EP and ignore it. - * Unfortunately the usb core calls - * usb_drv_release_endpoint() for ep=0..(USB_NUM_ENDPOINTS-1), - * but doesn't request a new control EP after that... - */ - if (i == 0 || /* Don't mask control EP */ - (i == 2 && d == 1)) /* See reset_endpoints(), EP2_OUT == EP0_OUT */ - return; - - if (!(endpoints[i][d].state & EP_STATE_ALLOCATED)) - return; - - /* logf("usb_drv_release_endpoint(%d, %d)\n", i, d); */ endpoints[i][d].state = 0; USB_DEV_EP_INTR_MASK |= (1<<(16*d+i)); USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK; + + return 0; } void usb_drv_cancel_all_transfers(void) diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c index 77860b5494..bff18f15e7 100644 --- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c @@ -53,7 +53,6 @@ struct endpoint_t const int type; /* EP type */ const int dir; /* DIR_IN/DIR_OUT */ volatile unsigned long *stat; /* RXSTAT/TXSTAT register */ - bool allocated; /* flag to mark EPs taken */ volatile void *buf; /* tx/rx buffer address */ volatile int len; /* size of the transfer (bytes) */ volatile int cnt; /* number of bytes transfered/received */ @@ -102,6 +101,9 @@ static struct endpoint_t endpoints[16] = ENDPOINT(15, INT, IN, &TX15STAT), /* IIN15 */ }; +struct usb_drv_ep_spec usb_drv_ep_specs[16]; /* filled in usb_drv_startup */ +uint8_t usb_drv_ep_specs_flags = 0; + static volatile bool set_address = false; static volatile bool set_configuration = false; @@ -260,48 +262,47 @@ static void udc_helper(void) } } +void usb_drv_startup(void) { + /* fill the endpoint spec table */ + usb_drv_ep_specs[0].type[DIR_OUT] = USB_ENDPOINT_XFER_CONTROL; + usb_drv_ep_specs[0].type[DIR_IN] = USB_ENDPOINT_XFER_CONTROL; + for(int ep_num = 1; ep_num < 16; ep_num++) { + int dir = endpoints[ep_num].dir; + int type = endpoints[ep_num].type; + usb_drv_ep_specs[ep_num].type[dir] = type; + usb_drv_ep_specs[ep_num].type[!dir] = USB_ENDPOINT_TYPE_NONE; + } +} + /* return port speed FS=0, HS=1 */ int usb_drv_port_speed(void) { return (DEV_INFO & DEV_SPEED) ? 0 : 1; } -/* Reserve endpoint */ -int usb_drv_request_endpoint(int type, int dir) -{ - logf("req: %s %s", XFER_DIR_STR(dir), XFER_TYPE_STR(type)); +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ - /* Find an available ep/dir pair */ - for(int ep_num = 1; ep_numallocated || endp->type != type || endp->dir != dir) - continue; - /* allocate endpoint and enable interrupt */ - endp->allocated = true; - if(dir == USB_DIR_IN) - TXCON(endp) = (ep_num << 8) | TXEPEN | TXNAK | TXACKINTEN | TXCFINTE; - else - RXCON(endp) = (ep_num << 8) | RXEPEN | RXNAK | RXACKINTEN | RXCFINTE | RXERRINTEN; - EN_INT |= 1 << (ep_num + 7); + struct endpoint_t *endp = &endpoints[num]; - logf("add: ep%d %s", ep_num, XFER_DIR_STR(dir)); - return ep_num | dir; - } - return -1; + if(EP_DIR(endpoint) == DIR_IN) + TXCON(endp) = (num << 8) | TXEPEN | TXNAK | TXACKINTEN | TXCFINTE; + else + RXCON(endp) = (num << 8) | RXEPEN | RXNAK | RXACKINTEN | RXCFINTE | RXERRINTEN; + EN_INT |= 1 << (num + 7); + + return 0; } -/* Free endpoint */ -void usb_drv_release_endpoint(int ep) -{ - int ep_num = EP_NUM(ep); - - logf("rel: ep%d", ep_num); - endpoints[ep_num].allocated = false; +int usb_drv_deinit_endpoint(int endpoint) { + int num = EP_NUM(endpoint); + struct endpoint_t *endp = &endpoints[num]; /* disable interrupt from this endpoint */ - EN_INT &= ~(1 << (ep_num + 7)); + EN_INT &= ~(1 << (num + 7)); } /* Set the address (usually it's in a register). diff --git a/firmware/target/arm/rk27xx/usb-rk27xx.c b/firmware/target/arm/rk27xx/usb-rk27xx.c index 09c9090a3b..4c1e62a875 100644 --- a/firmware/target/arm/rk27xx/usb-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-rk27xx.c @@ -46,6 +46,8 @@ void usb_init_device(void) /* configure INTCON */ INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ UDC_INTEN; /* enable EP0 interrupts */ + + usb_drv_startup(); } void usb_attach(void) diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c index 61a5a1dbaa..ac92c50253 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c @@ -60,11 +60,12 @@ static bool setup_is_set_address; static cppi_info cppi; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; /* filled in usb_drv_startup */ +uint8_t usb_drv_ep_specs_flags = 0; + static struct ep_runtime_t { int max_packet_size; - bool in_allocated; - bool out_allocated; uint8_t *rx_buf; /* OUT */ int rx_remaining; int rx_size; @@ -1239,13 +1240,22 @@ void usb_charging_maxcurrent_change(int maxcurrent) } } +void usb_drv_startup(void) +{ + /* fill the endpoint spec table */ + usb_drv_ep_specs[0].type[DIR_OUT] = USB_ENDPOINT_XFER_CONTROL; + usb_drv_ep_specs[0].type[DIR_IN] = USB_ENDPOINT_XFER_CONTROL; + for(int i = 1; i < USB_NUM_ENDPOINTS; i += 1) { + usb_drv_ep_specs[i].type[DIR_OUT] = ep_const_data[i].type; + usb_drv_ep_specs[i].type[DIR_IN] = ep_const_data[i].type; + } +} + void usb_drv_init(void) { int epn; memset(ep_runtime, 0, sizeof(ep_runtime)); ep_runtime[0].max_packet_size = EP0_MAX_PACKET_SIZE; - ep_runtime[0].in_allocated = true; - ep_runtime[0].out_allocated = true; for (epn = 0; epn < USB_NUM_ENDPOINTS; epn++) { semaphore_init(&ep_runtime[epn].complete, 1, 0); @@ -1479,41 +1489,16 @@ void usb_drv_set_test_mode(int mode) tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val); } -int usb_drv_request_endpoint(int type, int dir) -{ - int epn; - for (epn = 1; epn < USB_NUM_ENDPOINTS; epn++) - { - if (type == ep_const_data[epn].type) - { - if ((dir == USB_DIR_IN) && (!ep_runtime[epn].in_allocated)) - { - ep_runtime[epn].in_allocated = true; - tnetv_gadget_ep_enable(epn, true); - return epn | USB_DIR_IN; - } - if ((dir == USB_DIR_OUT) && (!ep_runtime[epn].out_allocated)) - { - ep_runtime[epn].out_allocated = true; - tnetv_gadget_ep_enable(epn, false); - return epn | USB_DIR_OUT; - } - } - } - return -1; +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ + + int num = EP_NUM(endpoint); + int dir = EP_DIR(endpoint); + return tnetv_gadget_ep_enable(num, dir == EP_IN); } -void usb_drv_release_endpoint(int ep) -{ - int epn = EP_NUM(ep); - if (EP_DIR(ep) == DIR_IN) - { - ep_runtime[epn].in_allocated = false; - tnetv_gadget_ep_disable(epn, true); - } - else - { - ep_runtime[epn].out_allocated = false; - tnetv_gadget_ep_disable(epn, false); - } +int usb_drv_deinit_endpoint(int endpoint) { + int num = EP_NUM(endpoint); + int dir = EP_DIR(endpoint); + return tnetv_gadget_ep_disable(num, dir == EP_IN); } diff --git a/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c index 986efe374c..2802814284 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c @@ -23,6 +23,7 @@ #include "system.h" #include "kernel.h" #include "usb_core.h" +#include "usb_drv.h" static int usb_detect_callback(struct timeout *tmo) { @@ -82,6 +83,8 @@ void usb_init_device(void) /* Enable USB insert detection interrupt */ IO_INTC_EINT1 |= (1 << 14); + + usb_drv_startup(); } void usb_enable(bool on) diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c index a732340bf9..1596f6a4d5 100644 --- a/firmware/target/arm/usb-drv-arc.c +++ b/firmware/target/arm/usb-drv-arc.c @@ -308,13 +308,8 @@ transfer size, so it seems like a good size */ #define NUM_TDS_PER_EP 4 -typedef struct usb_endpoint -{ - bool allocated[2]; - short type[2]; - short max_pkt_size[2]; -} usb_endpoint_t; -static usb_endpoint_t endpoints[USB_NUM_ENDPOINTS]; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS]; /* filled in usb_drv_startup */ +uint8_t usb_drv_ep_specs_flags = USB_ENDPOINT_SPEC_FORCE_IO_TYPE_MATCH; /* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */ struct transfer_descriptor { @@ -372,8 +367,6 @@ static void prepare_td(struct transfer_descriptor* td, struct transfer_descriptor* previous_td, void *ptr, int len,int pipe); static void bus_reset(void); static void init_control_queue_heads(void); -static void init_queue_heads(void); -static void init_endpoints(void); /*-------------------------------------------------------------------------*/ static void usb_drv_stop(void) { @@ -430,6 +423,14 @@ void usb_drv_startup(void) for(i=0;itype[ep_dir]), - endpoint->max_pkt_size[ep_dir]); -} -#else -#undef log_ep -#define log_ep(...) #endif /* manual: 32.14.1 Device Controller Initialization */ @@ -491,6 +480,14 @@ void usb_drv_init(void) logf("usb dccparams %x", REG_DCCPARAMS); /* now a bus reset will occur. see bus_reset() */ + + /* manual: 32.9.5.18 (Caution): Leaving an unconfigured endpoint control + * will cause undefined behavior for the data pid tracking on the active + * endpoint/direction. */ + for(int ep_num=1;ep_numallocated[ep_dir]) - continue; - - if (endpoint->allocated[other_dir] && - endpoint->type[other_dir] != ep_type) { - logf("ep of different type!"); - continue; + if(max_packet_size == -1) { + if(type == USB_ENDPOINT_XFER_ISOC) { + max_packet_size = 1024; + } else { + max_packet_size = usb_drv_port_speed() ? 512 : 64; } + } + if(type == USB_ENDPOINT_XFER_ISOC) + /* FIXME: we can adjust the number of packets per frame, currently use one */ + qh->max_pkt_length = max_packet_size << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL | 1 << QH_MULT_POS; + else + qh->max_pkt_length = max_packet_size << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; + qh->dtd.next_td_ptr = QH_NEXT_TERMINATE; - endpoint->allocated[ep_dir] = 1; - endpoint->type[ep_dir] = ep_type; + return 0; +} - log_ep(ep_num, ep_dir, "add"); - return (ep_num | (dir & USB_ENDPOINT_DIR_MASK)); +int usb_drv_deinit_endpoint(int endpoint) { + int ep_num = EP_NUM(endpoint); + int ep_dir = EP_DIR(endpoint); + + logf("ep deinit: %d %s", ep_num, XFER_DIR_STR(ep_dir)); + + if(ep_dir == DIR_IN) { + REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_ENABLE & ~EPCTRL_TX_TYPE; + } else { + REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_ENABLE & ~EPCTRL_RX_TYPE; } - return -1; + return 0; } -void usb_drv_release_endpoint(int ep) -{ - int ep_num = EP_NUM(ep); - int ep_dir = EP_DIR(ep); - - log_ep(ep_num, ep_dir, "rel"); - endpoints[ep_num].allocated[ep_dir] = 0; -} - - static void prepare_td(struct transfer_descriptor* td, struct transfer_descriptor* previous_td, void *ptr, int len,int pipe) @@ -978,57 +979,3 @@ static void init_control_queue_heads(void) qh_array[EP_CONTROL+1].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS; qh_array[EP_CONTROL+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; } -/* manual: 32.14.4.1 Queue Head Initialization */ -static void init_queue_heads(void) -{ - int packetsize = (usb_drv_port_speed() ? 512 : 64); - int isopacketsize = (usb_drv_port_speed() ? 1024 : 1024); - int i; - - /* TODO: this should take ep_allocation into account */ - for (i=1;iallocated[DIR_OUT]) - endpoint->type[DIR_OUT] = USB_ENDPOINT_XFER_BULK; - if (!endpoint->allocated[DIR_IN]) - endpoint->type[DIR_IN] = USB_ENDPOINT_XFER_BULK; - - REG_ENDPTCTRL(ep_num) = - EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | - EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | - (endpoint->type[DIR_OUT] << EPCTRL_RX_EP_TYPE_SHIFT) | - (endpoint->type[DIR_IN] << EPCTRL_TX_EP_TYPE_SHIFT); - } -} diff --git a/firmware/target/arm/usb-s3c6400x.c b/firmware/target/arm/usb-s3c6400x.c index 0f3ecf8c00..e570d07e31 100644 --- a/firmware/target/arm/usb-s3c6400x.c +++ b/firmware/target/arm/usb-s3c6400x.c @@ -59,7 +59,6 @@ struct ep_type unsigned int size; /* length of the data buffer */ struct semaphore complete; /* wait object */ int8_t status; /* completion status (0 for success) */ - bool active; /* true is endpoint has been requested (true for EP0) */ bool done; /* transfer completed */ bool busy; /* true is a transfer is pending */ }; @@ -67,6 +66,16 @@ struct ep_type static const uint8_t in_ep_list[] = {0, 1, 3, 5}; static const uint8_t out_ep_list[] = {0, 2, 4}; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS] = { + {.type = {USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_CONTROL}}, + {.type = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_TYPE_ANY}}, + {.type = {USB_ENDPOINT_TYPE_ANY, USB_ENDPOINT_TYPE_NONE}}, + {.type = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_TYPE_ANY}}, + {.type = {USB_ENDPOINT_TYPE_ANY, USB_ENDPOINT_TYPE_NONE}}, + {.type = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_TYPE_ANY}}, +}; +uint8_t usb_drv_ep_specs_flags = 0; + /* state of EP0 (to correctly schedule setup packet enqueing) */ enum ep0state { @@ -225,7 +234,6 @@ static void reset_endpoints(void) { int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; struct ep_type *endpoint = &endpoints[ep][out]; - endpoint->active = false; endpoint->busy = false; endpoint->status = -1; endpoint->done = true; @@ -580,29 +588,19 @@ void INT_USB_FUNC(void) GINTSTS = sts; } -int usb_drv_request_endpoint(int type, int dir) -{ - bool out = dir == USB_DIR_OUT; - for (unsigned i = 1; i < num_eps(out); i++) - { - int ep = (out ? out_ep_list : in_ep_list)[i]; - bool *active = &endpoints[ep][out ? DIR_OUT : DIR_IN].active; - if(*active) - continue; - *active = true; - DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) - | DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) | DEPCTL_usbactep; - return ep | dir; - } +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ - return -1; + int num = EP_NUM(endpoint); + int dir = EP_DIR(endpoint); + bool out = dir == DIR_OUT; + DEPCTL(num, out) = (DEPCTL(num, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) + | DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) | DEPCTL_usbactep; + return 0; } -void usb_drv_release_endpoint(int ep) -{ - if ((ep & 0x7f) == 0) - return; - endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false; +int usb_drv_deinit_endpoint(int endpoint) { + return 0; } void usb_drv_cancel_all_transfers() diff --git a/firmware/target/arm/usb-tcc.c b/firmware/target/arm/usb-tcc.c index 53f101c471..0083655434 100644 --- a/firmware/target/arm/usb-tcc.c +++ b/firmware/target/arm/usb-tcc.c @@ -32,6 +32,7 @@ #ifdef HAVE_USBSTACK #include "usb_ch9.h" #include "usb_core.h" +#include "usb_drv.h" #define TCC7xx_USB_EPIF_IRQ_MASK 0xf @@ -70,9 +71,15 @@ struct tcc_ep { char *buf; /* user buffer to store data */ int max_len; /* how match data will fit */ int count; /* actual data count */ - bool busy; } ; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS] = { + {.type = {USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_CONTROL}}, + {.type = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_XFER_BULK}}, + {.type = {USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_TYPE_NONE}}, +}; +uint8_t usb_drv_ep_specs_flags = 0; + static struct tcc_ep tcc_endpoints[] = { /* control */ { @@ -93,46 +100,16 @@ static struct tcc_ep tcc_endpoints[] = { static bool usb_drv_write_ep(struct tcc_ep *ep); static void usb_set_speed(int); -int usb_drv_request_endpoint(int type, int dir) -{ - int flags = disable_irq_save(); - size_t ep; - int ret = 0; +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ - if (type != USB_ENDPOINT_XFER_BULK) - return -1; - - if (dir == USB_DIR_IN) - ep = 1; - else - ep = 2; - - if (!tcc_endpoints[ep].busy) { - tcc_endpoints[ep].busy = true; - tcc_endpoints[ep].dir = dir; - ret = ep | dir; - } else { - ret = -1; - } - - restore_irq(flags); - return ret; + tcc_endpoints[EP_NUM(endpoint)].dir = EP_DIR(endpoint) == DIR_IN ? USB_DIR_IN : USB_DIR_OUT; + return 0; } -void usb_drv_release_endpoint(int ep) -{ - int flags; - ep = ep & 0x7f; - - if (ep < 1 || ep > USB_NUM_ENDPOINTS) - return ; - - flags = disable_irq_save(); - - tcc_endpoints[ep].busy = false; - tcc_endpoints[ep].dir = -1; - - restore_irq(flags); +int usb_drv_deinit_endpoint(int endpoint) { + tcc_endpoints[EP_NUM(endpoint)].dir = -1; + return 0; } static inline void pullup_on(void) @@ -349,8 +326,6 @@ void handle_ep(unsigned short ep_irq) if (0 == (ep_irq & (1 << endpoint))) continue; - if (!tcc_ep->busy) - panicf_my("ep%d: wasn't requested", endpoint); TCC7xx_USB_INDEX = endpoint; stat = TCC7xx_USB_EP_STAT; @@ -698,7 +673,6 @@ void usb_drv_init(void) tcc_endpoints[i].id = i; tcc_endpoints[i].mask = 1 << i; tcc_endpoints[i].buf = NULL; - tcc_endpoints[i].busy = false; tcc_endpoints[i].dir = -1; } diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index 07697da723..c923d8d97a 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -81,6 +81,13 @@ static struct usb_endpoint endpoints[] = { .type = ep_interrupt, .fifo_addr = USB_FIFO_EP2, .fifo_size = 64 }, }; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS] = { + {.type = {USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_CONTROL}}, + {.type = {USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_BULK}}, + {.type = {USB_ENDPOINT_TYPE_NONE, USB_ENDPOINT_XFER_INT}}, +}; +uint8_t usb_drv_ep_specs_flags = 0; + static inline void select_endpoint(int ep) { REG_USB_REG_INDEX = ep; @@ -829,33 +836,14 @@ void usb_drv_cancel_all_transfers(void) restore_irq(flags); } -void usb_drv_release_endpoint(int ep) -{ - (void)ep; - logf("%s(%d, %s)", __func__, (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)endpoint; + (void)type; + (void)max_packet_size; /* FIXME: support max packet size override */ + return 0; } -int usb_drv_request_endpoint(int type, int dir) -{ - logf("%s(%d, %s)", __func__, type, (dir == USB_DIR_IN) ? "IN" : "OUT"); - - dir &= USB_ENDPOINT_DIR_MASK; - type &= USB_ENDPOINT_XFERTYPE_MASK; - - /* There are only 3+2 endpoints, so hardcode this ... */ - switch(type) - { - case USB_ENDPOINT_XFER_BULK: - if(dir == USB_DIR_IN) - return (1 | USB_DIR_IN); - else - return (1 | USB_DIR_OUT); - - case USB_ENDPOINT_XFER_INT: - if(dir == USB_DIR_IN) - return (2 | USB_DIR_IN); - - default: - return -1; - } +int usb_drv_deinit_endpoint(int endpoint) { + (void)endpoint; + return 0; } diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c index 8ff6d4bc1e..94d841486d 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c @@ -109,6 +109,13 @@ static struct usb_endpoint endpoints[] = EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL), }; +struct usb_drv_ep_spec usb_drv_ep_specs[USB_NUM_ENDPOINTS] = { + {.type = {USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_CONTROL}}, + {.type = {USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_BULK}}, + {.type = {USB_ENDPOINT_XFER_INT, USB_ENDPOINT_XFER_INT}}, +}; +uint8_t usb_drv_ep_specs_flags = 0; + static inline void select_endpoint(int ep) { REG_USB_INDEX = ep; @@ -1185,78 +1192,28 @@ void usb_drv_cancel_all_transfers(void) restore_irq(flags); } -void usb_drv_release_endpoint(int ep) -{ - int n = ep & 0x7f; +int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) { + (void)max_packet_size; /* FIXME: support max packet size override */ - logf("%s(%d, %s)", __func__, (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); - - if (n) - { - int dir = ep & USB_ENDPOINT_DIR_MASK; - - if(dir == USB_DIR_IN) - { - REG_USB_INTRINE &= ~USB_INTR_EP(n); - endpoints[n << 1].allocated = false; - } - else - { - REG_USB_INTROUTE &= ~USB_INTR_EP(n); - endpoints[(n << 1) + 1].allocated = false; - } - } + int num = EP_NUM(endpoint); + int dir = EP_DIR(endpoint); + int index = num * 2 + (dir == DIR_OUT ? 1 : 0); + endpoints[index].allocated = true; + if(dir == DIR_IN) + REG_USB_INTRINE |= USB_INTR_EP(num); + else + REG_USB_INTROUTE |= USB_INTR_EP(num); + return 0; } -int usb_drv_request_endpoint(int type, int dir) -{ - logf("%s(%d, %s)", __func__, type, (dir == USB_DIR_IN) ? "IN" : "OUT"); - - dir &= USB_ENDPOINT_DIR_MASK; - type &= USB_ENDPOINT_XFERTYPE_MASK; - - /* There are only 3+2 endpoints, so hardcode this ... */ - switch(type) - { - case USB_ENDPOINT_XFER_BULK: - if(dir == USB_DIR_IN) - { - if (endpoints[2].allocated) - break; - endpoints[2].allocated = true; - REG_USB_INTRINE |= USB_INTR_EP(1); - return (1 | USB_DIR_IN); - } - else - { - if (endpoints[3].allocated) - break; - endpoints[3].allocated = true; - REG_USB_INTROUTE |= USB_INTR_EP(1); - return (1 | USB_DIR_OUT); - } - - case USB_ENDPOINT_XFER_INT: - if(dir == USB_DIR_IN) - { - if (endpoints[4].allocated) - break; - endpoints[4].allocated = true; - REG_USB_INTRINE |= USB_INTR_EP(2); - return (2 | USB_DIR_IN); - } - else - { - if (endpoints[5].allocated) - break; - endpoints[5].allocated = true; - REG_USB_INTROUTE |= USB_INTR_EP(2); - return (2 | USB_DIR_OUT); - } - - default: - break; - } - - return -1; +int usb_drv_deinit_endpoint(int endpoint) { + int num = EP_NUM(endpoint); + int dir = EP_DIR(endpoint); + int index = num * 2 + (dir == DIR_OUT ? 1 : 0); + endpoints[index].allocated = false; + if(dir == DIR_IN) + REG_USB_INTRINE &= ~USB_INTR_EP(num); + else + REG_USB_INTROUTE &= ~USB_INTR_EP(num); + return 0; } diff --git a/firmware/usbstack/usb_audio.c b/firmware/usbstack/usb_audio.c index de67cdf366..e55e93ce9b 100644 --- a/firmware/usbstack/usb_audio.c +++ b/firmware/usbstack/usb_audio.c @@ -297,8 +297,15 @@ static int usb_as_playback_intf_alt; /* playback streaming interface alternate s static int as_playback_freq_idx; /* audio playback streaming frequency index (in hw_freq_sampr) */ -static int out_iso_ep_adr; /* output isochronous endpoint */ -static int in_iso_feedback_ep_adr; /* input feedback isochronous endpoint */ +struct usb_class_driver_ep_allocation usb_audio_ep_allocs[2] = { + /* output isochronous endpoint */ + {.type = USB_ENDPOINT_XFER_ISOC, .dir = DIR_OUT, .optional = false}, + /* input feedback isochronous endpoint */ + {.type = USB_ENDPOINT_XFER_ISOC, .dir = DIR_IN, .optional = false}, +}; + +#define EP_ISO_OUT (usb_audio_ep_allocs[0].ep) +#define EP_ISO_FEEDBACK_IN (usb_audio_ep_allocs[1].ep) /* small buffer used for control transfers */ static unsigned char usb_buffer[128] USB_DEVBSS_ATTR; @@ -561,47 +568,14 @@ void usb_audio_free_buf(void) dsp_buf = NULL; } -int usb_audio_request_endpoints(struct usb_class_driver *drv) -{ - // make sure we can get the buffers first... - // return -1 if the allocation _failed_ - if (usb_audio_request_buf()) - return -1; - - out_iso_ep_adr = usb_core_request_endpoint(USB_ENDPOINT_XFER_ISOC, USB_DIR_OUT, drv); - if(out_iso_ep_adr < 0) - { - logf("usbaudio: cannot get an out iso endpoint"); - return -1; - } - - in_iso_feedback_ep_adr = usb_core_request_endpoint(USB_ENDPOINT_XFER_ISOC, USB_DIR_IN, drv); - if(in_iso_feedback_ep_adr < 0) - { - usb_core_release_endpoint(out_iso_ep_adr); - logf("usbaudio: cannot get an in iso endpoint"); - return -1; - } - - logf("usbaudio: iso out ep is 0x%x, in ep is 0x%x", out_iso_ep_adr, in_iso_feedback_ep_adr); - - as_iso_audio_out_ep.bEndpointAddress = out_iso_ep_adr; - as_iso_audio_out_ep.bSynchAddress = in_iso_feedback_ep_adr; - - as_iso_synch_in_ep.bEndpointAddress = in_iso_feedback_ep_adr; - as_iso_synch_in_ep.bSynchAddress = 0; - - return 0; -} - unsigned int usb_audio_get_out_ep(void) { - return out_iso_ep_adr; + return EP_ISO_OUT; } unsigned int usb_audio_get_in_ep(void) { - return in_iso_feedback_ep_adr; + return EP_ISO_FEEDBACK_IN; } int usb_audio_set_first_interface(int interface) @@ -638,6 +612,10 @@ int usb_audio_get_config_descriptor(unsigned char *dest, int max_packet_size) /* endpoints */ as_iso_audio_out_ep.wMaxPacketSize = 1023; + as_iso_audio_out_ep.bEndpointAddress = EP_ISO_OUT; + as_iso_audio_out_ep.bSynchAddress = EP_ISO_FEEDBACK_IN; + as_iso_synch_in_ep.bEndpointAddress = EP_ISO_FEEDBACK_IN; + as_iso_synch_in_ep.bSynchAddress = 0; /** Endpoint Interval calculation: * typically sampling frequency is 44100 Hz and top is 192000 Hz, which @@ -691,7 +669,7 @@ static void playback_audio_get_more(const void **start, size_t *size) { logf("usbaudio: recover usb rx overflow"); usb_rx_overflow = false; - usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE); + usb_drv_recv_nonblocking(EP_ISO_OUT, rx_buffer, BUFFER_SIZE); } restore_irq(oldlevel); } @@ -731,7 +709,7 @@ static void usb_audio_start_playback(void) pcm_apply_settings(); mixer_channel_set_amplitude(PCM_MIXER_CHAN_USBAUDIO, MIX_AMP_UNITY); - usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE); + usb_drv_recv_nonblocking(EP_ISO_OUT, rx_buffer, BUFFER_SIZE); } static void usb_audio_stop_playback(void) @@ -883,7 +861,7 @@ static bool usb_audio_endpoint_request(struct usb_ctrlrequest* req, void *reqdat { int ep = req->wIndex & 0xff; - if(ep == out_iso_ep_adr) + if(ep == EP_ISO_OUT) return usb_audio_as_ctrldata_endpoint_request(req, reqdata); else { @@ -1184,6 +1162,11 @@ void usb_audio_init_connection(void) { logf("usbaudio: init connection"); + // make sure we can get the buffers first... + // TODO: disable this driver when failed + if (usb_audio_request_buf()) + return; + usbaudio_active = true; dsp = dsp_get_config(CODEC_IDX_AUDIO); dsp_configure(dsp, DSP_RESET, 0); @@ -1204,6 +1187,9 @@ void usb_audio_disconnect(void) { logf("usbaudio: disconnect"); + if(!usbaudio_active) + return; + usb_audio_stop_playback(); usb_audio_free_buf(); usbaudio_active = false; @@ -1289,7 +1275,7 @@ bool usb_audio_fast_transfer_complete(int ep, int dir, int status, int length) (void) dir; bool retval = false; - if(ep == out_iso_ep_adr && usb_as_playback_intf_alt == 1) + if(ep == EP_ISO_OUT && usb_as_playback_intf_alt == 1) { // check for dropped frames if (last_frame != usb_drv_get_frame_number()) @@ -1340,7 +1326,7 @@ bool usb_audio_fast_transfer_complete(int ep, int dir, int status, int length) if(rx_usb_idx != rx_play_idx) { logf("usbaudio: new transaction"); - usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE); + usb_drv_recv_nonblocking(EP_ISO_OUT, rx_buffer, BUFFER_SIZE); } else { @@ -1399,7 +1385,7 @@ bool usb_audio_fast_transfer_complete(int ep, int dir, int status, int length) encodeFBfixedpt(sendFf, samples_fb, usb_drv_port_speed()); logf("usbaudio: frame %d fbval 0x%02X%02X%02X%02X", usb_drv_get_frame_number(), sendFf[3], sendFf[2], sendFf[1], sendFf[0]); - usb_drv_send_nonblocking(in_iso_feedback_ep_adr, sendFf, usb_drv_port_speed()?4:3); + usb_drv_send_nonblocking(EP_ISO_FEEDBACK_IN, sendFf, usb_drv_port_speed()?4:3); // debug screen counters // diff --git a/firmware/usbstack/usb_audio.h b/firmware/usbstack/usb_audio.h index ebe5542da0..b6cd2461d7 100644 --- a/firmware/usbstack/usb_audio.h +++ b/firmware/usbstack/usb_audio.h @@ -30,20 +30,7 @@ * Relevant specifications are USB 2.0 and USB Audio Class 1.0. */ -/* - * usb_audio_request_endpoints(): - * - * Calls usb_core_request_endpoint() to request one IN and one OUT - * isochronous endpoint. - * - * Called by allocate_interfaces_and_endpoints(). - * - * Returns -1 if either request fails, returns 0 if success. - * - * Also requests buffer allocations. If allocation fails, - * returns -1 so that the driver will be disabled by the USB core. - */ -int usb_audio_request_endpoints(struct usb_class_driver *); +extern struct usb_class_driver_ep_allocation usb_audio_ep_allocs[2]; /* * usb_audio_set_first_interface(): diff --git a/firmware/usbstack/usb_charging_only.c b/firmware/usbstack/usb_charging_only.c index 6bd17a92de..3fa384cfec 100644 --- a/firmware/usbstack/usb_charging_only.c +++ b/firmware/usbstack/usb_charging_only.c @@ -46,12 +46,6 @@ static struct usb_interface_descriptor __attribute__((aligned(2))) static int usb_interface; -int usb_charging_only_request_endpoints(struct usb_class_driver *drv) -{ - (void) drv; - return 0; -} - int usb_charging_only_set_first_interface(int interface) { usb_interface = interface; diff --git a/firmware/usbstack/usb_charging_only.h b/firmware/usbstack/usb_charging_only.h index 839e07dae4..68b60956e2 100644 --- a/firmware/usbstack/usb_charging_only.h +++ b/firmware/usbstack/usb_charging_only.h @@ -24,7 +24,6 @@ #include "usb_ch9.h" void usb_charging_only_init(void); -int usb_charging_only_request_endpoints(struct usb_class_driver *); int usb_charging_only_set_first_interface(int interface); int usb_charging_only_get_config_descriptor(unsigned char *dest,int max_packet_size); bool usb_charging_only_control_request(struct usb_ctrlrequest* req); diff --git a/firmware/usbstack/usb_class_driver.h b/firmware/usbstack/usb_class_driver.h index 8c4d28409c..3bc13b9f6d 100644 --- a/firmware/usbstack/usb_class_driver.h +++ b/firmware/usbstack/usb_class_driver.h @@ -29,6 +29,13 @@ /* Common api, implemented by all class drivers */ +struct usb_class_driver_ep_allocation { + uint8_t type; /* by driver, required ep type. USB_ENDPOINT_XFER_* */ + uint8_t dir; /* by driver, required ep dir. DIR_{IN,OUT} */ + uint8_t ep; /* by core, allocated ep. > 0 are valid but can be 0 if optional==true */ + bool optional; /* by driver, set true to mark this requirement to be optional */ +}; + struct usb_class_driver { /* First some runtime data */ bool enabled; @@ -40,8 +47,9 @@ struct usb_class_driver { /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */ bool needs_exclusive_storage; - /* Let the driver request endpoints it need. Returns zero on success */ - int (*request_endpoints)(struct usb_class_driver *); + /* Endpoint allocation state table */ + uint8_t ep_allocs_size; + struct usb_class_driver_ep_allocation* ep_allocs; /* Tells the driver what its first interface number will be. The driver returns the number of the first available interface for the next driver diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 0a670d43ce..57d6c0efeb 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -183,6 +183,13 @@ static struct struct usb_transfer_completion_event_data completion_event[2]; } ep_data[USB_NUM_ENDPOINTS]; +struct ep_alloc_state { + int8_t type[2]; + struct usb_class_driver* owner[2]; +}; + +static struct ep_alloc_state ep_alloc_states[1][USB_NUM_ENDPOINTS]; + static struct usb_class_driver drivers[USB_NUM_DRIVERS] = { #ifdef USB_ENABLE_STORAGE @@ -191,7 +198,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = .needs_exclusive_storage = true, .first_interface = 0, .last_interface = 0, - .request_endpoints = usb_storage_request_endpoints, + .ep_allocs_size = ARRAYLEN(usb_storage_ep_allocs), + .ep_allocs = usb_storage_ep_allocs, .set_first_interface = usb_storage_set_first_interface, .get_config_descriptor = usb_storage_get_config_descriptor, .init_connection = usb_storage_init_connection, @@ -210,7 +218,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = .needs_exclusive_storage = false, .first_interface = 0, .last_interface = 0, - .request_endpoints = usb_serial_request_endpoints, + .ep_allocs_size = ARRAYLEN(usb_serial_ep_allocs), + .ep_allocs = usb_serial_ep_allocs, .set_first_interface = usb_serial_set_first_interface, .get_config_descriptor = usb_serial_get_config_descriptor, .init_connection = usb_serial_init_connection, @@ -229,7 +238,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = .needs_exclusive_storage = false, .first_interface = 0, .last_interface = 0, - .request_endpoints = usb_charging_only_request_endpoints, + .ep_allocs_size = 0, + .ep_allocs = NULL, .set_first_interface = usb_charging_only_set_first_interface, .get_config_descriptor = usb_charging_only_get_config_descriptor, .init_connection = NULL, @@ -248,7 +258,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = .needs_exclusive_storage = false, .first_interface = 0, .last_interface = 0, - .request_endpoints = usb_hid_request_endpoints, + .ep_allocs_size = ARRAYLEN(usb_hid_ep_allocs), + .ep_allocs = usb_hid_ep_allocs, .set_first_interface = usb_hid_set_first_interface, .get_config_descriptor = usb_hid_get_config_descriptor, .init_connection = usb_hid_init_connection, @@ -267,7 +278,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = .needs_exclusive_storage = false, .first_interface = 0, .last_interface = 0, - .request_endpoints = usb_audio_request_endpoints, + .ep_allocs_size = ARRAYLEN(usb_audio_ep_allocs), + .ep_allocs = usb_audio_ep_allocs, .set_first_interface = usb_audio_set_first_interface, .get_config_descriptor = usb_audio_get_config_descriptor, .init_connection = usb_audio_init_connection, @@ -459,6 +471,9 @@ void usb_core_init(void) if(drivers[i].init != NULL) drivers[i].init(); + /* clear endpoint allocation state */ + memset(ep_alloc_states, 0, sizeof(ep_alloc_states)); + initialized = true; usb_state = DEFAULT; #ifdef HAVE_USB_CHARGING_ENABLE @@ -558,63 +573,99 @@ static void usb_core_set_serial_function_id(void) usb_string_iSerial.wString[0] = hex[id]; } -int usb_core_request_endpoint(int type, int dir, struct usb_class_driver* drv) -{ - int ret, ep; - - ret = usb_drv_request_endpoint(type, dir); - - if(ret == -1) - return -1; - - dir = EP_DIR(ret); - ep = EP_NUM(ret); - - ep_data[ep].completion_handler[dir] = drv->transfer_complete; - ep_data[ep].fast_completion_handler[dir] = drv->fast_transfer_complete; - ep_data[ep].control_handler[dir] = drv->control_request; - - return ret; -} - -void usb_core_release_endpoint(int ep) -{ - int dir; - - usb_drv_release_endpoint(ep); - - dir = EP_DIR(ep); - ep = EP_NUM(ep); - - ep_data[ep].completion_handler[dir] = NULL; - ep_data[ep].control_handler[dir] = NULL; -} - static void allocate_interfaces_and_endpoints(void) { - int i; int interface = 0; - memset(ep_data, 0, sizeof(ep_data)); - - for(i = 0; i < USB_NUM_ENDPOINTS; i++) { - usb_drv_release_endpoint(i | USB_DIR_OUT); - usb_drv_release_endpoint(i | USB_DIR_IN); - } - - for(i = 0; i < USB_NUM_DRIVERS; i++) { - if(drivers[i].enabled) { - drivers[i].first_interface = interface; - - if(drivers[i].request_endpoints(&drivers[i])) { - drivers[i].enabled = false; - continue; + /* deinit previously allocated endpoints */ + for(int conf = 0; conf < 1; conf += 1) { + for(int epnum = 0; epnum < USB_NUM_ENDPOINTS; epnum += 1) { + for(int dir = 0; dir < 2; dir += 1) { + struct ep_alloc_state* alloc = &ep_alloc_states[0][epnum]; + if(alloc->owner[dir] != NULL) { + int ep = epnum | (dir == DIR_OUT ? USB_DIR_OUT : USB_DIR_IN); + usb_drv_deinit_endpoint(ep); + alloc->owner[dir] = NULL; + } } - - interface = drivers[i].set_first_interface(interface); - drivers[i].last_interface = interface; } } + + for(int i = 0; i < USB_NUM_DRIVERS; i++) { + struct usb_class_driver* driver = &drivers[i]; + + if(!driver->enabled) { + continue; + } + + /* assign endpoints */ + for(int reqnum = 0; reqnum < driver->ep_allocs_size; reqnum += 1) { + /* find matching ep */ + struct usb_class_driver_ep_allocation* req = &driver->ep_allocs[reqnum]; + req->ep = 0; + for(int epnum = 1; epnum < USB_NUM_ENDPOINTS; epnum += 1) { + struct usb_drv_ep_spec* spec = &usb_drv_ep_specs[epnum]; + /* ep type check */ + const int8_t spec_type = spec->type[req->dir]; + if(spec_type != req->type && spec_type != USB_ENDPOINT_TYPE_ANY) { + continue; + } + /* free check */ + struct ep_alloc_state* alloc = &ep_alloc_states[0][epnum]; + if(alloc->owner[req->dir] != NULL) { + continue; + } + + /* this ep's requested direction is free */ + + /* another checks */ + if(usb_drv_ep_specs_flags & USB_ENDPOINT_SPEC_IO_EXCLUSIVE) { + /* check for the other direction type */ + if(alloc->owner[!req->dir] != NULL) { + /* the other side is allocated */ + continue; + } + } + if(usb_drv_ep_specs_flags & USB_ENDPOINT_SPEC_FORCE_IO_TYPE_MATCH) { + /* check for other direction type */ + if(alloc->owner[!req->dir] != NULL && alloc->type[!req->dir] != req->type) { + /* the other side is allocated with another type */ + continue; + } + } + + /* all checks passed, assign it */ + const int ep = epnum | (req->dir == DIR_OUT ? USB_DIR_OUT : USB_DIR_IN); + req->ep = ep; + alloc->owner[req->dir] = driver; + alloc->type[req->dir] = req->type; + break; + } + if(req->ep == 0 && !req->optional) { + /* no matching ep found, disable the driver */ + driver->enabled = false; + /* also revert all allocations for this driver */ + for(reqnum = reqnum - 1; reqnum >= 0; reqnum -= 1) { + const uint8_t ep = driver->ep_allocs[reqnum].ep; + const uint8_t epnum = EP_NUM(ep); + const uint8_t epdir = EP_DIR(ep); + const uint8_t dir = epdir == USB_DIR_OUT ? DIR_OUT : DIR_IN; + ep_alloc_states[0][epnum].owner[dir] = NULL; + } + break; + } + } + + if(!driver->enabled) { + continue; + } + + /* assign interfaces */ + driver->first_interface = interface; + interface = driver->set_first_interface(interface); + driver->last_interface = interface; + } + usb_core_num_interfaces = interface; } @@ -778,6 +829,35 @@ static void usb_core_do_set_addr(uint8_t address) static void usb_core_do_set_config(uint8_t config) { logf("usb_core: SET_CONFIG %d",config); + + /* (de)initialize allocated endpoints */ + const bool init = usb_state == ADDRESS && config; + const bool deinit = usb_state == CONFIGURED && !config; + if(init || deinit) { + memset(ep_data, 0, sizeof(ep_data)); + for(int epnum = 0; epnum < USB_NUM_ENDPOINTS; epnum += 1) { + for(int dir = 0; dir < 2; dir += 1) { + struct ep_alloc_state* alloc = &ep_alloc_states[0][epnum]; + if(alloc->owner[dir] == NULL) { + continue; + } + int ep = epnum | (dir == DIR_OUT ? USB_DIR_OUT : USB_DIR_IN); + int ret = init ? + usb_drv_init_endpoint(ep, alloc->type[dir], -1) : + usb_drv_deinit_endpoint(ep); + if(ret) { + logf("usb_core: usb_drv_%s_endpoint failed ep=%d dir=%e", init ? "init" : "deinit", epnum, dir); + continue; + } + if(init) { + ep_data[epnum].completion_handler[dir] = alloc->owner[dir]->transfer_complete; + ep_data[epnum].fast_completion_handler[dir] = alloc->owner[dir]->fast_transfer_complete; + ep_data[epnum].control_handler[dir] = alloc->owner[dir]->control_request; + } + } + } + } + if(config) { usb_state = CONFIGURED; diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c index 64aa123ced..44aee59b98 100644 --- a/firmware/usbstack/usb_hid.c +++ b/firmware/usbstack/usb_hid.c @@ -186,9 +186,14 @@ static int cur_buf_send; static bool active = false; static bool currently_sending = false; -static int ep_in; static int usb_interface; +struct usb_class_driver_ep_allocation usb_hid_ep_allocs[1] = { + {.type = USB_ENDPOINT_XFER_INT, .dir = DIR_IN, .optional = false}, +}; + +#define EP_IN (usb_hid_ep_allocs[0].ep) + static void usb_hid_try_send_drv(void); static void pack_parameter(unsigned char **dest, bool is_signed, bool mark_size, @@ -235,15 +240,6 @@ static void pack_parameter(unsigned char **dest, bool is_signed, bool mark_size, } } -int usb_hid_request_endpoints(struct usb_class_driver *drv) -{ - ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_INT, USB_DIR_IN, drv); - if (ep_in < 0) - return -1; - - return 0; -} - int usb_hid_set_first_interface(int interface) { usb_interface = interface; @@ -608,7 +604,7 @@ int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size) /* Endpoint descriptor */ endpoint_descriptor.wMaxPacketSize = 8; endpoint_descriptor.bInterval = 8; - endpoint_descriptor.bEndpointAddress = ep_in; + endpoint_descriptor.bEndpointAddress = EP_IN; PACK_DATA(&dest, endpoint_descriptor); return (int)(dest - orig_dest); @@ -832,7 +828,7 @@ static void usb_hid_try_send_drv(void) } logf("HID: Sending %d bytes",length); - rc = usb_drv_send_nonblocking(ep_in, send_buffer[cur_buf_send], length); + rc = usb_drv_send_nonblocking(EP_IN, send_buffer[cur_buf_send], length); currently_sending = true; if (rc) send_buffer_len[cur_buf_send] = 0; diff --git a/firmware/usbstack/usb_hid.h b/firmware/usbstack/usb_hid.h index 41e6662e29..379b17d2bf 100644 --- a/firmware/usbstack/usb_hid.h +++ b/firmware/usbstack/usb_hid.h @@ -21,11 +21,12 @@ #ifndef USB_HID_H #define USB_HID_H -#include "usb_ch9.h" #include "usb_core.h" +#include "usb_class_driver.h" #include "usb_hid_usage_tables.h" -int usb_hid_request_endpoints(struct usb_class_driver *drv); +extern struct usb_class_driver_ep_allocation usb_hid_ep_allocs[1]; + int usb_hid_set_first_interface(int interface); int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size); void usb_hid_init_connection(void); diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c index ae90b57078..5c3b084b4b 100644 --- a/firmware/usbstack/usb_serial.c +++ b/firmware/usbstack/usb_serial.c @@ -206,32 +206,18 @@ static int buffer_length; static int buffer_transitlength; static bool active = false; -static int ep_in, ep_out, ep_int; +struct usb_class_driver_ep_allocation usb_serial_ep_allocs[3] = { + {.type = USB_ENDPOINT_XFER_BULK, .dir = DIR_IN, .optional = false}, + {.type = USB_ENDPOINT_XFER_BULK, .dir = DIR_OUT, .optional = false}, + {.type = USB_ENDPOINT_XFER_INT, .dir = DIR_IN, .optional = true}, +}; + +#define EP_IN (usb_serial_ep_allocs[0].ep) +#define EP_OUT (usb_serial_ep_allocs[1].ep) +#define EP_INT (usb_serial_ep_allocs[2].ep) + static int control_interface, data_interface; -int usb_serial_request_endpoints(struct usb_class_driver *drv) -{ - ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN, drv); - if (ep_in < 0) - return -1; - - ep_out = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT, - drv); - if (ep_out < 0) { - usb_core_release_endpoint(ep_in); - return -1; - } - - /* Optional interrupt endpoint. While the code does not actively use it, - * it is needed to get out-of-the-box serial port experience on Windows - * and Linux. If this endpoint is not available, only CDC Data interface - * will be exported (can still work on Linux with manual modprobe). - */ - ep_int = usb_core_request_endpoint(USB_ENDPOINT_XFER_INT, USB_DIR_IN, drv); - - return 0; -} - int usb_serial_set_first_interface(int interface) { control_interface = interface; @@ -250,7 +236,7 @@ int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size) union_descriptor.bSubordinateInterface0 = data_interface; data_interface_descriptor.bInterfaceNumber = data_interface; - if (ep_int > 0) + if (EP_INT > 0) { PACK_DATA(&dest, association_descriptor); PACK_DATA(&dest, control_interface_descriptor); @@ -263,7 +249,7 @@ int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size) * both on Full and High speed. Note that max_packet_size is for bulk. * Maximum bInterval for High Speed is 16 and for Full Speed is 255. */ - endpoint_descriptor.bEndpointAddress = ep_int; + endpoint_descriptor.bEndpointAddress = EP_INT; endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint_descriptor.wMaxPacketSize = 64; endpoint_descriptor.bInterval = 16; @@ -271,13 +257,13 @@ int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size) } PACK_DATA(&dest, data_interface_descriptor); - endpoint_descriptor.bEndpointAddress = ep_in; + endpoint_descriptor.bEndpointAddress = EP_IN; endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK; endpoint_descriptor.wMaxPacketSize = max_packet_size; endpoint_descriptor.bInterval = 0; PACK_DATA(&dest, endpoint_descriptor); - endpoint_descriptor.bEndpointAddress = ep_out; + endpoint_descriptor.bEndpointAddress = EP_OUT; PACK_DATA(&dest, endpoint_descriptor); return (dest - orig_dest); @@ -346,7 +332,7 @@ bool usb_serial_control_request(struct usb_ctrlrequest* req, void* reqdata, unsi void usb_serial_init_connection(void) { /* prime rx endpoint */ - usb_drv_recv_nonblocking(ep_out, receive_buffer, RECV_BUFFER_SIZE); + usb_drv_recv_nonblocking(EP_OUT, receive_buffer, RECV_BUFFER_SIZE); /* we come here too after a bus reset, so reset some data */ buffer_transitlength = 0; @@ -379,7 +365,7 @@ static void sendout(void) buffer_transitlength = MIN(buffer_transitlength,TRANSIT_BUFFER_SIZE); buffer_length -= buffer_transitlength; memcpy(transit_buffer,&send_buffer[buffer_start],buffer_transitlength); - usb_drv_send_nonblocking(ep_in,transit_buffer,buffer_transitlength); + usb_drv_send_nonblocking(EP_IN,transit_buffer,buffer_transitlength); } } @@ -437,7 +423,7 @@ void usb_serial_transfer_complete(int ep,int dir, int status, int length) /* Data received. TODO : Do something with it ? */ /* Get the next bit */ - usb_drv_recv_nonblocking(ep_out, receive_buffer, RECV_BUFFER_SIZE); + usb_drv_recv_nonblocking(EP_OUT, receive_buffer, RECV_BUFFER_SIZE); break; case USB_DIR_IN: diff --git a/firmware/usbstack/usb_serial.h b/firmware/usbstack/usb_serial.h index c4c0e78724..e78273cb8e 100644 --- a/firmware/usbstack/usb_serial.h +++ b/firmware/usbstack/usb_serial.h @@ -21,9 +21,10 @@ #ifndef USB_SERIAL_H #define USB_SERIAL_H -#include "usb_ch9.h" +#include "usb_class_driver.h" + +extern struct usb_class_driver_ep_allocation usb_serial_ep_allocs[3]; -int usb_serial_request_endpoints(struct usb_class_driver *); int usb_serial_set_first_interface(int interface); int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size); void usb_serial_init_connection(void); diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index 75f71e7d3a..4aadf1e0f1 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c @@ -321,7 +321,14 @@ static bool ejected[NUM_DRIVES]; static bool locked[NUM_DRIVES]; static int usb_interface; -static int ep_in, ep_out; + +struct usb_class_driver_ep_allocation usb_storage_ep_allocs[2] = { + {.type = USB_ENDPOINT_XFER_BULK, .dir = DIR_IN, .optional = false}, + {.type = USB_ENDPOINT_XFER_BULK, .dir = DIR_OUT, .optional = false}, +}; + +#define EP_IN (usb_storage_ep_allocs[0].ep) +#define EP_OUT (usb_storage_ep_allocs[1].ep) #if defined(HAVE_MULTIDRIVE) static bool skip_first = 0; @@ -399,24 +406,6 @@ void usb_storage_init(void) logf("usb_storage_init done"); } -int usb_storage_request_endpoints(struct usb_class_driver *drv) -{ - ep_in = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN, drv); - - if(ep_in<0) - return -1; - - ep_out = usb_core_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT, - drv); - - if(ep_out<0) { - usb_core_release_endpoint(ep_in); - return -1; - } - - return 0; -} - int usb_storage_set_first_interface(int interface) { usb_interface = interface; @@ -432,10 +421,10 @@ int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size) endpoint_descriptor.wMaxPacketSize = max_packet_size; - endpoint_descriptor.bEndpointAddress = ep_in; + endpoint_descriptor.bEndpointAddress = EP_IN; PACK_DATA(&dest, endpoint_descriptor); - endpoint_descriptor.bEndpointAddress = ep_out; + endpoint_descriptor.bEndpointAddress = EP_OUT; PACK_DATA(&dest, endpoint_descriptor); return (dest - orig_dest); @@ -486,7 +475,7 @@ void usb_storage_init_connection(void) ramdisk_buffer = tb.transfer_buffer + ALLOCATE_BUFFER_SIZE; #endif #endif - usb_drv_recv_nonblocking(ep_out, cbw_buffer, MAX_CBW_SIZE); + usb_drv_recv_nonblocking(EP_OUT, cbw_buffer, MAX_CBW_SIZE); int i; for(i=0;isignature) != CBW_SIGNATURE) { logf("ums: bad cbw signature (%x)", cbw->signature); - usb_drv_stall(ep_in, true,true); - usb_drv_stall(ep_out, true,false); + usb_drv_stall(EP_IN, true,true); + usb_drv_stall(EP_OUT, true,false); return; } /* Clear the signature to prevent possible bugs elsewhere @@ -1407,33 +1396,33 @@ static void handle_scsi(struct command_block_wrapper* cbw) static void send_block_data(void *data,int size) { - usb_drv_send_nonblocking(ep_in, data,size); + usb_drv_send_nonblocking(EP_IN, data,size); state = SENDING_BLOCKS; } static void send_command_result(void *data,int size) { - usb_drv_send_nonblocking(ep_in, data,size); + usb_drv_send_nonblocking(EP_IN, data,size); state = SENDING_RESULT; } static void send_command_failed_result(void) { - usb_drv_send_nonblocking(ep_in, NULL, 0); + usb_drv_send_nonblocking(EP_IN, NULL, 0); state = SENDING_FAILED_RESULT; } #if CONFIG_RTC static void receive_time(void) { - usb_drv_recv_nonblocking(ep_out, tb.transfer_buffer, 12); + usb_drv_recv_nonblocking(EP_OUT, tb.transfer_buffer, 12); state = RECEIVING_TIME; } #endif /* CONFIG_RTC */ static void receive_block_data(void *data,int size) { - usb_drv_recv_nonblocking(ep_out, data, size); + usb_drv_recv_nonblocking(EP_OUT, data, size); state = RECEIVING_BLOCKS; } @@ -1444,12 +1433,12 @@ static void send_csw(int status) tb.csw->data_residue = 0; tb.csw->status = status; - usb_drv_send_nonblocking(ep_in, tb.csw, + usb_drv_send_nonblocking(EP_IN, tb.csw, sizeof(struct command_status_wrapper)); state = WAITING_FOR_CSW_COMPLETION_OR_COMMAND; //logf("CSW: %X",status); /* Already start waiting for the next command */ - usb_drv_recv_nonblocking(ep_out, cbw_buffer, MAX_CBW_SIZE); + usb_drv_recv_nonblocking(EP_OUT, cbw_buffer, MAX_CBW_SIZE); /* The next completed transfer will be either the CSW one * or the new command */ diff --git a/firmware/usbstack/usb_storage.h b/firmware/usbstack/usb_storage.h index af17689110..8dbe965882 100644 --- a/firmware/usbstack/usb_storage.h +++ b/firmware/usbstack/usb_storage.h @@ -21,9 +21,10 @@ #ifndef USB_STORAGE_H #define USB_STORAGE_H -#include "usb_ch9.h" +#include "usb_class_driver.h" + +extern struct usb_class_driver_ep_allocation usb_storage_ep_allocs[2]; -int usb_storage_request_endpoints(struct usb_class_driver *); int usb_storage_set_first_interface(int interface); int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size); void usb_storage_init_connection(void);