1
0
Fork 0
forked from len0rd/rockbox

Improve usb descriptor handling. This should fix any cache and/or alignment related problem.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16371 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Frank Gevaerts 2008-02-22 20:38:31 +00:00
parent a0b5780e2d
commit 9dbe7f2a8c
2 changed files with 172 additions and 182 deletions

View file

@ -227,7 +227,7 @@ struct usb_config_descriptor {
uint8_t iConfiguration; uint8_t iConfiguration;
uint8_t bmAttributes; uint8_t bmAttributes;
uint8_t bMaxPower; uint8_t bMaxPower;
} __attribute__ ((packed)); } __attribute__ ((packed,aligned(2)));
#define USB_DT_CONFIG_SIZE 9 #define USB_DT_CONFIG_SIZE 9
@ -285,7 +285,7 @@ struct usb_endpoint_descriptor {
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
//uint8_t bRefresh; //uint8_t bRefresh;
//uint8_t bSynchAddress; //uint8_t bSynchAddress;
} __attribute__ ((packed)); } __attribute__ ((packed,aligned(2)));
#define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ #define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
@ -304,7 +304,7 @@ struct usb_qualifier_descriptor {
uint8_t bMaxPacketSize0; uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations; uint8_t bNumConfigurations;
uint8_t bRESERVED; uint8_t bRESERVED;
} __attribute__ ((packed)); } __attribute__ ((packed,aligned(2)));
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/

View file

