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

@ -72,170 +72,139 @@ static const struct usb_device_descriptor device_descriptor= {
.bNumConfigurations = 1
};
static struct {
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 =
struct usb_config_descriptor config_descriptor =
{
{
.bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG,
.wTotalLength = sizeof _config_data,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 250, /* 500mA in 2mA units */
},
.bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG,
.wTotalLength = 0, /* will be filled in later */
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 250, /* 500mA in 2mA units */
};
#ifdef USB_CHARGING_ONLY
/* dummy interface for charging-only */
{
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.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
},
/* dummy interface for charging-only */
struct usb_interface_descriptor 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 = 5
};
#endif
#ifdef USB_STORAGE
/* storage interface */
{
.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
},
/* storage interface */
struct usb_interface_descriptor 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
};
{
.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
},
{
.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
},
struct usb_endpoint_descriptor 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 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 */
{
.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
},
/* serial interface */
struct usb_interface_descriptor 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
};
{
.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
},
{
.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
},
struct usb_endpoint_descriptor 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 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
#ifdef USB_BENCHMARK
/* bulk test interface */
{
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 255,
.bInterfaceProtocol = 255,
.iInterface = 4
},
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_BENCHMARK | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
},
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_BENCHMARK | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
},
#endif
/* bulk test interface */
struct usb_interface_descriptor benchmark_interface_descriptor =
{
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 255,
.bInterfaceProtocol = 255,
.iInterface = 4
};
struct usb_endpoint_descriptor benchmark_ep_in_descriptor =
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_BENCHMARK | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
};
struct usb_endpoint_descriptor benchmark_ep_out_descriptor =
{
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_BENCHMARK | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 16,
.bInterval = 0
};
#endif
static const struct usb_qualifier_descriptor qualifier_descriptor =
{
.bLength = sizeof(struct usb_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'}
};
#if defined(HAVE_AS3514)
static struct usb_string_descriptor usb_string_iSerial =
{
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'}
};
#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 */
@ -330,7 +290,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req);
static int ack_control(struct usb_ctrlrequest* req);
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
{
@ -356,7 +316,8 @@ static void set_serial_descriptor(void)
/* We need to convert from a little-endian 64-bit int
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;
int i,j;
@ -394,7 +355,6 @@ void usb_core_init(void)
if (initialized)
return;
config_data = (void*)UNCACHED_ADDR(&_config_data);
response_data = (void*)UNCACHED_ADDR(&__response_data);
queue_init(&usbcore_queue, false);
@ -496,6 +456,12 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
/* note: interrupt context */
data_connection = true;
#if defined(IPOD_ARCH) || defined(HAVE_AS3514)
if(usb_state == DEFAULT) {
set_serial_descriptor();
}
#endif
#ifdef USB_BENCHMARK
if ((req->bRequestType & 0x60) == USB_TYPE_VENDOR) {
usb_benchmark_control_request(req);
@ -617,7 +583,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
else {
max_packet_size=64;
}
config_data->config_descriptor.bDescriptorType=USB_DT_CONFIG;
config_descriptor.bDescriptorType=USB_DT_CONFIG;
}
else {
if(usb_drv_port_speed()) {
@ -626,43 +592,67 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
else {
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
memcpy(&config_data->charging_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
memcpy(&config_data->charging_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
config_data->charging_interface_descriptor.bInterfaceNumber=interface_number;
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
#ifdef USB_STORAGE
memcpy(&config_data->mass_storage_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
memcpy(&config_data->mass_storage_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
config_data->mass_storage_interface_descriptor.bInterfaceNumber=interface_number;
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
memcpy(&config_data->serial_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
memcpy(&config_data->serial_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
config_data->serial_interface_descriptor.bInterfaceNumber=interface_number;
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_BENCHMARK
memcpy(&config_data->benchmark_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
memcpy(&config_data->benchmark_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short));
config_data.benchmark_interface_descriptor.bInterfaceNumber=interface_number;
interface_number++;
benchmark_ep_in_descriptor.wMaxPacketSize=max_packet_size;
benchmark_ep_out_descriptor.wMaxPacketSize=max_packet_size;
config_descriptor.bNumInterfaces=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
config_data->config_descriptor.bNumInterfaces=interface_number;
ptr = config_data;
size = sizeof _config_data;
config_descriptor.wTotalLength = size;
memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor));
ptr = response_data;
break;
}
case USB_DT_STRING:
logf("STRING %d",index);
if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
ptr = usb_strings[index];
size = usb_strings[index]->bLength;
memcpy(&response_data[0],&usb_strings[index],size);
ptr = response_data;
}
else {
logf("bad string id %d", index);