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 7e86086dd4..13993f9271 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -23,10 +23,17 @@
23//#define LOGF_ENABLE 23//#define LOGF_ENABLE
24#include "logf.h" 24#include "logf.h"
25 25
26//#define USB_STORAGE 26#ifndef BOOTLOADER
27//#define USB_SERIAL 27//#define USB_SERIAL
28//#define USB_BENCHMARK 28//#define USB_BENCHMARK
29#ifdef USE_ROCKBOX_USB
30#define USB_STORAGE
31#else
29#define USB_CHARGING_ONLY 32#define USB_CHARGING_ONLY
33#endif /* USE_ROCKBOX_USB */
34#else
35#define USB_CHARGING_ONLY
36#endif
30 37
31#include "usb_ch9.h" 38#include "usb_ch9.h"
32#include "usb_drv.h" 39#include "usb_drv.h"
@@ -63,21 +70,21 @@ static const struct usb_device_descriptor device_descriptor = {
63 .bcdDevice = 0x0100, 70 .bcdDevice = 0x0100,
64 .iManufacturer = 1, 71 .iManufacturer = 1,
65 .iProduct = 2, 72 .iProduct = 2,
66 .iSerialNumber = 0, 73 .iSerialNumber = 3,
67 .bNumConfigurations = 1 74 .bNumConfigurations = 1
68}; 75};
69 76
70static const struct { 77static const struct {
71 struct usb_config_descriptor config_descriptor; 78 struct usb_config_descriptor config_descriptor;
72 struct usb_interface_descriptor interface_descriptor; 79 struct usb_interface_descriptor interface_descriptor;
73 struct usb_endpoint_descriptor ep1_hs_in_descriptor; 80 struct usb_endpoint_descriptor ep1_in_descriptor;
74 struct usb_endpoint_descriptor ep1_hs_out_descriptor; 81 struct usb_endpoint_descriptor ep1_out_descriptor;
75} config_data = 82} config_data_fs =
76{ 83{
77 { 84 {
78 .bLength = sizeof(struct usb_config_descriptor), 85 .bLength = sizeof(struct usb_config_descriptor),
79 .bDescriptorType = USB_DT_CONFIG, 86 .bDescriptorType = USB_DT_CONFIG,
80 .wTotalLength = sizeof config_data, 87 .wTotalLength = sizeof config_data_fs,
81 .bNumInterfaces = 1, 88 .bNumInterfaces = 1,
82 .bConfigurationValue = 1, 89 .bConfigurationValue = 1,
83 .iConfiguration = 0, 90 .iConfiguration = 0,
@@ -96,12 +103,153 @@ static const struct {
96 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 103 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
97 .bInterfaceSubClass = 0, 104 .bInterfaceSubClass = 0,
98 .bInterfaceProtocol = 0, 105 .bInterfaceProtocol = 0,
106 .iInterface = 5
107 },
108
109 {
110 .bLength = sizeof(struct usb_endpoint_descriptor),
111 .bDescriptorType = USB_DT_ENDPOINT,
112 .bEndpointAddress = EP_TX | USB_DIR_IN,
113 .bmAttributes = USB_ENDPOINT_XFER_BULK,
114 .wMaxPacketSize = 512,
115 .bInterval = 0
116 },
117 {
118 .bLength = sizeof(struct usb_endpoint_descriptor),
119 .bDescriptorType = USB_DT_ENDPOINT,
120 .bEndpointAddress = EP_RX | USB_DIR_OUT,
121 .bmAttributes = USB_ENDPOINT_XFER_BULK,
122 .wMaxPacketSize = 512,
123 .bInterval = 0
124 }
125#endif
126
127#ifdef USB_STORAGE
128 /* storage interface */
129 {
130 .bLength = sizeof(struct usb_interface_descriptor),
131 .bDescriptorType = USB_DT_INTERFACE,
132 .bInterfaceNumber = 0,
133 .bAlternateSetting = 0,
134 .bNumEndpoints = 2,
135 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
136 .bInterfaceSubClass = USB_SC_SCSI,
137 .bInterfaceProtocol = USB_PROT_BULK,
138 .iInterface = 0
139 },
140
141 {
142 .bLength = sizeof(struct usb_endpoint_descriptor),
143 .bDescriptorType = USB_DT_ENDPOINT,
144 .bEndpointAddress = EP_TX | USB_DIR_IN,
145 .bmAttributes = USB_ENDPOINT_XFER_BULK,
146 .wMaxPacketSize = 16,
147 .bInterval = 0
148 },
149 {
150 .bLength = sizeof(struct usb_endpoint_descriptor),
151 .bDescriptorType = USB_DT_ENDPOINT,
152 .bEndpointAddress = EP_RX | USB_DIR_OUT,
153 .bmAttributes = USB_ENDPOINT_XFER_BULK,
154 .wMaxPacketSize = 16,
155 .bInterval = 0
156 }
157#endif
158
159#ifdef USB_SERIAL
160 /* serial interface */
161 {
162 .bLength = sizeof(struct usb_interface_descriptor),
163 .bDescriptorType = USB_DT_INTERFACE,
164 .bInterfaceNumber = 0,
165 .bAlternateSetting = 0,
166 .bNumEndpoints = 2,
167 .bInterfaceClass = USB_CLASS_CDC_DATA,
168 .bInterfaceSubClass = 0,
169 .bInterfaceProtocol = 0,
170 .iInterface = 0
171 },
172
173 {
174 .bLength = sizeof(struct usb_endpoint_descriptor),
175 .bDescriptorType = USB_DT_ENDPOINT,
176 .bEndpointAddress = EP_TX | USB_DIR_IN,
177 .bmAttributes = USB_ENDPOINT_XFER_BULK,
178 .wMaxPacketSize = 64,
179 .bInterval = 0
180 },
181 {
182 .bLength = sizeof(struct usb_endpoint_descriptor),
183 .bDescriptorType = USB_DT_ENDPOINT,
184 .bEndpointAddress = EP_RX | USB_DIR_OUT,
185 .bmAttributes = USB_ENDPOINT_XFER_BULK,
186 .wMaxPacketSize = 64,
187 .bInterval = 0
188 }
189#endif
190
191#ifdef USB_BENCHMARK
192 /* bulk test interface */
193 {
194 .bLength = sizeof(struct usb_interface_descriptor),
195 .bDescriptorType = USB_DT_INTERFACE,
196 .bInterfaceNumber = 0,
197 .bAlternateSetting = 0,
198 .bNumEndpoints = 2,
199 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
200 .bInterfaceSubClass = 255,
201 .bInterfaceProtocol = 255,
99 .iInterface = 4 202 .iInterface = 4
100 }, 203 },
101 204
102 { 205 {
103 .bLength = sizeof(struct usb_endpoint_descriptor), 206 .bLength = sizeof(struct usb_endpoint_descriptor),
104 .bDescriptorType = USB_DT_ENDPOINT, 207 .bDescriptorType = USB_DT_ENDPOINT,
208 .bEndpointAddress = EP_RX | USB_DIR_OUT,
209 .bmAttributes = USB_ENDPOINT_XFER_BULK,
210 .wMaxPacketSize = 64,
211 .bInterval = 0
212 },
213 {
214 .bLength = sizeof(struct usb_endpoint_descriptor),
215 .bDescriptorType = USB_DT_ENDPOINT,
216 .bEndpointAddress = EP_TX | USB_DIR_IN,
217 .bmAttributes = USB_ENDPOINT_XFER_BULK,
218 .wMaxPacketSize = 64,
219 .bInterval = 0
220 }
221#endif
222},
223config_data_hs =
224{
225 {
226 .bLength = sizeof(struct usb_config_descriptor),
227 .bDescriptorType = USB_DT_CONFIG,
228 .wTotalLength = sizeof config_data_hs,
229 .bNumInterfaces = 1,
230 .bConfigurationValue = 1,
231 .iConfiguration = 0,
232 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
233 .bMaxPower = 250, /* 500mA in 2mA units */
234 },
235
236#ifdef USB_CHARGING_ONLY
237 /* dummy interface for charging-only */
238 {
239 .bLength = sizeof(struct usb_interface_descriptor),
240 .bDescriptorType = USB_DT_INTERFACE,
241 .bInterfaceNumber = 0,
242 .bAlternateSetting = 0,
243 .bNumEndpoints = 2,
244 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
245 .bInterfaceSubClass = 0,
246 .bInterfaceProtocol = 0,
247 .iInterface = 5
248 },
249
250 {
251 .bLength = sizeof(struct usb_endpoint_descriptor),
252 .bDescriptorType = USB_DT_ENDPOINT,
105 .bEndpointAddress = EP_TX | USB_DIR_IN, 253 .bEndpointAddress = EP_TX | USB_DIR_IN,
106 .bmAttributes = USB_ENDPOINT_XFER_BULK, 254 .bmAttributes = USB_ENDPOINT_XFER_BULK,
107 .wMaxPacketSize = 512, 255 .wMaxPacketSize = 512,
@@ -168,7 +316,7 @@ static const struct {
168 .bDescriptorType = USB_DT_ENDPOINT, 316 .bDescriptorType = USB_DT_ENDPOINT,
169 .bEndpointAddress = EP_TX | USB_DIR_IN, 317 .bEndpointAddress = EP_TX | USB_DIR_IN,
170 .bmAttributes = USB_ENDPOINT_XFER_BULK, 318 .bmAttributes = USB_ENDPOINT_XFER_BULK,
171 .wMaxPacketSize = 64, 319 .wMaxPacketSize = 512,
172 .bInterval = 0 320 .bInterval = 0
173 }, 321 },
174 { 322 {
@@ -176,7 +324,7 @@ static const struct {
176 .bDescriptorType = USB_DT_ENDPOINT, 324 .bDescriptorType = USB_DT_ENDPOINT,
177 .bEndpointAddress = EP_RX | USB_DIR_OUT, 325 .bEndpointAddress = EP_RX | USB_DIR_OUT,
178 .bmAttributes = USB_ENDPOINT_XFER_BULK, 326 .bmAttributes = USB_ENDPOINT_XFER_BULK,
179 .wMaxPacketSize = 64, 327 .wMaxPacketSize = 512,
180 .bInterval = 0 328 .bInterval = 0
181 } 329 }
182#endif 330#endif
@@ -192,7 +340,7 @@ static const struct {
192 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 340 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
193 .bInterfaceSubClass = 255, 341 .bInterfaceSubClass = 255,
194 .bInterfaceProtocol = 255, 342 .bInterfaceProtocol = 255,
195 .iInterface = 3 343 .iInterface = 4
196 }, 344 },
197 345
198 { 346 {
@@ -200,7 +348,6 @@ static const struct {
200 .bDescriptorType = USB_DT_ENDPOINT, 348 .bDescriptorType = USB_DT_ENDPOINT,
201 .bEndpointAddress = EP_RX | USB_DIR_OUT, 349 .bEndpointAddress = EP_RX | USB_DIR_OUT,
202 .bmAttributes = USB_ENDPOINT_XFER_BULK, 350 .bmAttributes = USB_ENDPOINT_XFER_BULK,
203// .wMaxPacketSize = 64,
204 .wMaxPacketSize = 512, 351 .wMaxPacketSize = 512,
205 .bInterval = 0 352 .bInterval = 0
206 }, 353 },
@@ -209,7 +356,6 @@ static const struct {
209 .bDescriptorType = USB_DT_ENDPOINT, 356 .bDescriptorType = USB_DT_ENDPOINT,
210 .bEndpointAddress = EP_TX | USB_DIR_IN, 357 .bEndpointAddress = EP_TX | USB_DIR_IN,
211 .bmAttributes = USB_ENDPOINT_XFER_BULK, 358 .bmAttributes = USB_ENDPOINT_XFER_BULK,
212// .wMaxPacketSize = 64,
213 .wMaxPacketSize = 512, 359 .wMaxPacketSize = 512,
214 .bInterval = 0 360 .bInterval = 0
215 } 361 }
@@ -228,72 +374,61 @@ static const struct usb_qualifier_descriptor qualifier_descriptor =
228 .bNumConfigurations = 1 374 .bNumConfigurations = 1
229}; 375};
230 376
231/* full speed = 12 Mbit */ 377static struct usb_string_descriptor usb_string_iManufacturer =
232static const struct usb_endpoint_descriptor ep1_fs_in_descriptor =
233{ 378{
234 .bLength = sizeof(struct usb_endpoint_descriptor), 379 24,
235 .bDescriptorType = USB_DT_ENDPOINT, 380 USB_DT_STRING,
236 .bEndpointAddress = 1 | USB_DIR_IN, 381 {'R','o','c','k','b','o','x','.','o','r','g'}
237 .bmAttributes = USB_ENDPOINT_XFER_BULK,
238 .wMaxPacketSize = 64,
239 .bInterval = 0
240}; 382};
241 383
242static const struct usb_endpoint_descriptor ep1_fs_out_descriptor = 384static struct usb_string_descriptor usb_string_iProduct =
243{ 385{
244 .bLength = sizeof(struct usb_endpoint_descriptor), 386 42,
245 .bDescriptorType = USB_DT_ENDPOINT, 387 USB_DT_STRING,
246 .bEndpointAddress = 1 | USB_DIR_OUT, 388 {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
247 .bmAttributes = USB_ENDPOINT_XFER_BULK,
248 .wMaxPacketSize = 64,
249 .bInterval = 0
250}; 389};
251 390
252static const struct usb_endpoint_descriptor* ep_descriptors[4] = 391static struct usb_string_descriptor usb_string_iSerial =
253{ 392{
254 &config_data.ep1_hs_in_descriptor, 393 34,
255 &config_data.ep1_hs_out_descriptor, 394 USB_DT_STRING,
256 &ep1_fs_in_descriptor, 395 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}
257 &ep1_fs_out_descriptor
258}; 396};
259 397
398
399/* Generic for all targets */
400
260/* this is stringid #0: languages supported */ 401/* this is stringid #0: languages supported */
261static const struct usb_string_descriptor lang_descriptor = 402static struct usb_string_descriptor lang_descriptor =
262{ 403{
263 sizeof(struct usb_string_descriptor), 404 4,
264 USB_DT_STRING, 405 USB_DT_STRING,
265 {0x0409} /* LANGID US English */ 406 {0x0409} /* LANGID US English */
266}; 407};
267 408
268/* this is stringid #1 and up: the actual strings */ 409static struct usb_string_descriptor usb_string_usb_benchmark =
269static const struct {
270 unsigned char size;
271 unsigned char type;
272 unsigned short string[32];
273} usb_strings[] =
274{ 410{
275 { 411 40,
276 24, 412 USB_DT_STRING,
277 USB_DT_STRING, 413 {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
278 {'R','o','c','k','b','o','x','.','o','r','g'}
279 },
280 {
281 42,
282 USB_DT_STRING,
283 {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
284 },
285 {
286 40,
287 USB_DT_STRING,
288 {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
289 },
290 {
291 28,
292 USB_DT_STRING,
293 {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
294 }
295}; 414};
296 415
416static struct usb_string_descriptor usb_string_charging_only =
417{
418 28,
419 USB_DT_STRING,
420 {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
421};
422
423static struct usb_string_descriptor* usb_strings[] =
424{
425 &lang_descriptor,
426 &usb_string_iManufacturer,
427 &usb_string_iProduct,
428 &usb_string_iSerial,
429 &usb_string_usb_benchmark,
430 &usb_string_charging_only
431};
297 432
298static int usb_address = 0; 433static int usb_address = 0;
299static bool initialized = false; 434static bool initialized = false;
@@ -310,11 +445,45 @@ static void usb_core_thread(void);
310 445
311static void ack_control(struct usb_ctrlrequest* req); 446static void ack_control(struct usb_ctrlrequest* req);
312 447
448#ifdef IPOD_ARCH
449void set_serial_descriptor(void)
450{
451 static short hex[16] = {'0','1','2','3','4','5','6','7',
452 '8','9','A','B','C','D','E','F'};
453#ifdef IPOD_VIDEO
454 uint32_t* serial = (uint32_t*)(0x20004034);
455#else
456 uint32_t* serial = (uint32_t*)(0x20002034);
457#endif
458
459 /* We need to convert from a little-endian 64-bit int
460 into a utf-16 string of hex characters */
461 short* p = &usb_string_iSerial.wString[15];
462 uint32_t x;
463 int i,j;
464
465 for (i = 0; i < 2; i++)
466 {
467 x = serial[i];
468 for (j=0;j<8;j++)
469 {
470 *p-- = hex[x & 0xf];
471 x >>= 4;
472 }
473 }
474
475}
476#endif
477
313void usb_core_init(void) 478void usb_core_init(void)
314{ 479{
315 if (initialized) 480 if (initialized)
316 return; 481 return;
317 482
483#ifdef IPOD_ARCH
484 set_serial_descriptor();
485#endif
486
318 queue_init(&usbcore_queue, false); 487 queue_init(&usbcore_queue, false);
319 usb_drv_init(); 488 usb_drv_init();
320#ifdef USB_STORAGE 489#ifdef USB_STORAGE
@@ -469,43 +638,25 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
469 break; 638 break;
470 639
471 case USB_DT_CONFIG: 640 case USB_DT_CONFIG:
472 ptr = &config_data; 641 if(usb_drv_port_speed())
473 size = sizeof config_data; 642 {
474 break; 643 ptr = &config_data_hs;
475 644 size = sizeof config_data_hs;
476 case USB_DT_STRING: 645 }
477 switch (index) { 646 else
478 case 0: /* lang descriptor */ 647 {
479 ptr = &lang_descriptor; 648 ptr = &config_data_fs;
480 size = sizeof lang_descriptor; 649 size = sizeof config_data_fs;
481 break;
482
483 default:
484 if ((unsigned)index <= (sizeof(usb_strings)/sizeof(usb_strings[0]))) {
485 index -= 1;
486 ptr = &usb_strings[index];
487 size = usb_strings[index].size;
488 }
489 else {
490 logf("bad string id %d", index);
491 usb_drv_stall(EP_CONTROL, true);
492 }
493 break;
494 } 650 }
495 break; 651 break;
496 652
497 case USB_DT_INTERFACE: 653 case USB_DT_STRING:
498 ptr = &config_data.interface_descriptor; 654 if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
499 size = sizeof config_data.interface_descriptor; 655 ptr = usb_strings[index];
500 break; 656 size = usb_strings[index]->bLength;
501
502 case USB_DT_ENDPOINT:
503 if (index <= NUM_ENDPOINTS) {
504 ptr = &ep_descriptors[index];
505 size = sizeof ep_descriptors[index];
506 } 657 }
507 else { 658 else {
508 logf("bad endpoint %d", index); 659 logf("bad string id %d", index);
509 usb_drv_stall(EP_CONTROL, true); 660 usb_drv_stall(EP_CONTROL, true);
510 } 661 }
511 break; 662 break;
@@ -515,12 +666,6 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
515 size = sizeof qualifier_descriptor; 666 size = sizeof qualifier_descriptor;
516 break; 667 break;
517 668
518/*
519 case USB_DT_OTHER_SPEED_CONFIG:
520 ptr = &other_speed_descriptor;
521 size = sizeof other_speed_descriptor;
522 break;
523*/
524 default: 669 default:
525 logf("bad desc %d", req->wValue >> 8); 670 logf("bad desc %d", req->wValue >> 8);
526 usb_drv_stall(EP_CONTROL, true); 671 usb_drv_stall(EP_CONTROL, true);