@ -72,75 +72,37 @@ static const struct usb_device_descriptor device_descriptor= {
.bNumConfigurations = 1 .bNumConfigurations = 1
}; };
static struct { struct usb_config_descriptor config_descriptor =
struct usb_config_descriptor config_descriptor;
#ifdef USB_CHARGING_ONLY
struct usb_interface_descriptor charging_interface_descriptor;
struct usb_endpoint_descriptor charging_ep_in_descriptor;
struct usb_endpoint_descriptor charging_ep_out_descriptor;
#endif
#ifdef USB_STORAGE
struct usb_interface_descriptor mass_storage_interface_descriptor;
struct usb_endpoint_descriptor mass_storage_ep_in_descriptor;
struct usb_endpoint_descriptor mass_storage_ep_out_descriptor;
#endif
#ifdef USB_SERIAL
struct usb_interface_descriptor serial_interface_descriptor;
struct usb_endpoint_descriptor serial_ep_in_descriptor;
struct usb_endpoint_descriptor serial_ep_out_descriptor;
#endif
#ifdef USB_BENCHMARK
struct usb_interface_descriptor benchmark_interface_descriptor;
struct usb_endpoint_descriptor benchmark_ep_in_descriptor;
struct usb_endpoint_descriptor benchmark_ep_out_descriptor;
#endif
} __attribute__((packed)) *config_data, _config_data =
{
{ {
.bLength = sizeof(struct usb_config_descriptor), .bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG, .bDescriptorType = USB_DT_CONFIG,
.wTotalLength = sizeof _config_data, .wTotalLength = 0, /* will be filled in later */
.bNumInterfaces = 1, .bNumInterfaces = 1,
.bConfigurationValue = 1, .bConfigurationValue = 1,
.iConfiguration = 0, .iConfiguration = 0,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 250, /* 500mA in 2mA units */ .bMaxPower = 250, /* 500mA in 2mA units */
}, };
#ifdef USB_CHARGING_ONLY #ifdef USB_CHARGING_ONLY
/* dummy interface for charging-only */ /* dummy interface for charging-only */
struct usb_interface_descriptor charging_interface_descriptor =
{ {
.bLength = sizeof(struct usb_interface_descriptor), .bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0, .bInterfaceNumber = 0,
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 2, .bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0, .bInterfaceSubClass = 0,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.iInterface = 5 .iInterface = 5
}, };
/* TODO: try with zero endpoints */
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_CHARGING_ONLY | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
},
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_CHARGING_ONLY | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
},
#endif #endif
#ifdef USB_STORAGE #ifdef USB_STORAGE
/* storage interface */ /* storage interface */
struct usb_interface_descriptor mass_storage_interface_descriptor =
{ {
.bLength = sizeof(struct usb_interface_descriptor), .bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
@ -151,8 +113,9 @@ static struct {
.bInterfaceSubClass = USB_SC_SCSI, .bInterfaceSubClass = USB_SC_SCSI,
.bInterfaceProtocol = USB_PROT_BULK, .bInterfaceProtocol = USB_PROT_BULK,
.iInterface = 0 .iInterface = 0
}, };
struct usb_endpoint_descriptor mass_storage_ep_in_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -160,7 +123,8 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
}, };
struct usb_endpoint_descriptor mass_storage_ep_out_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -168,11 +132,12 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
}, };
#endif #endif
#ifdef USB_SERIAL #ifdef USB_SERIAL
/* serial interface */ /* serial interface */
struct usb_interface_descriptor serial_interface_descriptor =
{ {
.bLength = sizeof(struct usb_interface_descriptor), .bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
@ -183,8 +148,9 @@ static struct {
.bInterfaceSubClass = 0, .bInterfaceSubClass = 0,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.iInterface = 0 .iInterface = 0
}, };
struct usb_endpoint_descriptor serial_ep_in_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -192,7 +158,8 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
}, };
struct usb_endpoint_descriptor serial_ep_out_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -200,11 +167,12 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
}, };
#endif #endif
#ifdef USB_BENCHMARK #ifdef USB_BENCHMARK
/* bulk test interface */ /* bulk test interface */
struct usb_interface_descriptor benchmark_interface_descriptor =
{ {
.bLength = sizeof(struct usb_interface_descriptor), .bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
@ -215,8 +183,9 @@ static struct {
.bInterfaceSubClass = 255, .bInterfaceSubClass = 255,
.bInterfaceProtocol = 255, .bInterfaceProtocol = 255,
.iInterface = 4 .iInterface = 4
}, };
struct usb_endpoint_descriptor benchmark_ep_in_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -224,7 +193,8 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
}, };
struct usb_endpoint_descriptor benchmark_ep_out_descriptor =
{ {
.bLength = sizeof(struct usb_endpoint_descriptor), .bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
@ -232,9 +202,8 @@ static struct {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 0 .bInterval = 0
},
#endif
}; };
#endif
static const struct usb_qualifier_descriptor qualifier_descriptor = static const struct usb_qualifier_descriptor qualifier_descriptor =
{ {
@ -262,7 +231,6 @@ static struct usb_string_descriptor usb_string_iProduct =
{'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'}
}; };
#if defined(HAVE_AS3514)
static struct usb_string_descriptor usb_string_iSerial = static struct usb_string_descriptor usb_string_iSerial =
{ {
66, 66,
@ -270,14 +238,6 @@ static struct usb_string_descriptor usb_string_iSerial =
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'} '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}
}; };
#else
static struct usb_string_descriptor usb_string_iSerial =
{
34,
USB_DT_STRING,
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}
};
#endif
/* Generic for all targets */ /* Generic for all targets */
@ -330,7 +290,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req);
static int ack_control(struct usb_ctrlrequest* req); static int ack_control(struct usb_ctrlrequest* req);
static unsigned char *response_data; static unsigned char *response_data;
static unsigned char __response_data[CACHEALIGN_UP(2)] CACHEALIGN_ATTR; static unsigned char __response_data[CACHEALIGN_UP(256)] CACHEALIGN_ATTR;
struct usb_core_event struct usb_core_event
{ {
@ -356,7 +316,8 @@ static void set_serial_descriptor(void)
/* We need to convert from a little-endian 64-bit int /* We need to convert from a little-endian 64-bit int
into a utf-16 string of hex characters */ into a utf-16 string of hex characters */
short* p = &usb_string_iSerial.wString[15]; /* Align at the right side of the 32-digit serial number */
short* p = &usb_string_iSerial.wString[31];
uint32_t x; uint32_t x;
int i,j; int i,j;
@ -394,7 +355,6 @@ void usb_core_init(void)
if (initialized) if (initialized)
return; return;
config_data = (void*)UNCACHED_ADDR(&_config_data);
response_data = (void*)UNCACHED_ADDR(&__response_data); response_data = (void*)UNCACHED_ADDR(&__response_data);
queue_init(&usbcore_queue, false); queue_init(&usbcore_queue, false);
@ -496,6 +456,12 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
/* note: interrupt context */ /* note: interrupt context */
data_connection = true; data_connection = true;
#if defined(IPOD_ARCH) || defined(HAVE_AS3514)
if(usb_state == DEFAULT) {
set_serial_descriptor();
}
#endif
#ifdef USB_BENCHMARK #ifdef USB_BENCHMARK
if ((req->bRequestType & 0x60) == USB_TYPE_VENDOR) { if ((req->bRequestType & 0x60) == USB_TYPE_VENDOR) {
usb_benchmark_control_request(req); usb_benchmark_control_request(req);
@ -617,7 +583,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
else { else {
max_packet_size=64; max_packet_size=64;
} }
config_data->config_descriptor.bDescriptorType=USB_DT_CONFIG; config_descriptor.bDescriptorType=USB_DT_CONFIG;
} }
else { else {
if(usb_drv_port_speed()) { if(usb_drv_port_speed()) {
@ -626,43 +592,67 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
else { else {
max_packet_size=512; max_packet_size=512;
} }
config_data->config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG; config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG;
} }
size = sizeof(config_descriptor);
#ifdef USB_CHARGING_ONLY #ifdef USB_CHARGING_ONLY
memcpy(&config_data->charging_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); charging_interface_descriptor.bInterfaceNumber=interface_number;
memcpy(&config_data->charging_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
config_data->charging_interface_descriptor.bInterfaceNumber=interface_number;
interface_number++; interface_number++;
memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor));
size += sizeof(struct usb_interface_descriptor);
#endif #endif
#ifdef USB_STORAGE #ifdef USB_STORAGE
memcpy(&config_data->mass_storage_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size;
memcpy(&config_data->mass_storage_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size;
config_data->mass_storage_interface_descriptor.bInterfaceNumber=interface_number; mass_storage_interface_descriptor.bInterfaceNumber=interface_number;
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 #endif
#ifdef USB_SERIAL #ifdef USB_SERIAL
memcpy(&config_data->serial_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); serial_ep_in_descriptor.wMaxPacketSize=max_packet_size;
memcpy(&config_data->serial_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); serial_ep_out_descriptor.wMaxPacketSize=max_packet_size;
config_data->serial_interface_descriptor.bInterfaceNumber=interface_number; serial_interface_descriptor.bInterfaceNumber=interface_number;
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 #endif
#ifdef USB_BENCHMARK #ifdef USB_BENCHMARK
memcpy(&config_data->benchmark_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); benchmark_ep_in_descriptor.wMaxPacketSize=max_packet_size;
memcpy(&config_data->benchmark_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); benchmark_ep_out_descriptor.wMaxPacketSize=max_packet_size;
config_data.benchmark_interface_descriptor.bInterfaceNumber=interface_number; config_descriptor.bNumInterfaces=interface_number;
interface_number++;
memcpy(&response_data[size],&benchmark_interface_descriptor,sizeof(struct usb_interface_descriptor));
size += sizeof(struct usb_interface_descriptor);
memcpy(&response_data[size],&benchmark_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor));
size += sizeof(struct usb_endpoint_descriptor);
memcpy(&response_data[size],&benchmark_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor));
size += sizeof(struct usb_endpoint_descriptor);
#endif #endif
config_data->config_descriptor.bNumInterfaces=interface_number; config_descriptor.wTotalLength = size;
ptr = config_data; memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor));
size = sizeof _config_data;
ptr = response_data;
break; break;
} }
case USB_DT_STRING: case USB_DT_STRING:
logf("STRING %d",index);
if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) { if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
ptr = usb_strings[index];
size = usb_strings[index]->bLength; size = usb_strings[index]->bLength;
memcpy(&response_data[0],&usb_strings[index],size);
ptr = response_data;
} }
else { else {
logf("bad string id %d", index); logf("bad string id %d", index);