Index: apps/debug_menu.c =================================================================== --- apps/debug_menu.c (revision 16519) +++ apps/debug_menu.c (working copy) @@ -102,6 +102,10 @@ #include "as3514.h" #endif +#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) +#include "usb_core.h" +#endif + /*---------------------------------------------------*/ /* SPECIAL DEBUG STUFF */ /*---------------------------------------------------*/ @@ -2364,13 +2368,12 @@ #endif #if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) -extern bool usb_core_serial_enabled; - static bool logf_usb_serial(void) { - usb_core_serial_enabled = !usb_core_serial_enabled; + bool serial_enabled = !usb_core_driver_enabled(USB_DRIVER_SERIAL); + usb_core_enable_driver(USB_DRIVER_SERIAL,serial_enabled); gui_syncsplash(HZ, "USB logf %s", - usb_core_serial_enabled?"enabled":"disabled"); + serial_enabled?"enabled":"disabled"); return false; } #endif Index: firmware/export/usb_core.h =================================================================== --- firmware/export/usb_core.h (revision 16519) +++ firmware/export/usb_core.h (working copy) @@ -21,7 +21,7 @@ #ifndef BOOTLOADER -//#define USB_SERIAL +#define USB_SERIAL #define USB_STORAGE #define USB_CHARGING_ONLY #else /* BOOTLOADER */ @@ -32,19 +32,8 @@ #include "usb.h" /* endpoints */ -enum { - EP_CONTROL = 0, -#ifdef USB_STORAGE - EP_MASS_STORAGE, -#endif -#ifdef USB_SERIAL - EP_SERIAL, -#endif -#ifdef USB_CHARGING_ONLY - EP_CHARGING_ONLY, -#endif - NUM_ENDPOINTS -}; +#define EP_CONTROL 0 +#define NUM_ENDPOINTS 3 extern int usb_max_pkt_size; @@ -54,7 +43,8 @@ void usb_core_transfer_complete(int endpoint, bool in, int status, int length); void usb_core_bus_reset(void); bool usb_core_exclusive_connection(void); -void usb_core_enable_protocol(int driver,bool enabled); +void usb_core_enable_driver(int driver,bool enabled); +bool usb_core_driver_enabled (int driver); void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event); #endif Index: firmware/export/usb.h =================================================================== --- firmware/export/usb.h (revision 16519) +++ firmware/export/usb.h (working copy) @@ -24,13 +24,13 @@ /* Messages from usb_tick and thread states */ enum { - USB_INSERTED, - USB_EXTRACTED, - USB_REENABLE, - USB_POWERED, - USB_TRANSFER_COMPLETION, - USB_REQUEST_DISK, - USB_REQUEST_REBOOT + USB_INSERTED, + USB_EXTRACTED, + USB_REENABLE, + USB_POWERED, + USB_TRANSFER_COMPLETION, + USB_REQUEST_DISK, + USB_REQUEST_REBOOT }; @@ -69,7 +69,8 @@ enum { USB_DRIVER_MASS_STORAGE, USB_DRIVER_SERIAL, - USB_DRIVER_CHARGING_ONLY + USB_DRIVER_CHARGING_ONLY, + USB_NUM_DRIVERS }; #endif #ifdef HAVE_USBSTACK Index: firmware/usbstack/usb_class_driver.h =================================================================== --- firmware/usbstack/usb_class_driver.h (revision 0) +++ firmware/usbstack/usb_class_driver.h (revision 0) @@ -0,0 +1,59 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2008 Frank Gevaerts + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _USB_CLASS_DRIVER_H_ +#define _USB_CLASS_DRIVER_H_ + +/* Common api, implemented by all class drivers */ + +struct usb_class_driver { + bool enabled; + bool needs_exclusive_ata; + int usb_endpoint; + int usb_interface; + + /* Asks the driver to put the interface descriptor and all other + needed descriptor for this driver at dest, for the given settings. + Returns the number of bytes taken by these descriptors. */ + int (*get_config_descriptor)(unsigned char *dest, + int max_packet_size, int interface_number, int endpoint); + + /* Tells the driver that a usb connection has been set up and is now + ready to use. */ + void (*init_connection)(int interface,int endpoint); + + /* Initialises the driver. This can be called multiple times, + and should not perform any action that can disturb other threads + (like getting the audio buffer) */ + void (*init)(void); + + /* Tells the driver that the usb connection is no longer active */ + void (*disconnect)(void); + + /* Tells the driver that a usb transfer has been completed. Note that "in" + is relative to the host */ + void (*transfer_complete)(bool in, int status, int length); + + /* 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 + it should return false. */ + bool (*control_request)(struct usb_ctrlrequest* req); +}; + +#endif Index: firmware/usbstack/usb_core.c =================================================================== --- firmware/usbstack/usb_core.c (revision 16519) +++ firmware/usbstack/usb_core.c (working copy) @@ -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" @@ -103,76 +104,6 @@ }; #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 = { .bLength = sizeof(struct usb_qualifier_descriptor), @@ -238,14 +169,56 @@ 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 usb_core_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 -/* Next one is non-static, to enable setting it from the debug menu */ -bool usb_core_serial_enabled = false; +#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 #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); @@ -323,6 +296,7 @@ void usb_core_init(void) { + int i; if (initialized) return; @@ -333,27 +307,33 @@ /* 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 + for(i=0;iendpoint) { 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); + default: + for(i=0;iendpoint && + usb_core_drivers[i].transfer_complete != NULL) + { + usb_core_drivers[i].transfer_complete(event->in,event->status,event->length); + break; + } + } 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: - 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 + usb_core_drivers[driver].enabled=enabled; +} + +bool usb_core_driver_enabled(int driver) +{ + return usb_core_drivers[driver].enabled; +} + +static void usb_core_set_serial_function_id(void) +{ + int id = 0; + int i; + for(i=0;i=NUM_ENDPOINTS) { + usb_core_drivers[i].enabled = false; + } + } + usb_core_num_interfaces = interface; +} + static void usb_core_control_request_handler(struct usb_ctrlrequest* req) { + int i; 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; - } -#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_set_serial_function_id(); - 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 + allocate_interfaces_and_endpoints(); -#ifdef USB_SERIAL - if(usb_core_serial_enabled) - usb_serial_control_request(req); -#endif - } - else { - usb_state = ADDRESS; - } - ack_control(req); - break; - - 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;iwValue) - 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_REQ_SET_FEATURE: - logf("usb_core: SET_FEATURE"); - switch(req->bRequestType & 0x0f){ - case 0: /* Device */ - 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); + 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 - usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); + response_data[0] = 1; + if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) + break; ack_control(req); break; - default: + case USB_REQ_SET_CONFIGURATION: + logf("usb_core: SET_CONFIG"); + usb_drv_cancel_all_transfers(); + if (req->wValue){ + usb_state = CONFIGURED; + for(i=0;iwValue; + 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); - 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; - } + switch (req->wValue >> 8) { /* type */ + case USB_DT_DEVICE: + ptr = &device_descriptor; + size = sizeof(struct usb_device_descriptor); + 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_DT_OTHER_SPEED_CONFIG: + case USB_DT_CONFIG: { + int max_packet_size; - 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); + 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); - switch (req->wValue >> 8) { /* type */ - case USB_DT_DEVICE: - ptr = &device_descriptor; - size = sizeof(struct usb_device_descriptor); - break; + for(i=0;iwValue >> 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); + 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; -#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++; + case USB_DT_DEVICE_QUALIFIER: + ptr = &qualifier_descriptor; + size = sizeof (struct usb_qualifier_descriptor); + break; - 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); + default: + logf("bad desc %d", req->wValue >> 8); + usb_drv_stall(EP_CONTROL, true,true); + break; } -#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); + if (ptr) { + length = MIN(size, length); + if(usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length)!=0) + break; } -#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; + 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); } - - 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); + 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: - logf("bad desc %d", req->wValue >> 8); - usb_drv_stall(EP_CONTROL, true,true); break; } + break; + case 1: /* Interface */ + switch (req->bRequest) { + case USB_REQ_SET_INTERFACE: + logf("usb_core: SET_INTERFACE"); + 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_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;iwIndex)){ + handled = usb_core_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) + 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; + 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; + 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: { - handled = usb_storage_control_request(req); + bool handled=false; + for(i=0;iwIndex & 0xf)){ + handled = usb_core_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; } -#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 +656,6 @@ /* 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 */ Index: firmware/usbstack/usb_storage.h =================================================================== --- firmware/usbstack/usb_storage.h (revision 16519) +++ firmware/usbstack/usb_storage.h (working copy) @@ -21,6 +21,9 @@ #include "usb_ch9.h" +int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size, + int interface_number,int endpoint); +void usb_storage_init_connection(int interface,int endpoint); void usb_storage_init(void); void usb_storage_transfer_complete(bool in,int state,int length); bool usb_storage_control_request(struct usb_ctrlrequest* req); Index: firmware/usbstack/usb_serial.c =================================================================== --- firmware/usbstack/usb_serial.c (revision 16519) +++ firmware/usbstack/usb_serial.c (working copy) @@ -27,6 +27,40 @@ #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 = 0, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0, + .bInterval = 0 +}; +struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_out_descriptor = +{ + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0, + .bInterval = 0 +}; + + #define BUFFER_SIZE 512 /* Max 16k because of controller limitations */ static unsigned char _send_buffer[BUFFER_SIZE] __attribute__((aligned(32))); static unsigned char* send_buffer; @@ -38,8 +72,64 @@ static int buffer_length; static bool active = false; +static int usb_endpoint; +static int usb_interface; + static struct mutex sendlock; +static void sendout(void) +{ + if(buffer_start+buffer_length > BUFFER_SIZE) + { + /* Buffer wraps. Only send the first part */ + usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start],(BUFFER_SIZE - buffer_start)); + } + else + { + /* Send everything */ + usb_drv_send_nonblocking(usb_endpoint, &send_buffer[buffer_start],buffer_length); + } + busy_sending=true; +} + +int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size, + int interface_number,int endpoint) +{ + serial_ep_in_descriptor.wMaxPacketSize=max_packet_size; + serial_ep_out_descriptor.wMaxPacketSize=max_packet_size; + serial_interface_descriptor.bInterfaceNumber=interface_number; + + serial_ep_in_descriptor.bEndpointAddress = endpoint | USB_DIR_IN, + serial_ep_out_descriptor.bEndpointAddress = endpoint | USB_DIR_OUT, + + memcpy(dest,&serial_interface_descriptor,sizeof(struct usb_interface_descriptor)); + dest+=sizeof(struct usb_interface_descriptor); + + memcpy(dest,&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); + dest+=sizeof(struct usb_endpoint_descriptor); + + memcpy(dest,&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); + return sizeof(struct usb_interface_descriptor)+2*sizeof(struct usb_endpoint_descriptor); +} + +void usb_serial_init_connection(int interface,int endpoint) +{ + usb_interface = interface; + usb_endpoint = endpoint; + + /* prime rx endpoint */ + usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); + + /* we come here too after a bus reset, so reset some data */ + mutex_lock(&sendlock); + busy_sending = false; + if(buffer_length>0) + { + sendout(); + } + mutex_unlock(&sendlock); +} + /* called by usb_code_init() */ void usb_serial_init(void) { @@ -53,26 +143,11 @@ mutex_init(&sendlock); } -void usb_serial_exit(void) +void usb_serial_disconnect(void) { active = false; } -static void sendout(void) -{ - if(buffer_start+buffer_length > BUFFER_SIZE) - { - /* Buffer wraps. Only send the first part */ - usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],(BUFFER_SIZE - buffer_start)); - } - else - { - /* Send everything */ - usb_drv_send_nonblocking(EP_SERIAL, &send_buffer[buffer_start],buffer_length); - } - busy_sending=true; -} - void usb_serial_send(unsigned char *data,int length) { if(!active) @@ -121,7 +196,7 @@ case false: logf("serial: %s", receive_buffer); /* Data received. TODO : Do something with it ? */ - usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); + usb_drv_recv(usb_endpoint, receive_buffer, sizeof _receive_buffer); break; case true: @@ -148,26 +223,9 @@ { bool handled = false; switch (req->bRequest) { - case USB_REQ_SET_CONFIGURATION: - logf("serial: set config"); - /* prime rx endpoint */ - usb_drv_recv(EP_SERIAL, receive_buffer, sizeof _receive_buffer); - handled = true; - - /* we come here too after a bus reset, so reset some data */ - mutex_lock(&sendlock); - busy_sending = false; - if(buffer_length>0) - { - sendout(); - } - mutex_unlock(&sendlock); - break; - default: logf("serial: unhandeld req %d", req->bRequest); } - return handled; } Index: firmware/usbstack/usb_serial.h =================================================================== --- firmware/usbstack/usb_serial.h (revision 16519) +++ firmware/usbstack/usb_serial.h (working copy) @@ -21,8 +21,11 @@ #include "usb_ch9.h" +int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size, + int interface_number, int endpoint); +void usb_serial_init_connection(int interface,int endpoint); void usb_serial_init(void); -void usb_serial_exit(void); +void usb_serial_disconnect(void); void usb_serial_transfer_complete(bool in, int status, int length); bool usb_serial_control_request(struct usb_ctrlrequest* req); Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (revision 16519) +++ firmware/usbstack/usb_storage.c (working copy) @@ -28,6 +28,7 @@ /* Needed to get at the audio buffer */ #include "audio.h" + #ifdef USB_STORAGE /* Enable the following define to export only the SD card slot. This @@ -85,7 +86,43 @@ #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 +/* storage interface */ +#define USB_SC_SCSI 0x06 /* Transparent */ +#define USB_PROT_BULK 0x50 /* bulk only */ + +static 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 +}; + +static struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_in_descriptor = +{ + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0, + .bInterval = 0 +}; +static struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_out_descriptor = +{ + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0, + .bInterval = 0 +}; + struct inquiry_data { unsigned char DeviceType; unsigned char DeviceTypeModifier; @@ -221,6 +258,9 @@ static void send_and_read_next(void); static bool ejected[NUM_VOLUMES]; +static int usb_endpoint; +static int usb_interface; + static enum { WAITING_FOR_COMMAND, SENDING_BLOCKS, @@ -238,6 +278,42 @@ logf("usb_storage_init done"); } +int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_size, + int interface_number,int endpoint) +{ + 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; + + mass_storage_ep_in_descriptor.bEndpointAddress = endpoint | USB_DIR_IN, + mass_storage_ep_out_descriptor.bEndpointAddress = endpoint | USB_DIR_OUT, + + memcpy(dest,&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor)); + dest+=sizeof(struct usb_interface_descriptor); + memcpy(dest,&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); + dest+=sizeof(struct usb_endpoint_descriptor); + memcpy(dest,&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); + return sizeof(struct usb_interface_descriptor)+2*sizeof(struct usb_endpoint_descriptor); +} + +void usb_storage_init_connection(int interface,int endpoint) +{ + size_t bufsize; + unsigned char * audio_buffer; + + usb_interface = interface; + usb_endpoint = endpoint; + + logf("ums: set config"); + /* prime rx endpoint. We only need room for commands */ + state = WAITING_FOR_COMMAND; + + /* TODO : check if bufsize is at least 32K ? */ + audio_buffer = audio_get_buffer(false,&bufsize); + tb.transfer_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0); + usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); +} + /* called by usb_core_transfer_complete() */ void usb_storage_transfer_complete(bool in,int status,int length) { @@ -307,8 +383,8 @@ handle_scsi(cbw); } else { - usb_drv_stall(EP_MASS_STORAGE, true,true); - usb_drv_stall(EP_MASS_STORAGE, true,false); + usb_drv_stall(usb_endpoint, true,true); + usb_drv_stall(usb_endpoint, true,false); } break; case SENDING_CSW: @@ -317,7 +393,7 @@ } //logf("csw sent, now go back to idle"); state = WAITING_FOR_COMMAND; - usb_drv_recv(EP_MASS_STORAGE, tb.transfer_buffer, 1024); + usb_drv_recv(usb_endpoint, tb.transfer_buffer, 1024); break; case SENDING_RESULT: if(in==false) { @@ -368,6 +444,7 @@ { bool handled = false; + switch (req->bRequest) { case USB_BULK_GET_MAX_LUN: { #ifdef ONLY_EXPOSE_CARD_SLOT @@ -389,28 +466,13 @@ * data toggle bits and endpoint STALL conditions despite the Bulk-Only * Mass Storage Reset. */ #if 0 - usb_drv_reset_endpoint(EP_MASS_STORAGE, false); - usb_drv_reset_endpoint(EP_MASS_STORAGE, true); + usb_drv_reset_endpoint(usb_endpoint, false); + usb_drv_reset_endpoint(usb_endpoint, true); #endif usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ handled = true; break; - - case USB_REQ_SET_CONFIGURATION: { - size_t bufsize; - unsigned char * audio_buffer; - logf("ums: set config"); - /* prime rx endpoint. We only need room for commands */ - state = WAITING_FOR_COMMAND; - - /* TODO : check if bufsize is at least 32K ? */ - audio_buffer = audio_get_buffer(false,&bufsize); - tb.transfer_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0); - usb_drv_recv(EP_MASS_STORAGE, tb.transfer_buffer, 1024); - handled = true; - break; - } } return handled; @@ -771,7 +833,7 @@ default: logf("scsi unknown cmd %x",cbw->command_block[0x0]); - usb_drv_stall(EP_MASS_STORAGE, true,true); + usb_drv_stall(usb_endpoint, true,true); send_csw(UMS_STATUS_FAIL); break; } @@ -779,19 +841,19 @@ static void send_block_data(void *data,int size) { - usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); + usb_drv_send_nonblocking(usb_endpoint, data,size); state = SENDING_BLOCKS; } static void send_command_result(void *data,int size) { - usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); + usb_drv_send_nonblocking(usb_endpoint, data,size); state = SENDING_RESULT; } static void receive_block_data(void *data,int size) { - usb_drv_recv(EP_MASS_STORAGE, data, size); + usb_drv_recv(usb_endpoint, data, size); state = RECEIVING_BLOCKS; } @@ -802,7 +864,7 @@ tb.csw->data_residue = 0; tb.csw->status = status; - usb_drv_send_nonblocking(EP_MASS_STORAGE, tb.csw, sizeof(struct command_status_wrapper)); + usb_drv_send_nonblocking(usb_endpoint, tb.csw, sizeof(struct command_status_wrapper)); state = SENDING_CSW; //logf("CSW: %X",status); Index: firmware/usb.c =================================================================== --- firmware/usb.c (revision 16519) +++ firmware/usb.c (working copy) @@ -191,8 +191,8 @@ { usb_state = USB_POWERED; #ifdef HAVE_USBSTACK - usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,false); - usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,true); + usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,false); + usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,true); usb_enable(true); #endif } @@ -200,8 +200,8 @@ #endif { #ifdef HAVE_USBSTACK - usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,true); - usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,false); + usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,true); + usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,false); usb_enable(true); #else /* Tell all threads that they have to back off the ATA.