summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/usb_core.c')
-rw-r--r--firmware/usbstack/usb_core.c750
1 files changed, 373 insertions, 377 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 96a5994..ff54e42 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -27,6 +27,7 @@
#include "usb_ch9.h"
#include "usb_drv.h"
#include "usb_core.h"
+#include "usb_class_driver.h"
#if defined(USB_STORAGE)
#include "usb_storage.h"
@@ -36,7 +37,7 @@
#include "usb_serial.h"
#endif
-/* TODO: Move this target-specific stuff somewhere else (serial number reading) */
+/* TODO: Move target-specific stuff somewhere else (serial number reading) */
#ifdef HAVE_AS3514
#include "i2c-pp.h"
@@ -54,7 +55,9 @@
#define USB_SC_SCSI 0x06 /* Transparent */
#define USB_PROT_BULK 0x50 /* bulk only */
-static const struct usb_device_descriptor __attribute__((aligned(2))) device_descriptor= {
+static const struct usb_device_descriptor __attribute__((aligned(2)))
+ device_descriptor=
+{
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = USB_DT_DEVICE,
#ifdef USE_HIGH_SPEED
@@ -75,7 +78,8 @@ static const struct usb_device_descriptor __attribute__((aligned(2))) device_des
.bNumConfigurations = 1
} ;
-struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor =
+static struct usb_config_descriptor __attribute__((aligned(2)))
+ config_descriptor =
{
.bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG,
@@ -89,7 +93,8 @@ struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor =
#ifdef USB_CHARGING_ONLY
/* dummy interface for charging-only */
-struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_descriptor =
+static struct usb_interface_descriptor __attribute__((aligned(2)))
+ charging_interface_descriptor =
{
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
@@ -103,77 +108,8 @@ struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_d
};
#endif
-#ifdef USB_STORAGE
-/* storage interface */
-struct usb_interface_descriptor __attribute__((aligned(2))) mass_storage_interface_descriptor =
-{
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,
- .bInterfaceSubClass = USB_SC_SCSI,
- .bInterfaceProtocol = USB_PROT_BULK,
- .iInterface = 0
-};
-
-struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_in_descriptor =
-{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 16,
- .bInterval = 0
-};
-struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_out_descriptor =
-{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 16,
- .bInterval = 0
-};
-#endif
-
-#ifdef USB_SERIAL
-/* serial interface */
-struct usb_interface_descriptor __attribute__((aligned(2))) serial_interface_descriptor =
-{
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = 0
-};
-
-struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_in_descriptor =
-{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_SERIAL | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 16,
- .bInterval = 0
-};
-struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_out_descriptor =
-{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_SERIAL | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 16,
- .bInterval = 0
-};
-#endif
-
-static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifier_descriptor =
+static const struct usb_qualifier_descriptor __attribute__((aligned(2)))
+ qualifier_descriptor =
{
.bLength = sizeof(struct usb_qualifier_descriptor),
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
@@ -185,21 +121,26 @@ static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifi
.bNumConfigurations = 1
};
-static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iManufacturer =
+static struct usb_string_descriptor __attribute__((aligned(2)))
+ usb_string_iManufacturer =
{
24,
USB_DT_STRING,
{'R','o','c','k','b','o','x','.','o','r','g'}
};
-static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iProduct =
+static struct usb_string_descriptor __attribute__((aligned(2)))
+ usb_string_iProduct =
{
42,
USB_DT_STRING,
- {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
+ {'R','o','c','k','b','o','x',' ',
+ 'm','e','d','i','a',' ',
+ 'p','l','a','y','e','r'}
};
-static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSerial =
+static struct usb_string_descriptor __attribute__((aligned(2)))
+ usb_string_iSerial =
{
84,
USB_DT_STRING,
@@ -211,14 +152,16 @@ static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSeri
/* Generic for all targets */
/* this is stringid #0: languages supported */
-static struct usb_string_descriptor __attribute__((aligned(2))) lang_descriptor =
+static struct usb_string_descriptor __attribute__((aligned(2)))
+ lang_descriptor =
{
4,
USB_DT_STRING,
{0x0409} /* LANGID US English */
};
-static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_charging_only =
+static struct usb_string_descriptor __attribute__((aligned(2)))
+ usb_string_charging_only =
{
28,
USB_DT_STRING,
@@ -238,14 +181,56 @@ static int usb_address = 0;
static bool initialized = false;
static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state;
+static int usb_core_num_interfaces;
+
+int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size,
+ int interface_number,int endpoint);
+
+struct usb_class_driver drivers[] =
+{
#ifdef USB_STORAGE
-static bool usb_core_storage_enabled = false;
+ [USB_DRIVER_MASS_STORAGE] = {
+ .enabled = false,
+ .needs_exclusive_ata = true,
+ .usb_endpoint = 0,
+ .usb_interface = 0,
+ .get_config_descriptor = usb_storage_get_config_descriptor,
+ .init_connection = usb_storage_init_connection,
+ .init = usb_storage_init,
+ .disconnect = NULL,
+ .transfer_complete = usb_storage_transfer_complete,
+ .control_request = usb_storage_control_request
+ },
+#endif
+#ifdef USB_SERIAL
+ [USB_DRIVER_SERIAL] = {
+ .enabled = false,
+ .needs_exclusive_ata = false,
+ .usb_endpoint = 0,
+ .usb_interface = 0,
+ .get_config_descriptor = usb_serial_get_config_descriptor,
+ .init_connection = usb_serial_init_connection,
+ .init = usb_serial_init,
+ .disconnect = usb_serial_disconnect,
+ .transfer_complete = usb_serial_transfer_complete,
+ .control_request = usb_serial_control_request
+ },
#endif
-/* Next one is non-static, to enable setting it from the debug menu */
-bool usb_core_serial_enabled = false;
#ifdef USB_CHARGING_ONLY
-static bool usb_core_charging_enabled = false;
+ [USB_DRIVER_CHARGING_ONLY] = {
+ .enabled = false,
+ .needs_exclusive_ata = false,
+ .usb_endpoint = 0,
+ .usb_interface = 0,
+ .get_config_descriptor = usb_charging_get_config_descriptor,
+ .init_connection = NULL,
+ .init = NULL,
+ .disconnect = NULL,
+ .transfer_complete = NULL,
+ .control_request = NULL
+ },
#endif
+};
static void usb_core_control_request_handler(struct usb_ctrlrequest* req);
static int ack_control(struct usb_ctrlrequest* req);
@@ -272,11 +257,9 @@ static void set_serial_descriptor(void)
uint32_t x;
int i,j;
- for (i = 0; i < 2; i++)
- {
+ for (i = 0; i < 2; i++) {
x = serial[i];
- for (j=0;j<8;j++)
- {
+ for (j=0;j<8;j++) {
*p-- = hex[x & 0xf];
x >>= 4;
}
@@ -292,8 +275,7 @@ static void set_serial_descriptor(void)
int i;
i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial);
- for (i = 0; i < 16; i++)
- {
+ for (i = 0; i < 16; i++) {
*p++ = hex[(serial[i] >> 4) & 0xF];
*p++ = hex[(serial[i] >> 0) & 0xF];
}
@@ -309,8 +291,7 @@ static void set_serial_descriptor(void)
unsigned short x;
int i;
- for (i = 10; i < 20; i++)
- {
+ for (i = 10; i < 20; i++) {
x = identify[i];
*p++ = hex[(x >> 12) & 0xF];
*p++ = hex[(x >> 8) & 0xF];
@@ -323,6 +304,7 @@ static void set_serial_descriptor(void)
void usb_core_init(void)
{
+ int i;
if (initialized)
return;
@@ -333,27 +315,34 @@ void usb_core_init(void)
/* class driver init functions should be safe to call even if the driver
* won't be used. This simplifies other logic (i.e. we don't need to know
* yet which drivers will be enabled */
-#ifdef USB_STORAGE
- if(usb_core_storage_enabled)
- usb_storage_init();
-#endif
-
-#ifdef USB_SERIAL
- if(usb_core_serial_enabled)
- usb_serial_init();
-#endif
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled && drivers[i].init != NULL)
+ drivers[i].init();
+ }
initialized = true;
usb_state = DEFAULT;
logf("usb_core_init() finished");
}
+int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size,
+ int interface_number,int endpoint)
+{
+ (void) max_packet_size;
+ (void) endpoint;
+ charging_interface_descriptor.bInterfaceNumber=interface_number;
+ memcpy(dest,&charging_interface_descriptor,
+ sizeof(struct usb_interface_descriptor));
+ return sizeof(struct usb_interface_descriptor);
+}
+
void usb_core_exit(void)
{
-#ifdef USB_SERIAL
- if(usb_core_serial_enabled)
- usb_serial_exit();
-#endif
+ int i;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled && drivers[i].disconnect != NULL)
+ drivers[i].disconnect ();
+ }
if (initialized) {
usb_drv_exit();
@@ -362,321 +351,332 @@ void usb_core_exit(void)
logf("usb_core_exit() finished");
}
-void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event)
+void usb_core_handle_transfer_completion(
+ struct usb_transfer_completion_event_data* event)
{
+ int i;
switch(event->endpoint) {
case EP_CONTROL:
logf("ctrl handled %ld",current_tick);
- usb_core_control_request_handler((struct usb_ctrlrequest*)event->data);
- break;
-#ifdef USB_STORAGE
- case EP_MASS_STORAGE:
- usb_storage_transfer_complete(event->in,event->status,event->length);
+ usb_core_control_request_handler(
+ (struct usb_ctrlrequest*)event->data);
break;
-#endif
-#ifdef USB_SERIAL
- case EP_SERIAL:
- usb_serial_transfer_complete(event->in,event->status,event->length);
- break;
-#endif
-#ifdef USB_CHARGING_ONLY
- case EP_CHARGING_ONLY:
+ default:
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].usb_endpoint == event->endpoint &&
+ drivers[i].transfer_complete != NULL)
+ {
+ drivers[i].transfer_complete(event->in,
+ event->status,event->length);
+ break;
+ }
+ }
break;
-#endif
}
}
-void usb_core_enable_protocol(int driver,bool enabled)
+void usb_core_enable_driver(int driver,bool enabled)
{
- switch(driver) {
-#ifdef USB_STORAGE
- case USB_DRIVER_MASS_STORAGE:
- usb_core_storage_enabled = enabled;
- break;
-#endif
-#ifdef USB_SERIAL
- case USB_DRIVER_SERIAL:
- usb_core_serial_enabled = enabled;
- break;
-#endif
-#ifdef USB_CHARGING_ONLY
- case USB_DRIVER_CHARGING_ONLY:
- usb_core_charging_enabled = enabled;
- break;
-#endif
+ drivers[driver].enabled = enabled;
+}
+
+bool usb_core_driver_enabled(int driver)
+{
+ return drivers[driver].enabled;
+}
+
+static void usb_core_set_serial_function_id(void)
+{
+ int id = 0;
+ int i;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled)
+ id |= 1<<i;
}
+ usb_string_iSerial.wString[0] = hex[id];
}
-static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
+static void allocate_interfaces_and_endpoints(void)
{
- if(usb_state == DEFAULT) {
- set_serial_descriptor();
-
- int serial_function_id = 0;
-#ifdef USB_STORAGE
- if(usb_core_storage_enabled) {
- usb_request_exclusive_ata();
- serial_function_id |= 1;
+ int i;
+ int interface=0;
+ int endpoint=1;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled) {
+ drivers[i].usb_endpoint = endpoint++;
+ drivers[i].usb_interface = interface++;
+ }
+ if(endpoint>NUM_ENDPOINTS) {
+ drivers[i].enabled = false;
}
-#endif
-#ifdef USB_SERIAL
- if(usb_core_serial_enabled)
- serial_function_id |= 2;
-#endif
- usb_string_iSerial.wString[0] = hex[serial_function_id];
}
+ usb_core_num_interfaces = interface;
+}
- switch (req->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- logf("usb_core: SET_CONFIG");
- usb_drv_cancel_all_transfers();
- if (req->wValue){
- usb_state = CONFIGURED;
-#ifdef USB_STORAGE
- if(usb_core_storage_enabled)
- usb_storage_control_request(req);
-#endif
+static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
+{
+ int i;
+ if(usb_state == DEFAULT) {
+ set_serial_descriptor();
+ usb_core_set_serial_function_id();
-#ifdef USB_SERIAL
- if(usb_core_serial_enabled)
- usb_serial_control_request(req);
-#endif
- }
- else {
- usb_state = ADDRESS;
- }
- ack_control(req);
- break;
+ allocate_interfaces_and_endpoints();
- case USB_REQ_GET_CONFIGURATION: {
- logf("usb_core: GET_CONFIG");
- if (usb_state == ADDRESS)
- response_data[0] = 0;
- else
- response_data[0] = 1;
- if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0)
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].needs_exclusive_ata) {
+ usb_request_exclusive_ata();
break;
- ack_control(req);
- break;
+ }
}
+ }
- case USB_REQ_SET_INTERFACE:
- logf("usb_core: SET_INTERFACE");
- ack_control(req);
- break;
+ switch(req->bRequestType & 0x1f) {
+ case 0: /* Device */
+ switch (req->bRequest) {
+ case USB_REQ_GET_CONFIGURATION: {
+ logf("usb_core: GET_CONFIG");
+ if (usb_state == ADDRESS)
+ response_data[0] = 0;
+ else
+ response_data[0] = 1;
+ if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0)
+ break;
+ ack_control(req);
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ logf("usb_core: SET_CONFIG");
+ usb_drv_cancel_all_transfers();
+ if (req->wValue) {
+ usb_state = CONFIGURED;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].init_connection!=NULL)
+ {
+ drivers[i].init_connection(
+ drivers[i].usb_interface,
+ drivers[i].usb_endpoint);
+ }
+ }
+ }
+ else {
+ usb_state = ADDRESS;
+ }
+ ack_control(req);
+ break;
+ }
+ case USB_REQ_SET_ADDRESS: {
+ unsigned char address = req->wValue;
+ logf("usb_core: SET_ADR %d", address);
+ if(ack_control(req)!=0)
+ break;
+ usb_drv_cancel_all_transfers();
+ usb_address = address;
+ usb_drv_set_address(usb_address);
+ usb_state = ADDRESS;
+ break;
+ }
+ case USB_REQ_GET_DESCRIPTOR: {
+ int index = req->wValue & 0xff;
+ int length = req->wLength;
+ int size;
+ const void* ptr = NULL;
+ logf("usb_core: GET_DESC %d", req->wValue >> 8);
+
+ switch (req->wValue >> 8) { /* type */
+ case USB_DT_DEVICE:
+ ptr = &device_descriptor;
+ size = sizeof(struct usb_device_descriptor);
+ break;
+
+ case USB_DT_OTHER_SPEED_CONFIG:
+ case USB_DT_CONFIG: {
+ int max_packet_size;
+
+ if(req->wValue >> 8 == USB_DT_CONFIG) {
+ if(usb_drv_port_speed())
+ max_packet_size=512;
+ else
+ max_packet_size=64;
+ config_descriptor.bDescriptorType=USB_DT_CONFIG;
+ }
+ else {
+ if(usb_drv_port_speed())
+ max_packet_size=64;
+ else
+ max_packet_size=512;
+ config_descriptor.bDescriptorType =
+ USB_DT_OTHER_SPEED_CONFIG;
+ }
+ size = sizeof(struct usb_config_descriptor);
+
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].get_config_descriptor)
+ {
+ size+=drivers[i].get_config_descriptor(
+ &response_data[size],
+ max_packet_size,
+ drivers[i].usb_interface,
+ drivers[i].usb_endpoint);
+ }
+ }
+ config_descriptor.bNumInterfaces =
+ usb_core_num_interfaces;
+ config_descriptor.wTotalLength = size;
+ memcpy(&response_data[0],&config_descriptor,
+ sizeof(struct usb_config_descriptor));
+
+ ptr = response_data;
+ break;
+ }
- case USB_REQ_GET_INTERFACE:
- logf("usb_core: GET_INTERFACE");
- response_data[0] = 0;
- if(usb_drv_send(EP_CONTROL, response_data, 1)!=0)
- break;
- ack_control(req);
- break;
- case USB_REQ_CLEAR_FEATURE:
- logf("usb_core: CLEAR_FEATURE");
- if (req->wValue)
- usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0);
- else
- usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0);
- ack_control(req);
- break;
+ case USB_DT_STRING:
+ logf("STRING %d",index);
+ if ((unsigned)index < (sizeof(usb_strings)/
+ sizeof(struct usb_string_descriptor*)))
+ {
+ size = usb_strings[index]->bLength;
+ memcpy(&response_data[0],usb_strings[index],
+ size);
+ ptr = response_data;
+ }
+ else {
+ logf("bad string id %d", index);
+ usb_drv_stall(EP_CONTROL, true,true);
+ }
+ break;
+
+ case USB_DT_DEVICE_QUALIFIER:
+ ptr = &qualifier_descriptor;
+ size = sizeof (struct usb_qualifier_descriptor);
+ break;
+
+ default:
+ logf("bad desc %d", req->wValue >> 8);
+ usb_drv_stall(EP_CONTROL, true,true);
+ break;
+ }
- case USB_REQ_SET_FEATURE:
- logf("usb_core: SET_FEATURE");
- switch(req->bRequestType & 0x0f){
- case 0: /* Device */
+ if (ptr) {
+ unsigned char *uncached = (void*)UNCACHED_ADDR(ptr);
+ length = MIN(size, length);
+ if(usb_drv_send(EP_CONTROL, uncached, length)!=0)
+ break;
+ }
+ ack_control(req);
+ break;
+ } /* USB_REQ_GET_DESCRIPTOR */
+ case USB_REQ_CLEAR_FEATURE:
+ break;
+ case USB_REQ_SET_FEATURE:
if(req->wValue == 2) { /* TEST_MODE */
int mode=req->wIndex>>8;
ack_control(req);
usb_drv_set_test_mode(mode);
}
break;
- case 2: /* Endpoint */
- if (req->wValue)
- usb_drv_stall(req->wIndex & 0xf, true,(req->wIndex & 0x80) !=0);
- else
- usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0);
+ case USB_REQ_GET_STATUS:
+ response_data[0]= 0;
+ response_data[1]= 0;
+ if(usb_drv_send(EP_CONTROL, response_data, 2)!=0)
+ break;
ack_control(req);
break;
default:
break;
}
break;
-
- case USB_REQ_SET_ADDRESS: {
- unsigned char address = req->wValue;
- logf("usb_core: SET_ADR %d", address);
- if(ack_control(req)!=0)
- break;
- usb_drv_cancel_all_transfers();
- usb_address = address;
- usb_drv_set_address(usb_address);
- usb_state = ADDRESS;
- break;
- }
-
- case USB_REQ_GET_STATUS: {
- response_data[0]= 0;
- response_data[1]= 0;
- logf("usb_core: GET_STATUS");
- if(req->wIndex>0) {
- if(usb_drv_stalled(req->wIndex&0xf,(req->wIndex&0x80)!=0))
- response_data[0] = 1;
- }
- logf("usb_core: %X %X",response_data[0],response_data[1]);
- if(usb_drv_send(EP_CONTROL, response_data, 2)!=0)
- break;
- ack_control(req);
- break;
- }
-
- case USB_REQ_GET_DESCRIPTOR: {
- int index = req->wValue & 0xff;
- int length = req->wLength;
- int size;
- const void* ptr = NULL;
- logf("usb_core: GET_DESC %d", req->wValue >> 8);
-
- switch (req->wValue >> 8) { /* type */
- case USB_DT_DEVICE:
- ptr = &device_descriptor;
- size = sizeof(struct usb_device_descriptor);
+ case 1: /* Interface */
+ switch (req->bRequest) {
+ case USB_REQ_SET_INTERFACE:
+ logf("usb_core: SET_INTERFACE");
+ ack_control(req);
break;
- case USB_DT_OTHER_SPEED_CONFIG:
- case USB_DT_CONFIG: {
- int max_packet_size;
- int interface_number=0;
-
- if(req->wValue >> 8 == USB_DT_CONFIG) {
- if(usb_drv_port_speed()) {
- max_packet_size=512;
- }
- else {
- max_packet_size=64;
- }
- config_descriptor.bDescriptorType=USB_DT_CONFIG;
- }
- else {
- if(usb_drv_port_speed()) {
- max_packet_size=64;
- }
- else {
- max_packet_size=512;
- }
- config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG;
- }
- size = sizeof(struct usb_config_descriptor);
-
-#ifdef USB_STORAGE
- if(usb_core_storage_enabled){
- mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size;
- mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size;
- mass_storage_interface_descriptor.bInterfaceNumber=interface_number;
- interface_number++;
-
- memcpy(&response_data[size],&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor));
- size += sizeof(struct usb_interface_descriptor);
- memcpy(&response_data[size],&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor));
- size += sizeof(struct usb_endpoint_descriptor);
- memcpy(&response_data[size],&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor));
- size += sizeof(struct usb_endpoint_descriptor);
- }
-#endif
-#ifdef USB_SERIAL
- if(usb_core_serial_enabled){
- serial_ep_in_descriptor.wMaxPacketSize=max_packet_size;
- serial_ep_out_descriptor.wMaxPacketSize=max_packet_size;
- serial_interface_descriptor.bInterfaceNumber=interface_number;
- interface_number++;
-
- memcpy(&response_data[size],&serial_interface_descriptor,sizeof(struct usb_interface_descriptor));
- size += sizeof(struct usb_interface_descriptor);
- memcpy(&response_data[size],&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor));
- size += sizeof(struct usb_endpoint_descriptor);
- memcpy(&response_data[size],&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor));
- size += sizeof(struct usb_endpoint_descriptor);
- }
-#endif
-#ifdef USB_CHARGING_ONLY
- if(usb_core_charging_enabled && interface_number == 0){
- charging_interface_descriptor.bInterfaceNumber=interface_number;
- interface_number++;
- memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor));
- size += sizeof(struct usb_interface_descriptor);
- }
-#endif
- config_descriptor.bNumInterfaces=interface_number;
- config_descriptor.wTotalLength = size;
- memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor));
-
- ptr = response_data;
+ case USB_REQ_GET_INTERFACE:
+ logf("usb_core: GET_INTERFACE");
+ response_data[0] = 0;
+ if(usb_drv_send(EP_CONTROL, response_data, 1)!=0)
+ break;
+ ack_control(req);
break;
+ case USB_REQ_CLEAR_FEATURE:
+ break;
+ case USB_REQ_SET_FEATURE:
+ break;
+ case USB_REQ_GET_STATUS:
+ response_data[0]= 0;
+ response_data[1]= 0;
+ if(usb_drv_send(EP_CONTROL, response_data, 2)!=0)
+ break;
+ ack_control(req);
+ break;
+ default: {
+ bool handled=false;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].control_request &&
+ drivers[i].usb_interface == (req->wIndex))
+ {
+ handled = drivers[i].control_request(req);
+ }
}
-
- case USB_DT_STRING:
- logf("STRING %d",index);
- if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
- size = usb_strings[index]->bLength;
- memcpy(&response_data[0],usb_strings[index],size);
- ptr = response_data;
- }
- else {
- logf("bad string id %d", index);
+ if(!handled) {
+ /* nope. flag error */
+ logf("usb bad req %d", req->bRequest);
usb_drv_stall(EP_CONTROL, true,true);
+ ack_control(req);
}
break;
-
- case USB_DT_DEVICE_QUALIFIER:
- ptr = &qualifier_descriptor;
- size = sizeof (struct usb_qualifier_descriptor);
+ }
+ }
+ break;
+ case 2: /* Endpoint */
+ switch (req->bRequest) {
+ case USB_REQ_CLEAR_FEATURE:
+ if (req->wValue == 0 ) /* ENDPOINT_HALT */
+ usb_drv_stall(req->wIndex & 0xf, false,
+ (req->wIndex & 0x80) !=0);
+ ack_control(req);
break;
-
- default:
- logf("bad desc %d", req->wValue >> 8);
- usb_drv_stall(EP_CONTROL, true,true);
+ case USB_REQ_SET_FEATURE:
+ if (req->wValue == 0 ) /* ENDPOINT_HALT */
+ usb_drv_stall(req->wIndex & 0xf, true,
+ (req->wIndex & 0x80) !=0);
+ ack_control(req);
break;
- }
-
- if (ptr) {
- length = MIN(size, length);
- if(usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length)!=0)
+ case USB_REQ_GET_STATUS:
+ response_data[0]= 0;
+ response_data[1]= 0;
+ logf("usb_core: GET_STATUS");
+ if(req->wIndex>0)
+ response_data[0] = usb_drv_stalled(req->wIndex&0xf,
+ (req->wIndex&0x80)!=0);
+ if(usb_drv_send(EP_CONTROL, response_data, 2)!=0)
+ break;
+ ack_control(req);
+ break;
+ default: {
+ bool handled=false;
+ for(i=0;i<USB_NUM_DRIVERS;i++) {
+ if(drivers[i].enabled &&
+ drivers[i].control_request &&
+ drivers[i].usb_endpoint == (req->wIndex & 0xf))
+ {
+ handled = drivers[i].control_request(req);
+ }
+ }
+ if(!handled) {
+ /* nope. flag error */
+ logf("usb bad req %d", req->bRequest);
+ usb_drv_stall(EP_CONTROL, true,true);
+ ack_control(req);
+ }
break;
- }
- ack_control(req);
- break;
- } /* USB_REQ_GET_DESCRIPTOR */
-
- default: {
- bool handled=false;
- if((req->bRequestType & 0x1f) == 1) /* Interface */
- {
-#ifdef USB_STORAGE
- /* does usb_storage know this request? */
- if(req->wIndex == mass_storage_interface_descriptor.bInterfaceNumber)
- {
- handled = usb_storage_control_request(req);
- }
-#endif
-
-#ifdef USB_SERIAL
- /* does usb_serial know this request? */
- if(req->wIndex == serial_interface_descriptor.bInterfaceNumber)
- {
- handled = usb_serial_control_request(req);
}
-
-#endif
- }
- if(!handled)
- {
- /* nope. flag error */
- logf("usb bad req %d", req->bRequest);
- usb_drv_stall(EP_CONTROL, true,true);
- ack_control(req);
}
- break;
- }
}
logf("control handled");
}
@@ -691,10 +691,6 @@ void usb_core_bus_reset(void)
/* called by usb_drv_transfer_completed() */
void usb_core_transfer_complete(int endpoint, bool in, int status,int length)
{
-#if defined(USB_CHARGING_ONLY) || defined(USB_STORAGE)
- (void)in;
-#endif
-
switch (endpoint) {
case EP_CONTROL:
/* already handled */