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.c339
1 files changed, 242 insertions, 97 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 7e86086..13993f9 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -23,10 +23,17 @@
//#define LOGF_ENABLE
#include "logf.h"
-//#define USB_STORAGE
+#ifndef BOOTLOADER
//#define USB_SERIAL
//#define USB_BENCHMARK
+#ifdef USE_ROCKBOX_USB
+#define USB_STORAGE
+#else
#define USB_CHARGING_ONLY
+#endif /* USE_ROCKBOX_USB */
+#else
+#define USB_CHARGING_ONLY
+#endif
#include "usb_ch9.h"
#include "usb_drv.h"
@@ -63,21 +70,21 @@ static const struct usb_device_descriptor device_descriptor = {
.bcdDevice = 0x0100,
.iManufacturer = 1,
.iProduct = 2,
- .iSerialNumber = 0,
+ .iSerialNumber = 3,
.bNumConfigurations = 1
};
static const struct {
struct usb_config_descriptor config_descriptor;
struct usb_interface_descriptor interface_descriptor;
- struct usb_endpoint_descriptor ep1_hs_in_descriptor;
- struct usb_endpoint_descriptor ep1_hs_out_descriptor;
-} config_data =
+ struct usb_endpoint_descriptor ep1_in_descriptor;
+ struct usb_endpoint_descriptor ep1_out_descriptor;
+} config_data_fs =
{
{
.bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG,
- .wTotalLength = sizeof config_data,
+ .wTotalLength = sizeof config_data_fs,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
@@ -96,12 +103,153 @@ static const struct {
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
+ .iInterface = 5
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ }
+#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
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 16,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | 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
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .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_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+ }
+#endif
+},
+config_data_hs =
+{
+ {
+ .bLength = sizeof(struct usb_config_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength = sizeof config_data_hs,
+ .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
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_TX | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 512,
@@ -168,7 +316,7 @@ static const struct {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_TX | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
+ .wMaxPacketSize = 512,
.bInterval = 0
},
{
@@ -176,7 +324,7 @@ static const struct {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_RX | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
+ .wMaxPacketSize = 512,
.bInterval = 0
}
#endif
@@ -192,7 +340,7 @@ static const struct {
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 255,
.bInterfaceProtocol = 255,
- .iInterface = 3
+ .iInterface = 4
},
{
@@ -200,7 +348,6 @@ static const struct {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_RX | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
-// .wMaxPacketSize = 64,
.wMaxPacketSize = 512,
.bInterval = 0
},
@@ -209,7 +356,6 @@ static const struct {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_TX | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
-// .wMaxPacketSize = 64,
.wMaxPacketSize = 512,
.bInterval = 0
}
@@ -228,72 +374,61 @@ static const struct usb_qualifier_descriptor qualifier_descriptor =
.bNumConfigurations = 1
};
-/* full speed = 12 Mbit */
-static const struct usb_endpoint_descriptor ep1_fs_in_descriptor =
+static struct usb_string_descriptor usb_string_iManufacturer =
{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
- .bInterval = 0
+ 24,
+ USB_DT_STRING,
+ {'R','o','c','k','b','o','x','.','o','r','g'}
};
-static const struct usb_endpoint_descriptor ep1_fs_out_descriptor =
+static struct usb_string_descriptor usb_string_iProduct =
{
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
- .bInterval = 0
+ 42,
+ USB_DT_STRING,
+ {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
};
-static const struct usb_endpoint_descriptor* ep_descriptors[4] =
+static struct usb_string_descriptor usb_string_iSerial =
{
- &config_data.ep1_hs_in_descriptor,
- &config_data.ep1_hs_out_descriptor,
- &ep1_fs_in_descriptor,
- &ep1_fs_out_descriptor
+ 34,
+ USB_DT_STRING,
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}
};
+
+/* Generic for all targets */
+
/* this is stringid #0: languages supported */
-static const struct usb_string_descriptor lang_descriptor =
+static struct usb_string_descriptor lang_descriptor =
{
- sizeof(struct usb_string_descriptor),
+ 4,
USB_DT_STRING,
{0x0409} /* LANGID US English */
};
-/* this is stringid #1 and up: the actual strings */
-static const struct {
- unsigned char size;
- unsigned char type;
- unsigned short string[32];
-} usb_strings[] =
+static struct usb_string_descriptor usb_string_usb_benchmark =
{
- {
- 24,
- USB_DT_STRING,
- {'R','o','c','k','b','o','x','.','o','r','g'}
- },
- {
- 42,
- USB_DT_STRING,
- {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
- },
- {
- 40,
- USB_DT_STRING,
- {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
- },
- {
- 28,
- USB_DT_STRING,
- {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
- }
+ 40,
+ USB_DT_STRING,
+ {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
};
+static struct usb_string_descriptor usb_string_charging_only =
+{
+ 28,
+ USB_DT_STRING,
+ {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
+};
+
+static struct usb_string_descriptor* usb_strings[] =
+{
+ &lang_descriptor,
+ &usb_string_iManufacturer,
+ &usb_string_iProduct,
+ &usb_string_iSerial,
+ &usb_string_usb_benchmark,
+ &usb_string_charging_only
+};
static int usb_address = 0;
static bool initialized = false;
@@ -310,11 +445,45 @@ static void usb_core_thread(void);
static void ack_control(struct usb_ctrlrequest* req);
+#ifdef IPOD_ARCH
+void set_serial_descriptor(void)
+{
+ static short hex[16] = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+#ifdef IPOD_VIDEO
+ uint32_t* serial = (uint32_t*)(0x20004034);
+#else
+ uint32_t* serial = (uint32_t*)(0x20002034);
+#endif
+
+ /* 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];
+ uint32_t x;
+ int i,j;
+
+ for (i = 0; i < 2; i++)
+ {
+ x = serial[i];
+ for (j=0;j<8;j++)
+ {
+ *p-- = hex[x & 0xf];
+ x >>= 4;
+ }
+ }
+
+}
+#endif
+
void usb_core_init(void)
{
if (initialized)
return;
+#ifdef IPOD_ARCH
+ set_serial_descriptor();
+#endif
+
queue_init(&usbcore_queue, false);
usb_drv_init();
#ifdef USB_STORAGE
@@ -469,43 +638,25 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
break;
case USB_DT_CONFIG:
- ptr = &config_data;
- size = sizeof config_data;
- break;
-
- case USB_DT_STRING:
- switch (index) {
- case 0: /* lang descriptor */
- ptr = &lang_descriptor;
- size = sizeof lang_descriptor;
- break;
-
- default:
- if ((unsigned)index <= (sizeof(usb_strings)/sizeof(usb_strings[0]))) {
- index -= 1;
- ptr = &usb_strings[index];
- size = usb_strings[index].size;
- }
- else {
- logf("bad string id %d", index);
- usb_drv_stall(EP_CONTROL, true);
- }
- break;
+ if(usb_drv_port_speed())
+ {
+ ptr = &config_data_hs;
+ size = sizeof config_data_hs;
+ }
+ else
+ {
+ ptr = &config_data_fs;
+ size = sizeof config_data_fs;
}
break;
- case USB_DT_INTERFACE:
- ptr = &config_data.interface_descriptor;
- size = sizeof config_data.interface_descriptor;
- break;
-
- case USB_DT_ENDPOINT:
- if (index <= NUM_ENDPOINTS) {
- ptr = &ep_descriptors[index];
- size = sizeof ep_descriptors[index];
+ case USB_DT_STRING:
+ if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
+ ptr = usb_strings[index];
+ size = usb_strings[index]->bLength;
}
else {
- logf("bad endpoint %d", index);
+ logf("bad string id %d", index);
usb_drv_stall(EP_CONTROL, true);
}
break;
@@ -515,12 +666,6 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
size = sizeof qualifier_descriptor;
break;
-/*
- case USB_DT_OTHER_SPEED_CONFIG:
- ptr = &other_speed_descriptor;
- size = sizeof other_speed_descriptor;
- break;
-*/
default:
logf("bad desc %d", req->wValue >> 8);
usb_drv_stall(EP_CONTROL, true);