mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-01-22 01:30:35 -05:00
usb: implement endpoint allocation
this commit has following changes: - introduce `usb_drv_ep_spec` table to udc drivers, which represents endpoint characteristics. - introduce 'ep_allocs' table to class drivers, which represents what endpoint type does the class driver want. - implement endpoint matching logic to usb core. this is a required step to implement usb config switching, because we need to create config descriptors without actually initializing endpoints. Change-Id: I11c324cd35189ab636744488f6259d0cdb2179f0
This commit is contained in:
parent
f13f80c506
commit
350a2250b1
27 changed files with 579 additions and 714 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/* If this reached USB_NUM_ENDPOINTS the endpoints were all busy */
|
||||
if(ep==USB_NUM_ENDPOINTS) {
|
||||
logf("mxx: ep %d busy", ep);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Not a supported type */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int num = endpoint & USB_ENDPOINT_NUMBER_MASK;
|
||||
int dir = endpoint & USB_ENDPOINT_DIR_MASK;
|
||||
if (dir == USB_DIR_IN) {
|
||||
pipecfg |= (1<<4);
|
||||
}
|
||||
|
||||
M66591_eps[num].dir = dir;
|
||||
|
||||
M66591_eps[ep].busy = true;
|
||||
M66591_eps[ep].dir = dir;
|
||||
|
||||
M66591_PIPE_CFGSEL=ep;
|
||||
|
||||
M66591_PIPE_CFGSEL=num;
|
||||
|
||||
/* Enable pipe (15) */
|
||||
pipecfg |= 1<<15;
|
||||
|
||||
pipe_handshake(ep, PIPE_SHAKE_NAK);
|
||||
pipe_handshake(num, PIPE_SHAKE_NAK);
|
||||
|
||||
/* Setup the flags */
|
||||
M66591_PIPE_CFGWND=pipecfg;
|
||||
|
||||
pipe_init(ep);
|
||||
pipe_init(num);
|
||||
|
||||
logf("mxx: ep req ep#: %d config: 0x%04x", ep, M66591_PIPE_CFGWND);
|
||||
logf("mxx: ep req ep#: %d config: 0x%04x", num, M66591_PIPE_CFGWND);
|
||||
|
||||
return ep | dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Used by stack to tell the helper functions that the pipe is not in use */
|
||||
void usb_drv_release_endpoint(int ep) {
|
||||
int flags;
|
||||
ep &= 0x7f;
|
||||
int usb_drv_deinit_endpoint(int endpoint) {
|
||||
int num = endpoint & USB_ENDPOINT_NUMBER_MASK;
|
||||
|
||||
if (ep < 1 || 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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<<i);
|
||||
} else {
|
||||
USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH |
|
||||
USB_EP_CTRL_SNAK |
|
||||
USB_EP_CTRL_ACT |
|
||||
(type << 4);
|
||||
USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
|
||||
}
|
||||
/* logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); */
|
||||
return i | dir;
|
||||
if (EP_DIR(endpoint) == 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<<i);
|
||||
} else {
|
||||
USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH |
|
||||
USB_EP_CTRL_SNAK |
|
||||
USB_EP_CTRL_ACT |
|
||||
(type << 4);
|
||||
USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
|
||||
}
|
||||
|
||||
logf("usb_drv_request_endpoint(%d, %d): no free endpoint found\n", type, dir);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb_drv_release_endpoint(int ep)
|
||||
{
|
||||
int i = ep & 0x7f;
|
||||
int d = ep & USB_DIR_IN ? 0 : 1;
|
||||
int usb_drv_deinit_endpoint(int endpoint) {
|
||||
int i = EP_NUM(endpoint);
|
||||
int d = EP_DIR(endpoint) == DIR_IN ? 0 : 1;
|
||||
|
||||
if (i >= 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)
|
||||
|
|
|
|||
|
|
@ -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_num<USB_NUM_ENDPOINTS;ep_num++)
|
||||
{
|
||||
struct endpoint_t *endp = &endpoints[ep_num];
|
||||
int num = EP_NUM(endpoint);
|
||||
int dir = EP_DIR(endpoint);
|
||||
|
||||
if(endp->allocated || 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).
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;i<USB_NUM_ENDPOINTS*2;i++) {
|
||||
semaphore_init(&transfer_completion_signal[i], 1, 0);
|
||||
}
|
||||
|
||||
/* 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] = USB_ENDPOINT_TYPE_ANY;
|
||||
usb_drv_ep_specs[i].type[DIR_IN] = USB_ENDPOINT_TYPE_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOGF_ENABLE
|
||||
|
|
@ -439,18 +440,6 @@ void usb_drv_startup(void)
|
|||
((type) == USB_ENDPOINT_XFER_ISOC ? "ISOC" : \
|
||||
((type) == USB_ENDPOINT_XFER_BULK ? "BULK" : \
|
||||
((type) == USB_ENDPOINT_XFER_INT ? "INTR" : "INVL"))))
|
||||
|
||||
static void log_ep(int ep_num, int ep_dir, char* prefix)
|
||||
{
|
||||
usb_endpoint_t* endpoint = &endpoints[ep_num];
|
||||
|
||||
logf("%s: ep%d %s %s %d", prefix, ep_num, XFER_DIR_STR(ep_dir),
|
||||
XFER_TYPE_STR(endpoint->type[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_num<USB_NUM_ENDPOINTS;ep_num++) {
|
||||
usb_drv_init_endpoint(ep_num | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, -1);
|
||||
usb_drv_init_endpoint(ep_num | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_drv_exit(void)
|
||||
|
|
@ -631,8 +628,6 @@ bool usb_drv_powered(void)
|
|||
void usb_drv_set_address(int address)
|
||||
{
|
||||
REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS;
|
||||
init_queue_heads();
|
||||
init_endpoints();
|
||||
}
|
||||
|
||||
void usb_drv_reset_endpoint(int endpoint, bool send)
|
||||
|
|
@ -797,52 +792,58 @@ void usb_drv_cancel_all_transfers(void)
|
|||
}
|
||||
}
|
||||
|
||||
int usb_drv_request_endpoint(int type, int dir)
|
||||
{
|
||||
int ep_num, ep_dir;
|
||||
short ep_type;
|
||||
int usb_drv_init_endpoint(int endpoint, int type, int max_packet_size) {
|
||||
int ep_num = EP_NUM(endpoint);
|
||||
int ep_dir = EP_DIR(endpoint);
|
||||
|
||||
/* Safety */
|
||||
ep_dir = EP_DIR(dir);
|
||||
ep_type = type & USB_ENDPOINT_XFERTYPE_MASK;
|
||||
logf("ep init: %d %s %s", ep_num, XFER_DIR_STR(ep_dir), XFER_TYPE_STR(type));
|
||||
|
||||
logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type));
|
||||
struct queue_head* qh;
|
||||
unsigned int ctrl = REG_ENDPTCTRL(ep_num);
|
||||
if(ep_dir == DIR_IN) {
|
||||
ctrl &= ~EPCTRL_TX_TYPE;
|
||||
ctrl |= EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | type << EPCTRL_TX_EP_TYPE_SHIFT;
|
||||
qh = &qh_array[ep_num * 2 + 1];
|
||||
} else {
|
||||
ctrl &= ~EPCTRL_RX_TYPE;
|
||||
ctrl |= EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | type << EPCTRL_RX_EP_TYPE_SHIFT;
|
||||
qh = &qh_array[ep_num * 2];
|
||||
}
|
||||
REG_ENDPTCTRL(ep_num) = ctrl;
|
||||
|
||||
/* Find an available ep/dir pair */
|
||||
for (ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++) {
|
||||
usb_endpoint_t* endpoint=&endpoints[ep_num];
|
||||
int other_dir=(ep_dir ? 0:1);
|
||||
|
||||
if (endpoint->allocated[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;i<USB_NUM_ENDPOINTS;i++) {
|
||||
|
||||
/* OUT */
|
||||
if(endpoints[i].type[DIR_OUT] == USB_ENDPOINT_XFER_ISOC)
|
||||
/* FIXME: we can adjust the number of packets per frame, currently use one */
|
||||
qh_array[i*2].max_pkt_length = isopacketsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL | 1 << QH_MULT_POS;
|
||||
else
|
||||
qh_array[i*2].max_pkt_length = packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL;
|
||||
|
||||
qh_array[i*2].dtd.next_td_ptr = QH_NEXT_TERMINATE;
|
||||
|
||||
/* IN */
|
||||
if(endpoints[i].type[DIR_IN] == USB_ENDPOINT_XFER_ISOC)
|
||||
/* FIXME: we can adjust the number of packets per frame, currently use one */
|
||||
qh_array[i*2+1].max_pkt_length = isopacketsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL | 1 << QH_MULT_POS;
|
||||
else
|
||||
qh_array[i*2+1].max_pkt_length = packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL;
|
||||
|
||||
qh_array[i*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_endpoints(void)
|
||||
{
|
||||
int ep_num;
|
||||
|
||||
logf("init_endpoints");
|
||||
/* RX/TX from the device POV: OUT/IN, respectively */
|
||||
for(ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++) {
|
||||
usb_endpoint_t *endpoint = &endpoints[ep_num];
|
||||
|
||||
/* 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. */
|
||||
if (!endpoint->allocated[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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;i<storage_num_drives();i++) {
|
||||
|
|
@ -731,8 +720,8 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req, void* reqdata, uns
|
|||
data toggle bits and endpoint STALL conditions despite
|
||||
the Bulk-Only Mass Storage Reset. */
|
||||
#if 0
|
||||
usb_drv_reset_endpoint(ep_in, false);
|
||||
usb_drv_reset_endpoint(ep_out, true);
|
||||
usb_drv_reset_endpoint(EP_IN, false);
|
||||
usb_drv_reset_endpoint(EP_OUT, true);
|
||||
#endif
|
||||
usb_drv_control_response(USB_CONTROL_ACK, NULL, 0);
|
||||
handled = true;
|
||||
|
|
@ -789,8 +778,8 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
|||
|
||||
if(letoh32(cbw->signature) != 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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue