1
0
Fork 0
forked from len0rd/rockbox

reorganise the USB stack a bit to allow for easier integration of non-ARC controller drivers

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18703 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Frank Gevaerts 2008-10-03 22:43:16 +00:00
parent 6219f4c862
commit 478fc5baed
12 changed files with 185 additions and 99 deletions

View file

@ -85,7 +85,7 @@ enum {
struct usb_transfer_completion_event_data struct usb_transfer_completion_event_data
{ {
unsigned char endpoint; unsigned char endpoint;
bool in; int dir;
int status; int status;
int length; int length;
void* data; void* data;

View file

@ -45,10 +45,12 @@
extern int usb_max_pkt_size; extern int usb_max_pkt_size;
struct usb_class_driver;
void usb_core_init(void); void usb_core_init(void);
void usb_core_exit(void); void usb_core_exit(void);
void usb_core_control_request(struct usb_ctrlrequest* req); void usb_core_control_request(struct usb_ctrlrequest* req);
void usb_core_transfer_complete(int endpoint, bool in, int status, int length); void usb_core_transfer_complete(int endpoint, int dir, int status, int length);
void usb_core_bus_reset(void); void usb_core_bus_reset(void);
bool usb_core_exclusive_connection(void); bool usb_core_exclusive_connection(void);
void usb_core_enable_driver(int driver,bool enabled); void usb_core_enable_driver(int driver,bool enabled);
@ -56,6 +58,10 @@ bool usb_core_driver_enabled (int driver);
void usb_core_handle_transfer_completion( void usb_core_handle_transfer_completion(
struct usb_transfer_completion_event_data* event); struct usb_transfer_completion_event_data* event);
int usb_core_ack_control(struct usb_ctrlrequest* req); int usb_core_ack_control(struct usb_ctrlrequest* req);
int usb_core_request_endpoint(int dir, struct usb_class_driver *drv);
void usb_core_release_endpoint(int dir);
#ifdef HAVE_HOTSWAP #ifdef HAVE_HOTSWAP
void usb_core_hotswap_event(int volume,bool inserted); void usb_core_hotswap_event(int volume,bool inserted);
#endif #endif

View file

@ -41,5 +41,7 @@ int usb_drv_port_speed(void);
void usb_drv_cancel_all_transfers(void); void usb_drv_cancel_all_transfers(void);
void usb_drv_set_test_mode(int mode); void usb_drv_set_test_mode(int mode);
bool usb_drv_connected(void); bool usb_drv_connected(void);
int usb_drv_request_endpoint(int dir);
void usb_drv_release_endpoint(int ep);
#endif #endif

View file

@ -363,6 +363,8 @@ static const unsigned int pipe2mask[] = {
0x10, 0x100000, 0x10, 0x100000,
}; };
static char ep_allocation[NUM_ENDPOINTS];
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void transfer_completed(void); static void transfer_completed(void);
static void control_received(void); static void control_received(void);
@ -534,23 +536,23 @@ void usb_drv_int(void)
bool usb_drv_stalled(int endpoint,bool in) bool usb_drv_stalled(int endpoint,bool in)
{ {
if(in) { if(in) {
return ((REG_ENDPTCTRL(endpoint) & EPCTRL_TX_EP_STALL)!=0); return ((REG_ENDPTCTRL(endpoint&0x7f) & EPCTRL_TX_EP_STALL)!=0);
} }
else { else {
return ((REG_ENDPTCTRL(endpoint) & EPCTRL_RX_EP_STALL)!=0); return ((REG_ENDPTCTRL(endpoint&0x7f) & EPCTRL_RX_EP_STALL)!=0);
} }
} }
void usb_drv_stall(int endpoint, bool stall,bool in) void usb_drv_stall(int endpoint, bool stall,bool in)
{ {
logf("%sstall %d", stall?"":"un", endpoint); logf("%sstall %d", stall?"":"un", endpoint&0x7f);
if(in) { if(in) {
if (stall) { if (stall) {
REG_ENDPTCTRL(endpoint) |= EPCTRL_TX_EP_STALL; REG_ENDPTCTRL(endpoint&0x7f) |= EPCTRL_TX_EP_STALL;
} }
else { else {
REG_ENDPTCTRL(endpoint) &= ~EPCTRL_TX_EP_STALL; REG_ENDPTCTRL(endpoint&0x7f) &= ~EPCTRL_TX_EP_STALL;
} }
} }
else { else {
@ -565,23 +567,23 @@ void usb_drv_stall(int endpoint, bool stall,bool in)
int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
{ {
return prime_transfer(endpoint, ptr, length, true, false); return prime_transfer(endpoint&0x7f, ptr, length, true, false);
} }
int usb_drv_send(int endpoint, void* ptr, int length) int usb_drv_send(int endpoint, void* ptr, int length)
{ {
return prime_transfer(endpoint, ptr, length, true, true); return prime_transfer(endpoint&0x7f, ptr, length, true, true);
} }
int usb_drv_recv(int endpoint, void* ptr, int length) int usb_drv_recv(int endpoint, void* ptr, int length)
{ {
//logf("usbrecv(%x, %d)", ptr, length); //logf("usbrecv(%x, %d)", ptr, length);
return prime_transfer(endpoint, ptr, length, false, false); return prime_transfer(endpoint&0x7f, ptr, length, false, false);
} }
void usb_drv_wait(int endpoint, bool send) void usb_drv_wait(int endpoint, bool send)
{ {
int pipe = endpoint * 2 + (send ? 1 : 0); int pipe = (endpoint&0x7f) * 2 + (send ? 1 : 0);
struct queue_head* qh = &qh_array[pipe]; struct queue_head* qh = &qh_array[pipe];
while (qh->dtd.size_ioc_sts & QH_STATUS_ACTIVE) { while (qh->dtd.size_ioc_sts & QH_STATUS_ACTIVE) {
@ -609,7 +611,7 @@ void usb_drv_set_address(int address)
void usb_drv_reset_endpoint(int endpoint, bool send) void usb_drv_reset_endpoint(int endpoint, bool send)
{ {
int pipe = endpoint * 2 + (send ? 1 : 0); int pipe = (endpoint&0x7f) * 2 + (send ? 1 : 0);
unsigned int mask = pipe2mask[pipe]; unsigned int mask = pipe2mask[pipe];
REG_ENDPTFLUSH = mask; REG_ENDPTFLUSH = mask;
while (REG_ENDPTFLUSH & mask); while (REG_ENDPTFLUSH & mask);
@ -753,6 +755,29 @@ void usb_drv_cancel_all_transfers(void)
} }
} }
int usb_drv_request_endpoint(int dir)
{
int i, bit;
bit=(dir & USB_DIR_IN)? 2:1;
for (i=1; i < NUM_ENDPOINTS; i++) {
if((ep_allocation[i] & bit)!=0)
continue;
ep_allocation[i] |= bit;
return i | dir;
}
return -1;
}
void usb_drv_release_endpoint(int ep)
{
int mask = (ep & USB_DIR_IN)? ~2:~1;
ep_allocation[ep & 0x7f] &= mask;
}
static void prepare_td(struct transfer_descriptor* td, static void prepare_td(struct transfer_descriptor* td,
struct transfer_descriptor* previous_td, struct transfer_descriptor* previous_td,
void *ptr, int len,int pipe) void *ptr, int len,int pipe)
@ -831,7 +856,7 @@ static void transfer_completed(void)
qh->wait=0; qh->wait=0;
wakeup_signal(&transfer_completion_signal[pipe]); wakeup_signal(&transfer_completion_signal[pipe]);
} }
usb_core_transfer_complete(ep, dir, qh->status, qh->length); usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT, qh->status, qh->length);
} }
} }
} }
@ -900,6 +925,7 @@ static void init_bulk_queue_heads(void)
rx_packetsize = 64; rx_packetsize = 64;
tx_packetsize = 64; tx_packetsize = 64;
} }
/* TODO: this should take ep_allocation into account */
/*** bulk ***/ /*** bulk ***/
for(i=1;i<NUM_ENDPOINTS;i++) { for(i=1;i<NUM_ENDPOINTS;i++) {
@ -913,6 +939,7 @@ static void init_bulk_queue_heads(void)
static void init_endpoints(void) static void init_endpoints(void)
{ {
int i; int i;
/* TODO: this should take ep_allocation into account */
/* bulk */ /* bulk */
for(i=1;i<NUM_ENDPOINTS;i++) { for(i=1;i<NUM_ENDPOINTS;i++) {
REG_ENDPTCTRL(i) = REG_ENDPTCTRL(i) =

View file

@ -48,11 +48,12 @@ static struct usb_interface_descriptor __attribute__((aligned(2)))
static int usb_interface; static int usb_interface;
int usb_charging_only_set_first_endpoint(int endpoint) int usb_charging_only_request_endpoints(struct usb_class_driver *drv)
{ {
/* The dummy charging_only driver doesn't need an endpoint pair */ (void) drv;
return endpoint; return 0;
} }
int usb_charging_only_set_first_interface(int interface) int usb_charging_only_set_first_interface(int interface)
{ {
usb_interface = interface; usb_interface = interface;

View file

@ -24,7 +24,7 @@
#include "usb_ch9.h" #include "usb_ch9.h"
void usb_charging_only_init(void); void usb_charging_only_init(void);
int usb_charging_only_set_first_endpoint(int endpoint); int usb_charging_only_request_endpoints(struct usb_class_driver *);
int usb_charging_only_set_first_interface(int interface); int usb_charging_only_set_first_interface(int interface);
int usb_charging_only_get_config_descriptor(unsigned char *dest,int max_packet_size); int usb_charging_only_get_config_descriptor(unsigned char *dest,int max_packet_size);
bool usb_charging_only_control_request(struct usb_ctrlrequest* req); bool usb_charging_only_control_request(struct usb_ctrlrequest* req);

View file

@ -35,6 +35,9 @@ struct usb_class_driver {
/* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */ /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */
bool needs_exclusive_ata; bool needs_exclusive_ata;
/* Let the driver request endpoints it need. Returns zero on success */
int (*request_endpoints)(struct usb_class_driver *);
/* Tells the driver what its first interface number will be. The driver /* Tells the driver what its first interface number will be. The driver
returns the number of the first available interface for the next driver returns the number of the first available interface for the next driver
(i.e. a driver with one interface will return interface+1) (i.e. a driver with one interface will return interface+1)
@ -42,12 +45,6 @@ struct usb_class_driver {
Mandatory function */ Mandatory function */
int (*set_first_interface)(int interface); int (*set_first_interface)(int interface);
/* Tells the driver what its first endpoint pair number will be. The driver
returns the number of the first available endpoint pair for the next
driver (i.e. a driver with one endpoint pair will return endpoint +1)
Mandatory function */
int (*set_first_endpoint)(int endpoint);
/* Asks the driver to put the interface descriptor and all other /* Asks the driver to put the interface descriptor and all other
needed descriptor for this driver at dest. needed descriptor for this driver at dest.
Returns the number of bytes taken by these descriptors. Returns the number of bytes taken by these descriptors.
@ -69,10 +66,10 @@ struct usb_class_driver {
Optional function */ Optional function */
void (*disconnect)(void); void (*disconnect)(void);
/* Tells the driver that a usb transfer has been completed. Note that "in" /* Tells the driver that a usb transfer has been completed. Note that "dir"
is relative to the host is relative to the host
Optional function */ Optional function */
void (*transfer_complete)(int ep,bool in, int status, int length); void (*transfer_complete)(int ep,int dir, int status, int length);
/* Tells the driver that a control request has come in. If the driver is /* Tells the driver that a control request has come in. If the driver is
able to handle it, it should ack the request, and return true. Otherwise able to handle it, it should ack the request, and return true. Otherwise

View file

@ -22,7 +22,7 @@
#include "thread.h" #include "thread.h"
#include "kernel.h" #include "kernel.h"
#include "string.h" #include "string.h"
//#define LOGF_ENABLE #define LOGF_ENABLE
#include "logf.h" #include "logf.h"
#include "usb.h" #include "usb.h"
@ -164,10 +164,13 @@ static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state;
static int usb_core_num_interfaces; static int usb_core_num_interfaces;
typedef void (*completion_handler_t)(int ep,int dir, int status, int length);
typedef bool (*control_handler_t)(struct usb_ctrlrequest* req);
static struct static struct
{ {
void (*completion_handler)(int ep,bool in, int status, int length); completion_handler_t completion_handler[2];
bool (*control_handler)(struct usb_ctrlrequest* req); control_handler_t control_handler[2];
struct usb_transfer_completion_event_data completion_event; struct usb_transfer_completion_event_data completion_event;
} ep_data[NUM_ENDPOINTS]; } ep_data[NUM_ENDPOINTS];
@ -179,8 +182,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
.needs_exclusive_ata = true, .needs_exclusive_ata = true,
.first_interface = 0, .first_interface = 0,
.last_interface = 0, .last_interface = 0,
.request_endpoints = usb_storage_request_endpoints,
.set_first_interface = usb_storage_set_first_interface, .set_first_interface = usb_storage_set_first_interface,
.set_first_endpoint = usb_storage_set_first_endpoint,
.get_config_descriptor = usb_storage_get_config_descriptor, .get_config_descriptor = usb_storage_get_config_descriptor,
.init_connection = usb_storage_init_connection, .init_connection = usb_storage_init_connection,
.init = usb_storage_init, .init = usb_storage_init,
@ -198,8 +201,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
.needs_exclusive_ata = false, .needs_exclusive_ata = false,
.first_interface = 0, .first_interface = 0,
.last_interface = 0, .last_interface = 0,
.request_endpoints = usb_serial_request_endpoints,
.set_first_interface = usb_serial_set_first_interface, .set_first_interface = usb_serial_set_first_interface,
.set_first_endpoint = usb_serial_set_first_endpoint,
.get_config_descriptor = usb_serial_get_config_descriptor, .get_config_descriptor = usb_serial_get_config_descriptor,
.init_connection = usb_serial_init_connection, .init_connection = usb_serial_init_connection,
.init = usb_serial_init, .init = usb_serial_init,
@ -217,8 +220,8 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
.needs_exclusive_ata = false, .needs_exclusive_ata = false,
.first_interface = 0, .first_interface = 0,
.last_interface = 0, .last_interface = 0,
.request_endpoints = usb_charging_only_request_endpoints,
.set_first_interface = usb_charging_only_set_first_interface, .set_first_interface = usb_charging_only_set_first_interface,
.set_first_endpoint = usb_charging_only_set_first_endpoint,
.get_config_descriptor = usb_charging_only_get_config_descriptor, .get_config_descriptor = usb_charging_only_get_config_descriptor,
.init_connection = NULL, .init_connection = NULL,
.init = NULL, .init = NULL,
@ -339,6 +342,7 @@ void usb_core_handle_transfer_completion(
struct usb_transfer_completion_event_data* event) struct usb_transfer_completion_event_data* event)
{ {
int ep = event->endpoint; int ep = event->endpoint;
switch(ep) { switch(ep) {
case EP_CONTROL: case EP_CONTROL:
logf("ctrl handled %ld",current_tick); logf("ctrl handled %ld",current_tick);
@ -346,8 +350,8 @@ void usb_core_handle_transfer_completion(
(struct usb_ctrlrequest*)event->data); (struct usb_ctrlrequest*)event->data);
break; break;
default: default:
if(ep_data[ep].completion_handler != NULL) if(ep_data[ep].completion_handler[event->dir>>7] != NULL)
ep_data[ep].completion_handler(ep,event->in, ep_data[ep].completion_handler[event->dir>>7](ep,event->dir,
event->status,event->length); event->status,event->length);
break; break;
} }
@ -388,34 +392,60 @@ static void usb_core_set_serial_function_id(void)
usb_string_iSerial.wString[0] = hex[id]; usb_string_iSerial.wString[0] = hex[id];
} }
int usb_core_request_endpoint(int dir, struct usb_class_driver *drv)
{
int ret, ep;
ret = usb_drv_request_endpoint(dir);
if (ret == -1)
return -1;
ep = ret & 0x7f;
dir = ret >> 7;
ep_data[ep].completion_handler[dir] = drv->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 >> 7;
ep &= 0x7f;
ep_data[ep].completion_handler[dir] = NULL;
ep_data[ep].control_handler[dir] = NULL;
}
static void allocate_interfaces_and_endpoints(void) static void allocate_interfaces_and_endpoints(void)
{ {
int i,j; int i;
int interface=0; int interface=0;
int endpoint=1;
memset(ep_data,0,sizeof(ep_data)); memset(ep_data,0,sizeof(ep_data));
for(i=0;i<USB_NUM_DRIVERS;i++) { for (i = 0; i < 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) { if(drivers[i].enabled) {
int oldendpoint = endpoint;
drivers[i].first_interface = interface; drivers[i].first_interface = interface;
endpoint = drivers[i].set_first_endpoint(endpoint); if (drivers[i].request_endpoints(&drivers[i])) {
if(endpoint>NUM_ENDPOINTS) {
drivers[i].enabled = false; drivers[i].enabled = false;
continue; continue;
} }
interface = drivers[i].set_first_interface(interface); interface = drivers[i].set_first_interface(interface);
drivers[i].last_interface = interface; drivers[i].last_interface = interface;
for(j=oldendpoint;j<endpoint;j++) {
ep_data[j].completion_handler=drivers[i].transfer_complete;
ep_data[j].control_handler=drivers[i].control_request;
}
}
if(endpoint>NUM_ENDPOINTS) {
drivers[i].enabled = false;
} }
} }
usb_core_num_interfaces = interface; usb_core_num_interfaces = interface;
@ -666,8 +696,8 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
break; break;
default: { default: {
bool handled=false; bool handled=false;
if(ep_data[req->wIndex & 0xf].control_handler != NULL) if(ep_data[req->wIndex & 0xf].control_handler[0] != NULL)
handled = ep_data[req->wIndex & 0xf].control_handler(req); handled = ep_data[req->wIndex & 0xf].control_handler[0](req);
if(!handled) { if(!handled) {
/* nope. flag error */ /* nope. flag error */
logf("usb bad req %d", req->bRequest); logf("usb bad req %d", req->bRequest);
@ -689,7 +719,7 @@ void usb_core_bus_reset(void)
} }
/* called by usb_drv_transfer_completed() */ /* called by usb_drv_transfer_completed() */
void usb_core_transfer_complete(int endpoint, bool in, int status,int length) void usb_core_transfer_complete(int endpoint, int dir, int status,int length)
{ {
switch (endpoint) { switch (endpoint) {
case EP_CONTROL: case EP_CONTROL:
@ -698,7 +728,7 @@ void usb_core_transfer_complete(int endpoint, bool in, int status,int length)
default: default:
ep_data[endpoint].completion_event.endpoint=endpoint; ep_data[endpoint].completion_event.endpoint=endpoint;
ep_data[endpoint].completion_event.in=in; ep_data[endpoint].completion_event.dir=dir;
ep_data[endpoint].completion_event.data=0; ep_data[endpoint].completion_event.data=0;
ep_data[endpoint].completion_event.status=status; ep_data[endpoint].completion_event.status=status;
ep_data[endpoint].completion_event.length=length; ep_data[endpoint].completion_event.length=length;
@ -712,7 +742,7 @@ void usb_core_transfer_complete(int endpoint, bool in, int status,int length)
void usb_core_control_request(struct usb_ctrlrequest* req) void usb_core_control_request(struct usb_ctrlrequest* req)
{ {
ep_data[0].completion_event.endpoint=0; ep_data[0].completion_event.endpoint=0;
ep_data[0].completion_event.in=0; ep_data[0].completion_event.dir=0;
ep_data[0].completion_event.data=(void *)req; ep_data[0].completion_event.data=(void *)req;
ep_data[0].completion_event.status=0; ep_data[0].completion_event.status=0;
ep_data[0].completion_event.length=0; ep_data[0].completion_event.length=0;

View file

@ -72,7 +72,7 @@ static int buffer_start;
static int buffer_length; static int buffer_length;
static bool active = false; static bool active = false;
static int usb_endpoint; static int ep_in, ep_out;
static int usb_interface; static int usb_interface;
static struct mutex sendlock SHAREDBSS_ATTR; static struct mutex sendlock SHAREDBSS_ATTR;
@ -82,22 +82,33 @@ static void sendout(void)
if(buffer_start+buffer_length > BUFFER_SIZE) if(buffer_start+buffer_length > BUFFER_SIZE)
{ {
/* Buffer wraps. Only send the first part */ /* Buffer wraps. Only send the first part */
usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], usb_drv_send_nonblocking(ep_in, &send_buffer[buffer_start],
(BUFFER_SIZE - buffer_start)); (BUFFER_SIZE - buffer_start));
} }
else else
{ {
/* Send everything */ /* Send everything */
usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start], usb_drv_send_nonblocking(ep_in, &send_buffer[buffer_start],
buffer_length); buffer_length);
} }
busy_sending=true; busy_sending=true;
} }
int usb_serial_set_first_endpoint(int endpoint) int usb_serial_request_endpoints(struct usb_class_driver *drv)
{ {
usb_endpoint = endpoint; ep_in = usb_core_request_endpoint(USB_DIR_IN, drv);
return endpoint + 1;
if (ep_in < 0)
return -1;
ep_out = usb_core_request_endpoint(USB_DIR_OUT, drv);
if (ep_out < 0) {
usb_core_release_endpoint(ep_in);
return -1;
}
return 0;
} }
int usb_serial_set_first_interface(int interface) int usb_serial_set_first_interface(int interface)
@ -117,11 +128,11 @@ int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size)
memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor));
dest+=sizeof(struct usb_interface_descriptor); dest+=sizeof(struct usb_interface_descriptor);
endpoint_descriptor.bEndpointAddress = usb_endpoint | USB_DIR_IN; endpoint_descriptor.bEndpointAddress = ep_in;
memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor));
dest+=sizeof(struct usb_endpoint_descriptor); dest+=sizeof(struct usb_endpoint_descriptor);
endpoint_descriptor.bEndpointAddress = usb_endpoint | USB_DIR_OUT; endpoint_descriptor.bEndpointAddress = ep_out;
memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor));
dest+=sizeof(struct usb_endpoint_descriptor); dest+=sizeof(struct usb_endpoint_descriptor);
@ -131,7 +142,7 @@ int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size)
void usb_serial_init_connection(void) void usb_serial_init_connection(void)
{ {
/* prime rx endpoint */ /* prime rx endpoint */
usb_drv_recv(usb_endpoint, receive_buffer, sizeof receive_buffer); usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
/* we come here too after a bus reset, so reset some data */ /* we come here too after a bus reset, so reset some data */
mutex_lock(&sendlock); mutex_lock(&sendlock);
@ -202,17 +213,17 @@ void usb_serial_send(unsigned char *data,int length)
} }
/* called by usb_core_transfer_complete() */ /* called by usb_core_transfer_complete() */
void usb_serial_transfer_complete(int ep,bool in, int status, int length) void usb_serial_transfer_complete(int ep,int dir, int status, int length)
{ {
(void)ep; (void)ep;
switch (in) { switch (dir) {
case false: case USB_DIR_OUT:
logf("serial: %s", receive_buffer); logf("serial: %s", receive_buffer);
/* Data received. TODO : Do something with it ? */ /* Data received. TODO : Do something with it ? */
usb_drv_recv(usb_endpoint, receive_buffer, sizeof receive_buffer); usb_drv_recv(ep_out, receive_buffer, sizeof receive_buffer);
break; break;
case true: case USB_DIR_IN:
mutex_lock(&sendlock); mutex_lock(&sendlock);
/* Data sent out. Update circular buffer */ /* Data sent out. Update circular buffer */
if(status == 0) if(status == 0)

View file

@ -23,13 +23,13 @@
#include "usb_ch9.h" #include "usb_ch9.h"
int usb_serial_set_first_endpoint(int endpoint); int usb_serial_request_endpoints(struct usb_class_driver *);
int usb_serial_set_first_interface(int interface); int usb_serial_set_first_interface(int interface);
int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size); int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size);
void usb_serial_init_connection(void); void usb_serial_init_connection(void);
void usb_serial_init(void); void usb_serial_init(void);
void usb_serial_disconnect(void); void usb_serial_disconnect(void);
void usb_serial_transfer_complete(int ep,bool in, int status, int length); void usb_serial_transfer_complete(int ep,int dir, int status, int length);
bool usb_serial_control_request(struct usb_ctrlrequest* req); bool usb_serial_control_request(struct usb_ctrlrequest* req);
void usb_serial_send(unsigned char *data,int length); void usb_serial_send(unsigned char *data,int length);

View file

@ -22,7 +22,7 @@
#include "system.h" #include "system.h"
#include "usb_core.h" #include "usb_core.h"
#include "usb_drv.h" #include "usb_drv.h"
//#define LOGF_ENABLE #define LOGF_ENABLE
#include "logf.h" #include "logf.h"
#include "ata.h" #include "ata.h"
#include "hotswap.h" #include "hotswap.h"
@ -263,8 +263,8 @@ static void identify2inquiry(int lun);
static void send_and_read_next(void); static void send_and_read_next(void);
static bool ejected[NUM_VOLUMES]; static bool ejected[NUM_VOLUMES];
static int usb_endpoint;
static int usb_interface; static int usb_interface;
static int ep_in, ep_out;
static enum { static enum {
WAITING_FOR_COMMAND, WAITING_FOR_COMMAND,
@ -321,7 +321,7 @@ void usb_storage_reconnect(void)
&& usb_inserted()) { && usb_inserted()) {
for(i=0;i<NUM_VOLUMES;i++) for(i=0;i<NUM_VOLUMES;i++)
ejected[i] = !check_disk_present(IF_MV(i)); ejected[i] = !check_disk_present(IF_MV(i));
logf("%s", __func__);
usb_request_exclusive_ata(); usb_request_exclusive_ata();
} }
} }
@ -336,12 +336,23 @@ void usb_storage_init(void)
logf("usb_storage_init done"); logf("usb_storage_init done");
} }
int usb_storage_request_endpoints(struct usb_class_driver *drv)
int usb_storage_set_first_endpoint(int endpoint)
{ {
usb_endpoint = endpoint; ep_in = usb_core_request_endpoint(USB_DIR_IN, drv);
return endpoint + 1;
if (ep_in < 0)
return -1;
ep_out = usb_core_request_endpoint(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) int usb_storage_set_first_interface(int interface)
{ {
usb_interface = interface; usb_interface = interface;
@ -357,12 +368,12 @@ int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size)
sizeof(struct usb_interface_descriptor)); sizeof(struct usb_interface_descriptor));
dest+=sizeof(struct usb_interface_descriptor); dest+=sizeof(struct usb_interface_descriptor);
endpoint_descriptor.bEndpointAddress = usb_endpoint | USB_DIR_IN; endpoint_descriptor.bEndpointAddress = ep_in;
memcpy(dest,&endpoint_descriptor, memcpy(dest,&endpoint_descriptor,
sizeof(struct usb_endpoint_descriptor)); sizeof(struct usb_endpoint_descriptor));
dest+=sizeof(struct usb_endpoint_descriptor); dest+=sizeof(struct usb_endpoint_descriptor);
endpoint_descriptor.bEndpointAddress = usb_endpoint | USB_DIR_OUT; endpoint_descriptor.bEndpointAddress = ep_out;
memcpy(dest,&endpoint_descriptor, memcpy(dest,&endpoint_descriptor,
sizeof(struct usb_endpoint_descriptor)); sizeof(struct usb_endpoint_descriptor));
@ -376,7 +387,8 @@ void usb_storage_init_connection(void)
/* prime rx endpoint. We only need room for commands */ /* prime rx endpoint. We only need room for commands */
state = WAITING_FOR_COMMAND; state = WAITING_FOR_COMMAND;
#if CONFIG_CPU == IMX31L || CONFIG_USBOTG == USBOTG_ISP1583 #if CONFIG_CPU == IMX31L || CONFIG_USBOTG == USBOTG_ISP1583 || \
defined(CPU_TCC77X) || defined(CPU_TCC780X)
static unsigned char _transfer_buffer[BUFFER_SIZE*2] static unsigned char _transfer_buffer[BUFFER_SIZE*2]
USBDEVBSS_ATTR __attribute__((aligned(32))); USBDEVBSS_ATTR __attribute__((aligned(32)));
tb.transfer_buffer = (void *)_transfer_buffer; tb.transfer_buffer = (void *)_transfer_buffer;
@ -390,11 +402,11 @@ void usb_storage_init_connection(void)
(void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0); (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0);
invalidate_icache(); invalidate_icache();
#endif #endif
usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); usb_drv_recv(ep_out, tb.transfer_buffer, 1024);
} }
/* called by usb_core_transfer_complete() */ /* called by usb_core_transfer_complete() */
void usb_storage_transfer_complete(int ep,bool in,int status,int length) void usb_storage_transfer_complete(int ep,int dir,int status,int length)
{ {
(void)ep; (void)ep;
struct command_block_wrapper* cbw = (void*)tb.transfer_buffer; struct command_block_wrapper* cbw = (void*)tb.transfer_buffer;
@ -402,7 +414,7 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
//logf("transfer result %X %d", status, length); //logf("transfer result %X %d", status, length);
switch(state) { switch(state) {
case RECEIVING_BLOCKS: case RECEIVING_BLOCKS:
if(in==true) { if(dir==USB_DIR_IN) {
logf("IN received in RECEIVING"); logf("IN received in RECEIVING");
} }
logf("scsi write %d %d", cur_cmd.sector, cur_cmd.count); logf("scsi write %d %d", cur_cmd.sector, cur_cmd.count);
@ -470,7 +482,7 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
} }
break; break;
case WAITING_FOR_COMMAND: case WAITING_FOR_COMMAND:
if(in==true) { if(dir==USB_DIR_IN) {
logf("IN received in WAITING_FOR_COMMAND"); logf("IN received in WAITING_FOR_COMMAND");
} }
//logf("command received"); //logf("command received");
@ -478,20 +490,20 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
handle_scsi(cbw); handle_scsi(cbw);
} }
else { else {
usb_drv_stall(usb_endpoint, true,true); usb_drv_stall(ep_in, true,true);
usb_drv_stall(usb_endpoint, true,false); usb_drv_stall(ep_out, true,false);
} }
break; break;
case SENDING_CSW: case SENDING_CSW:
if(in==false) { if(dir==USB_DIR_OUT) {
logf("OUT received in SENDING_CSW"); logf("OUT received in SENDING_CSW");
} }
//logf("csw sent, now go back to idle"); //logf("csw sent, now go back to idle");
state = WAITING_FOR_COMMAND; state = WAITING_FOR_COMMAND;
usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); usb_drv_recv(ep_out, tb.transfer_buffer, 1024);
break; break;
case SENDING_RESULT: case SENDING_RESULT:
if(in==false) { if(dir==USB_DIR_OUT) {
logf("OUT received in SENDING"); logf("OUT received in SENDING");
} }
if(status==0) { if(status==0) {
@ -509,13 +521,13 @@ void usb_storage_transfer_complete(int ep,bool in,int status,int length)
} }
break; break;
case SENDING_FAILED_RESULT: case SENDING_FAILED_RESULT:
if(in==false) { if(dir==USB_DIR_OUT) {
logf("OUT received in SENDING"); logf("OUT received in SENDING");
} }
send_csw(UMS_STATUS_FAIL); send_csw(UMS_STATUS_FAIL);
break; break;
case SENDING_BLOCKS: case SENDING_BLOCKS:
if(in==false) { if(dir==USB_DIR_OUT) {
logf("OUT received in SENDING"); logf("OUT received in SENDING");
} }
if(status==0) { if(status==0) {
@ -567,8 +579,8 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req)
data toggle bits and endpoint STALL conditions despite data toggle bits and endpoint STALL conditions despite
the Bulk-Only Mass Storage Reset. */ the Bulk-Only Mass Storage Reset. */
#if 0 #if 0
usb_drv_reset_endpoint(usb_endpoint, false); usb_drv_reset_endpoint(ep_in, false);
usb_drv_reset_endpoint(usb_endpoint, true); usb_drv_reset_endpoint(ep_out, true);
#endif #endif
usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
@ -972,7 +984,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
default: default:
logf("scsi unknown cmd %x",cbw->command_block[0x0]); logf("scsi unknown cmd %x",cbw->command_block[0x0]);
usb_drv_stall(usb_endpoint, true,true); usb_drv_stall(ep_in, true,true);
send_csw(UMS_STATUS_FAIL); send_csw(UMS_STATUS_FAIL);
break; break;
} }
@ -980,25 +992,25 @@ static void handle_scsi(struct command_block_wrapper* cbw)
static void send_block_data(void *data,int size) static void send_block_data(void *data,int size)
{ {
usb_drv_send_nonblocking(usb_endpoint, data,size); usb_drv_send_nonblocking(ep_in, data,size);
state = SENDING_BLOCKS; state = SENDING_BLOCKS;
} }
static void send_command_result(void *data,int size) static void send_command_result(void *data,int size)
{ {
usb_drv_send_nonblocking(usb_endpoint, data,size); usb_drv_send_nonblocking(ep_in, data,size);
state = SENDING_RESULT; state = SENDING_RESULT;
} }
static void send_command_failed_result(void) static void send_command_failed_result(void)
{ {
usb_drv_send_nonblocking(usb_endpoint, NULL, 0); usb_drv_send_nonblocking(ep_in, NULL, 0);
state = SENDING_FAILED_RESULT; state = SENDING_FAILED_RESULT;
} }
static void receive_block_data(void *data,int size) static void receive_block_data(void *data,int size)
{ {
usb_drv_recv(usb_endpoint, data, size); usb_drv_recv(ep_out, data, size);
state = RECEIVING_BLOCKS; state = RECEIVING_BLOCKS;
} }
@ -1009,7 +1021,7 @@ static void send_csw(int status)
tb.csw->data_residue = 0; tb.csw->data_residue = 0;
tb.csw->status = status; tb.csw->status = status;
usb_drv_send_nonblocking(usb_endpoint, tb.csw, usb_drv_send_nonblocking(ep_in, tb.csw,
sizeof(struct command_status_wrapper)); sizeof(struct command_status_wrapper));
state = SENDING_CSW; state = SENDING_CSW;
//logf("CSW: %X",status); //logf("CSW: %X",status);

View file

@ -23,12 +23,12 @@
#include "usb_ch9.h" #include "usb_ch9.h"
int usb_storage_set_first_endpoint(int endpoint); int usb_storage_request_endpoints(struct usb_class_driver *);
int usb_storage_set_first_interface(int interface); int usb_storage_set_first_interface(int interface);
int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size); int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size);
void usb_storage_init_connection(void); void usb_storage_init_connection(void);
void usb_storage_init(void); void usb_storage_init(void);
void usb_storage_transfer_complete(int ep,bool in,int state,int length); void usb_storage_transfer_complete(int ep,int dir,int state,int length);
bool usb_storage_control_request(struct usb_ctrlrequest* req); bool usb_storage_control_request(struct usb_ctrlrequest* req);
#ifdef HAVE_HOTSWAP #ifdef HAVE_HOTSWAP
void usb_storage_notify_hotswap(int volume,bool inserted); void usb_storage_notify_hotswap(int volume,bool inserted);