From bec6aa3176fc6d5ce80bcd4d6022358aa6c01629 Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Sat, 26 Apr 2008 19:02:16 +0000 Subject: - change the usb class driver framework to allow for device classes with more than one interface or more than one endpoint pair - move the charging-only dummy driver out of usb_core git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17252 a1c6a512-1295-4272-9138-f99709370657 --- firmware/usbstack/usb_core.c | 184 +++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 104 deletions(-) (limited to 'firmware/usbstack/usb_core.c') diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 084b8893af..759a342dd2 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -37,6 +37,10 @@ #include "usb_serial.h" #endif +#if defined(USB_CHARGING_ONLY) +#include "usb_charging_only.h" +#endif + /* TODO: Move target-specific stuff somewhere else (serial number reading) */ #ifdef HAVE_AS3514 @@ -91,22 +95,6 @@ static struct usb_config_descriptor __attribute__((aligned(2))) .bMaxPower = 250, /* 500mA in 2mA units */ }; -#ifdef USB_CHARGING_ONLY -/* dummy interface for charging-only */ -static struct usb_interface_descriptor __attribute__((aligned(2))) - charging_interface_descriptor = -{ - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 4 -}; -#endif static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifier_descriptor = @@ -160,21 +148,12 @@ static const struct usb_string_descriptor __attribute__((aligned(2))) {0x0409} /* LANGID US English */ }; -static const struct usb_string_descriptor __attribute__((aligned(2))) - usb_string_charging_only = -{ - 28, - USB_DT_STRING, - {'C','h','a','r','g','i','n','g',' ','o','n','l','y'} -}; - static const struct usb_string_descriptor* const usb_strings[] = { &lang_descriptor, &usb_string_iManufacturer, &usb_string_iProduct, - &usb_string_iSerial, - &usb_string_charging_only + &usb_string_iSerial }; static int usb_address = 0; @@ -183,8 +162,12 @@ static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; static int usb_core_num_interfaces; -static int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size, - int interface_number,int endpoint); +static struct +{ + void (*completion_handler)(int ep,bool in, int status, int length); + bool (*control_handler)(struct usb_ctrlrequest* req); + struct usb_transfer_completion_event_data completion_event; +} ep_data[NUM_ENDPOINTS]; static struct usb_class_driver drivers[USB_NUM_DRIVERS] = { @@ -192,8 +175,10 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = [USB_DRIVER_MASS_STORAGE] = { .enabled = false, .needs_exclusive_ata = true, - .usb_endpoint = 0, - .usb_interface = 0, + .first_interface = 0, + .last_interface = 0, + .set_first_interface = usb_storage_set_first_interface, + .set_first_endpoint = usb_storage_set_first_endpoint, .get_config_descriptor = usb_storage_get_config_descriptor, .init_connection = usb_storage_init_connection, .init = usb_storage_init, @@ -209,8 +194,10 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = [USB_DRIVER_SERIAL] = { .enabled = false, .needs_exclusive_ata = false, - .usb_endpoint = 0, - .usb_interface = 0, + .first_interface = 0, + .last_interface = 0, + .set_first_interface = usb_serial_set_first_interface, + .set_first_endpoint = usb_serial_set_first_endpoint, .get_config_descriptor = usb_serial_get_config_descriptor, .init_connection = usb_serial_init_connection, .init = usb_serial_init, @@ -226,9 +213,11 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = [USB_DRIVER_CHARGING_ONLY] = { .enabled = false, .needs_exclusive_ata = false, - .usb_endpoint = 0, - .usb_interface = 0, - .get_config_descriptor = usb_charging_get_config_descriptor, + .first_interface = 0, + .last_interface = 0, + .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, .init_connection = NULL, .init = NULL, .disconnect = NULL, @@ -242,11 +231,9 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = }; static void usb_core_control_request_handler(struct usb_ctrlrequest* req); -static int ack_control(struct usb_ctrlrequest* req); static unsigned char response_data[256] USBDEVBSS_ATTR; -static struct usb_transfer_completion_event_data events[NUM_ENDPOINTS]; static short hex[16] = {'0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F'}; @@ -331,17 +318,6 @@ void usb_core_init(void) logf("usb_core_init() finished"); } -static 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) { int i; @@ -360,24 +336,17 @@ void usb_core_exit(void) void usb_core_handle_transfer_completion( struct usb_transfer_completion_event_data* event) { - int i; - switch(event->endpoint) { + int ep = event->endpoint; + switch(ep) { case EP_CONTROL: logf("ctrl handled %ld",current_tick); usb_core_control_request_handler( (struct usb_ctrlrequest*)event->data); break; default: - for(i=0;iendpoint && - drivers[i].transfer_complete != NULL) - { - drivers[i].transfer_complete(event->in, + if(ep_data[ep].completion_handler != NULL) + ep_data[ep].completion_handler(ep,event->in, event->status,event->length); - break; - } - } break; } } @@ -419,13 +388,29 @@ static void usb_core_set_serial_function_id(void) static void allocate_interfaces_and_endpoints(void) { - int i; + int i,j; int interface=0; int endpoint=1; + + memset(ep_data,0,sizeof(ep_data)); + for(i=0;iNUM_ENDPOINTS) { + drivers[i].enabled = false; + continue; + } + interface = drivers[i].set_first_interface(interface); + drivers[i].last_interface = interface; + + for(j=oldendpoint;jNUM_ENDPOINTS) { drivers[i].enabled = false; @@ -463,7 +448,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) response_data[0] = 1; if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) break; - ack_control(req); + usb_core_ack_control(req); break; case USB_REQ_SET_CONFIGURATION: logf("usb_core: SET_CONFIG"); @@ -474,22 +459,20 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) if(drivers[i].enabled && drivers[i].init_connection!=NULL) { - drivers[i].init_connection( - drivers[i].usb_interface, - drivers[i].usb_endpoint); + drivers[i].init_connection(); } } } else { usb_state = ADDRESS; } - ack_control(req); + usb_core_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) + if(usb_core_ack_control(req)!=0) break; usb_drv_cancel_all_transfers(); usb_address = address; @@ -537,9 +520,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) { size+=drivers[i].get_config_descriptor( &response_data[size], - max_packet_size, - drivers[i].usb_interface, - drivers[i].usb_endpoint); + max_packet_size); } } config_descriptor.bNumInterfaces = @@ -587,7 +568,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) if(usb_drv_send(EP_CONTROL, response_data, length)!=0) break; } - ack_control(req); + usb_core_ack_control(req); break; } /* USB_REQ_GET_DESCRIPTOR */ case USB_REQ_CLEAR_FEATURE: @@ -595,7 +576,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) case USB_REQ_SET_FEATURE: if(req->wValue == 2) { /* TEST_MODE */ int mode=req->wIndex>>8; - ack_control(req); + usb_core_ack_control(req); usb_drv_set_test_mode(mode); } break; @@ -604,7 +585,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) response_data[1]= 0; if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) break; - ack_control(req); + usb_core_ack_control(req); break; default: break; @@ -614,7 +595,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) switch (req->bRequest) { case USB_REQ_SET_INTERFACE: logf("usb_core: SET_INTERFACE"); - ack_control(req); + usb_core_ack_control(req); break; case USB_REQ_GET_INTERFACE: @@ -622,7 +603,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) response_data[0] = 0; if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) break; - ack_control(req); + usb_core_ack_control(req); break; case USB_REQ_CLEAR_FEATURE: break; @@ -633,14 +614,15 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) response_data[1]= 0; if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) break; - ack_control(req); + usb_core_ack_control(req); break; default: { bool handled=false; for(i=0;iwIndex)) + drivers[i].first_interface <= (req->wIndex) && + drivers[i].last_interface > (req->wIndex)) { handled = drivers[i].control_request(req); } @@ -649,7 +631,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) /* nope. flag error */ logf("usb bad req %d", req->bRequest); usb_drv_stall(EP_CONTROL, true,true); - ack_control(req); + usb_core_ack_control(req); } break; } @@ -661,13 +643,13 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) if (req->wValue == 0 ) /* ENDPOINT_HALT */ usb_drv_stall(req->wIndex & 0xf, false, (req->wIndex & 0x80) !=0); - ack_control(req); + usb_core_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); + usb_core_ack_control(req); break; case USB_REQ_GET_STATUS: response_data[0]= 0; @@ -678,23 +660,17 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req) (req->wIndex&0x80)!=0); if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) break; - ack_control(req); + usb_core_ack_control(req); break; default: { bool handled=false; - for(i=0;iwIndex & 0xf)) - { - handled = drivers[i].control_request(req); - } - } + if(ep_data[req->wIndex & 0xf].control_handler != NULL) + handled = ep_data[req->wIndex & 0xf].control_handler(req); if(!handled) { /* nope. flag error */ logf("usb bad req %d", req->bRequest); usb_drv_stall(EP_CONTROL, true,true); - ack_control(req); + usb_core_ack_control(req); } break; } @@ -719,13 +695,13 @@ void usb_core_transfer_complete(int endpoint, bool in, int status,int length) break; default: - events[endpoint].endpoint=endpoint; - events[endpoint].in=in; - events[endpoint].data=0; - events[endpoint].status=status; - events[endpoint].length=length; + ep_data[endpoint].completion_event.endpoint=endpoint; + ep_data[endpoint].completion_event.in=in; + ep_data[endpoint].completion_event.data=0; + ep_data[endpoint].completion_event.status=status; + ep_data[endpoint].completion_event.length=length; /* All other endoints. Let the thread deal with it */ - usb_signal_transfer_completion(&events[endpoint]); + usb_signal_transfer_completion(&ep_data[endpoint].completion_event); break; } } @@ -733,16 +709,16 @@ void usb_core_transfer_complete(int endpoint, bool in, int status,int length) /* called by usb_drv_int() */ void usb_core_control_request(struct usb_ctrlrequest* req) { - events[0].endpoint=0; - events[0].in=0; - events[0].data=(void *)req; - events[0].status=0; - events[0].length=0; + ep_data[0].completion_event.endpoint=0; + ep_data[0].completion_event.in=0; + ep_data[0].completion_event.data=(void *)req; + ep_data[0].completion_event.status=0; + ep_data[0].completion_event.length=0; logf("ctrl received %ld",current_tick); - usb_signal_transfer_completion(&events[0]); + usb_signal_transfer_completion(&ep_data[0].completion_event); } -static int ack_control(struct usb_ctrlrequest* req) +int usb_core_ack_control(struct usb_ctrlrequest* req) { if (req->bRequestType & 0x80) return usb_drv_recv(EP_CONTROL, NULL, 0); -- cgit v1.2.3