1 /*
2 * Implementation of generic HCD
3 */
4
5 #include <string.h> /* memcpy */
6
7 #include <minix/drivers.h> /* errno with sign */
8
9 #include <usbd/hcd_common.h>
10 #include <usbd/hcd_ddekit.h>
11 #include <usbd/hcd_interface.h>
12 #include <usbd/hcd_schedule.h>
13 #include <usbd/usbd_common.h>
14
15
16 /*===========================================================================*
17 * Local declarations *
18 *===========================================================================*/
19 /* Thread to handle device logic */
20 static void hcd_device_thread(void *);
21
22 /* Procedure that locks device thread forever in case of error/completion */
23 static void hcd_device_finish(hcd_device_state *, const char *);
24
25 /* Procedure that finds device, waiting for given EP interrupt */
26 static hcd_device_state * hcd_get_child_for_ep(hcd_device_state *, hcd_reg1);
27
28 /* For HCD level, hub handling */
29 static void hcd_add_child(hcd_device_state *, hcd_reg1, hcd_speed);
30 static void hcd_delete_child(hcd_device_state *, hcd_reg1);
31 static void hcd_disconnect_tree(hcd_device_state *);
32 static void hcd_dump_tree(hcd_device_state *, hcd_reg1);
33
34 /* Typical USD device communication procedures */
35 static int hcd_enumerate(hcd_device_state *);
36 static int hcd_get_device_descriptor(hcd_device_state *);
37 static int hcd_set_address(hcd_device_state *);
38 static int hcd_get_descriptor_tree(hcd_device_state *);
39 static int hcd_set_configuration(hcd_device_state *, hcd_reg1);
40 static void hcd_handle_urb(hcd_device_state *);
41 static void hcd_complete_urb(hcd_device_state *);
42 static int hcd_control_urb(hcd_device_state *, hcd_urb *);
43 static int hcd_non_control_urb(hcd_device_state *, hcd_urb *);
44
45 /* For internal use by more general methods */
46 static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *, hcd_reg1);
47 static int hcd_finish_setup(hcd_device_state *, void *);
48 static int hcd_data_transfer(hcd_device_state *, hcd_datarequest *);
49
50 /* TODO: This is not meant to be explicitly visible outside DDEKit library
51 * but there is no other way to set thread priority for now */
52 extern void _ddekit_thread_set_myprio(int);
53
54
55 /*===========================================================================*
56 * Local definitions *
57 *===========================================================================*/
58 /* TODO: This was added for compatibility with DDELinux drivers that
59 * allow receiving less data than expected in URB, without error */
60 #define HCD_ANY_LENGTH 0xFFFFFFFFu
61
62 /* This doesn't seem to be specified in standard but abnormal values
63 * are unlikely so check for this was added below */
64 #define HCD_SANE_DESCRIPTOR_LENGTH 2048
65
66
67 /*===========================================================================*
68 * hcd_handle_event *
69 *===========================================================================*/
70 void
hcd_handle_event(hcd_device_state * device,hcd_event event,hcd_reg1 val)71 hcd_handle_event(hcd_device_state * device, hcd_event event, hcd_reg1 val)
72 {
73 DEBUG_DUMP;
74
75 /* Invalid device may be supplied */
76 if (EXIT_SUCCESS != hcd_check_device(device)) {
77 USB_MSG("No device available for event: 0x%02X, value: 0x%02X",
78 event, val);
79 return;
80 }
81
82 #ifdef HCD_DUMP_DEVICE_TREE
83 /* This can be unlocked to dump current USB device tree on event */
84 {
85 /* Go to the base of USB device tree and
86 * print the current state of it */
87 hcd_device_state * base;
88
89 base = device;
90
91 while (NULL != base->parent)
92 base = base->parent;
93
94 USB_MSG("Current state of USB device tree:");
95 hcd_dump_tree(base, 0);
96 }
97 #endif
98
99 /* Handle event and forward control to device thread when required */
100 switch (event) {
101 case HCD_EVENT_CONNECTED:
102 USB_ASSERT((HCD_STATE_DISCONNECTED == device->state),
103 "Device not marked as 'disconnected' "
104 "for 'connection' event");
105
106 /* Try creating new thread for device */
107 if (hcd_connect_device(device, hcd_device_thread))
108 USB_MSG("Device creation failed, nothing more "
109 "will happen until disconnected");
110
111 break;
112
113 case HCD_EVENT_DISCONNECTED:
114 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
115 "Device is marked as 'disconnected' "
116 "for 'disconnection' event");
117
118 /* Make this device and all attached children
119 * disconnect recursively */
120 hcd_disconnect_tree(device);
121
122 break;
123
124 case HCD_EVENT_PORT_LS_CONNECTED:
125 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
126 "Device is marked as 'disconnected' "
127 "for 'hub port LS attach' event");
128
129 USB_MSG("Low speed device connected at "
130 "hub 0x%p, port %u", device, val);
131
132 hcd_add_child(device, val, HCD_SPEED_LOW);
133 break;
134
135 case HCD_EVENT_PORT_FS_CONNECTED:
136 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
137 "Device is marked as 'disconnected' "
138 "for 'hub port FS attach' event");
139
140 USB_MSG("Full speed device connected at "
141 "hub 0x%p, port %u", device, val);
142
143 hcd_add_child(device, val, HCD_SPEED_FULL);
144 break;
145
146 case HCD_EVENT_PORT_HS_CONNECTED:
147 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
148 "Device is marked as 'disconnected' "
149 "for 'hub port HS attach' event");
150
151 USB_MSG("High speed device connected at "
152 "hub 0x%p, port %u", device, val);
153
154 hcd_add_child(device, val, HCD_SPEED_HIGH);
155 break;
156
157 case HCD_EVENT_PORT_DISCONNECTED:
158 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
159 "Device is marked as 'disconnected' "
160 "for 'hub port detach' event");
161
162 hcd_delete_child(device, val);
163
164 USB_MSG("Device disconnected from "
165 "hub 0x%p, port %u", device, val);
166
167 break;
168
169 case HCD_EVENT_ENDPOINT:
170 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
171 "Parent device is marked as 'disconnected' "
172 "for 'endpoint' event");
173
174 /* Alters 'device' when endpoint is allocated to
175 * child rather than parent (hub), which allows
176 * proper thread to continue */
177 device = hcd_get_child_for_ep(device, val);
178
179 /* Check if anything at all, waits for such endpoint */
180 if (device)
181 /* Allow device thread, waiting for endpoint
182 * event, to continue with its logic */
183 hcd_device_continue(device, event, val);
184 else
185 USB_MSG("No device waits for endpoint %u", val);
186
187 break;
188
189 case HCD_EVENT_URB:
190 USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
191 "Device is marked as 'disconnected' "
192 "for 'URB' event");
193
194 /* Allow device thread to continue with it's logic */
195 hcd_device_continue(device, event, val);
196
197 break;
198
199 default:
200 USB_ASSERT(0, "Illegal HCD event");
201 }
202 }
203
204
205 /*===========================================================================*
206 * hcd_update_port *
207 *===========================================================================*/
208 void
hcd_update_port(hcd_driver_state * driver,hcd_event event)209 hcd_update_port(hcd_driver_state * driver, hcd_event event)
210 {
211 DEBUG_DUMP;
212
213 switch (event) {
214 case HCD_EVENT_CONNECTED:
215 /* Check if already assigned */
216 USB_ASSERT(NULL == driver->port_device,
217 "Device was already connected before "
218 "receiving 'connection' event");
219
220 /* Assign new blank device */
221 driver->port_device = hcd_new_device();
222
223 /* Associate this device with driver */
224 driver->port_device->driver = driver;
225 break;
226
227 case HCD_EVENT_DISCONNECTED:
228 /* Check if already released */
229 USB_ASSERT(NULL != driver->port_device,
230 "Device was already disconnected before "
231 "receiving 'disconnection' event");
232
233 /* Release device */
234 hcd_delete_device(driver->port_device);
235
236 /* Clear port device pointer */
237 driver->port_device = NULL;
238 break;
239
240 default:
241 USB_ASSERT(0, "Illegal port update event");
242 }
243 }
244
245
246 /*===========================================================================*
247 * hcd_device_thread *
248 *===========================================================================*/
249 static void
hcd_device_thread(void * thread_args)250 hcd_device_thread(void * thread_args)
251 {
252 hcd_device_state * this_device;
253
254 DEBUG_DUMP;
255
256 /* Set device thread priority higher so it
257 * won't change context unless explicitly locked */
258 _ddekit_thread_set_myprio(2);
259
260 /* Retrieve structures from generic data */
261 this_device = (hcd_device_state *)thread_args;
262
263 /* Enumeration sequence */
264 if (EXIT_SUCCESS != hcd_enumerate(this_device))
265 hcd_device_finish(this_device, "USB device enumeration failed");
266
267 /* Tell everyone that device was connected */
268 hcd_connect_cb(this_device);
269
270 /* Fully configured */
271 this_device->state = HCD_STATE_CONNECTED;
272
273 USB_DBG("Waiting for URBs");
274
275 /* Start handling URB's */
276 for(;;) {
277 /* Block and wait for something like 'submit URB' */
278 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
279 hcd_handle_urb(this_device);
280 }
281
282 /* Finish device handling to avoid leaving thread */
283 hcd_device_finish(this_device, "USB device handling completed");
284 }
285
286
287 /*===========================================================================*
288 * hcd_device_finish *
289 *===========================================================================*/
290 static void
hcd_device_finish(hcd_device_state * this_device,const char * finish_msg)291 hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
292 {
293 DEBUG_DUMP;
294
295 USB_MSG("USB device handling finished with message: '%s'", finish_msg);
296
297 /* Lock forever */
298 for (;;) {
299 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
300 USB_MSG("Failed attempt to continue finished thread");
301 }
302 }
303
304
305 /*===========================================================================*
306 * hcd_get_child_for_ep *
307 *===========================================================================*/
308 static hcd_device_state *
hcd_get_child_for_ep(hcd_device_state * device,hcd_reg1 ep)309 hcd_get_child_for_ep(hcd_device_state * device, hcd_reg1 ep)
310 {
311 hcd_device_state * child_found;
312 hcd_device_state * final_found;
313 hcd_device_state * child;
314 hcd_reg1 child_num;
315
316 DEBUG_DUMP;
317
318 /* Nothing yet */
319 final_found = NULL;
320
321 /* Check if any children (and their children) wait for EP event */
322 /* Every device in tree is checked every time so errors can be found */
323 for (child_num = 0; child_num < HCD_CHILDREN; child_num++) {
324 /* Device, to be checked for EP event recursively... */
325 child = device->child[child_num];
326
327 /* ...but only if attached */
328 if (NULL != child) {
329 /* Look deeper first */
330 child_found = hcd_get_child_for_ep(child, ep);
331
332 if (NULL != child_found) {
333 /* Only one device can wait for EP event */
334 USB_ASSERT((NULL == final_found),
335 "More than one device waits for EP");
336 /* Remember what was found */
337 final_found = child_found;
338 }
339 }
340 }
341
342 /* Check this device last */
343 if ((HCD_EVENT_ENDPOINT == device->wait_event) &&
344 (ep == device->wait_ep)) {
345 /* Only one device can wait for EP event */
346 USB_ASSERT((NULL == final_found),
347 "More than one device waits for EP");
348 /* Remember what was found */
349 final_found = device;
350 }
351
352 return final_found;
353 }
354
355
356 /*===========================================================================*
357 * hcd_add_child *
358 *===========================================================================*/
359 static void
hcd_add_child(hcd_device_state * parent,hcd_reg1 port,hcd_speed speed)360 hcd_add_child(hcd_device_state * parent, hcd_reg1 port, hcd_speed speed)
361 {
362 DEBUG_DUMP;
363
364 USB_ASSERT(port < HCD_CHILDREN, "Port number too high");
365 USB_ASSERT(NULL == parent->child[port], "Child device already exists");
366
367 /* Basic addition */
368 parent->child[port] = hcd_new_device();
369 parent->child[port]->parent = parent;
370
371 /* Inherit parent's driver */
372 parent->child[port]->driver = parent->driver;
373
374 /* Remember speed, determined by hub driver */
375 parent->child[port]->speed = speed;
376
377 /* Try creating new thread for device */
378 if (hcd_connect_device(parent->child[port], hcd_device_thread))
379 USB_MSG("Device creation failed, nothing more "
380 "will happen until disconnected");
381 }
382
383
384 /*===========================================================================*
385 * hcd_delete_child *
386 *===========================================================================*/
387 static void
hcd_delete_child(hcd_device_state * parent,hcd_reg1 port)388 hcd_delete_child(hcd_device_state * parent, hcd_reg1 port)
389 {
390 hcd_device_state * child;
391
392 DEBUG_DUMP;
393
394 USB_ASSERT(port < HCD_CHILDREN, "Port number too high");
395
396 child = parent->child[port]; /* Child to be detached */
397
398 USB_ASSERT(NULL != child, "Child device does not exist");
399
400 /* Make this child device and all its attached children
401 * disconnect recursively */
402 hcd_disconnect_tree(child);
403
404 /* Delete to release device itself */
405 hcd_delete_device(child);
406
407 /* Mark as released */
408 parent->child[port] = NULL;
409 }
410
411
412 /*===========================================================================*
413 * hcd_disconnect_tree *
414 *===========================================================================*/
415 static void
hcd_disconnect_tree(hcd_device_state * device)416 hcd_disconnect_tree(hcd_device_state * device)
417 {
418 hcd_reg1 child_num;
419
420 DEBUG_DUMP;
421
422 /* Generate disconnect event for all children */
423 for (child_num = 0; child_num < HCD_CHILDREN; child_num++) {
424 if (NULL != device->child[child_num])
425 hcd_handle_event(device, HCD_EVENT_PORT_DISCONNECTED,
426 child_num);
427 }
428
429 /* If this device was detached during URB handling, some steps must be
430 * taken to ensure that no process/thread is waiting for completion */
431 if (NULL != device->urb) {
432 USB_MSG("Unplugged device had unhandled URB");
433 /* Tell device driver that device was detached */
434 /* TODO: ENODEV selected for that */
435 device->urb->inout_status = ENODEV;
436 hcd_complete_urb(device);
437 }
438
439 /* If connect callback was used before, call
440 * it's equivalent to signal disconnection */
441 if (HCD_STATE_CONNECTED == device->state)
442 hcd_disconnect_cb(device);
443
444 /* Handle device disconnection (freeing memory etc.) */
445 hcd_disconnect_device(device);
446 }
447
448
449 /*===========================================================================*
450 * hcd_dump_tree *
451 *===========================================================================*/
452 static void
hcd_dump_tree(hcd_device_state * device,hcd_reg1 level)453 hcd_dump_tree(hcd_device_state * device, hcd_reg1 level)
454 {
455 hcd_reg1 child_num;
456
457 /* DEBUG_DUMP; */ /* Let's keep tree output cleaner */
458
459 USB_MSG("Device on level %03u: 0x%p", level, device);
460
461 /* Traverse device tree recursively */
462 for (child_num = 0; child_num < HCD_CHILDREN; child_num++) {
463 if (NULL != device->child[child_num])
464 hcd_dump_tree(device->child[child_num], level + 1);
465 }
466 }
467
468
469 /*===========================================================================*
470 * hcd_enumerate *
471 *===========================================================================*/
472 static int
hcd_enumerate(hcd_device_state * this_device)473 hcd_enumerate(hcd_device_state * this_device)
474 {
475 hcd_driver_state * d;
476
477 DEBUG_DUMP;
478
479 d = this_device->driver;
480
481 /* Having a parent device also means being reseted by it
482 * so only reset devices that have no parents */
483 if (NULL == this_device->parent) {
484 /* First let driver reset device */
485 if (EXIT_SUCCESS != d->reset_device(d->private_data,
486 &(this_device->speed))) {
487 USB_MSG("Failed to reset device");
488 return EXIT_FAILURE;
489 }
490 }
491
492 /* Default MaxPacketSize, based on speed */
493 if (HCD_SPEED_HIGH == this_device->speed)
494 this_device->max_packet_size = HCD_HS_MAXPACKETSIZE;
495 else
496 this_device->max_packet_size = HCD_LS_MAXPACKETSIZE;
497
498 /* Get device descriptor */
499 if (EXIT_SUCCESS != hcd_get_device_descriptor(this_device)) {
500 USB_MSG("Failed to get device descriptor");
501 return EXIT_FAILURE;
502 }
503
504 /* Remember max packet size from device descriptor */
505 this_device->max_packet_size = this_device->device_desc.bMaxPacketSize;
506
507 /* Dump device descriptor in debug mode */
508 #ifdef DEBUG
509 {
510 hcd_device_descriptor * d;
511 d = &(this_device->device_desc);
512
513 USB_DBG("<<DEVICE>>");
514 USB_DBG("bLength %02X", d->bLength);
515 USB_DBG("bDescriptorType %02X", d->bDescriptorType);
516 USB_DBG("bcdUSB %04X", UGETW(d->bcdUSB));
517 USB_DBG("bDeviceClass %02X", d->bDeviceClass);
518 USB_DBG("bDeviceSubClass %02X", d->bDeviceSubClass);
519 USB_DBG("bDeviceProtocol %02X", d->bDeviceProtocol);
520 USB_DBG("bMaxPacketSize %02X", d->bMaxPacketSize);
521 USB_DBG("idVendor %04X", UGETW(d->idVendor));
522 USB_DBG("idProduct %04X", UGETW(d->idProduct));
523 USB_DBG("bcdDevice %04X", UGETW(d->bcdDevice));
524 USB_DBG("iManufacturer %02X", d->iManufacturer);
525 USB_DBG("iProduct %02X", d->iProduct);
526 USB_DBG("iSerialNumber %02X", d->iSerialNumber);
527 USB_DBG("bNumConfigurations %02X", d->bNumConfigurations);
528 }
529 #endif
530
531 /* Set reserved address */
532 if (EXIT_SUCCESS != hcd_set_address(this_device)) {
533 USB_MSG("Failed to set device address");
534 return EXIT_FAILURE;
535 }
536
537 /* Sleep 5msec to allow addressing */
538 hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(5));
539
540 /* Remember what was assigned in hardware */
541 this_device->current_address = this_device->reserved_address;
542
543 /* Get other descriptors */
544 if (EXIT_SUCCESS != hcd_get_descriptor_tree(this_device)) {
545 USB_MSG("Failed to get configuration descriptor tree");
546 return EXIT_FAILURE;
547 }
548
549 /* TODO: Always use first configuration, as there is no support for
550 * multiple configurations in DDEKit/devman and devices rarely have
551 * more than one anyway */
552 /* Set configuration */
553 if (EXIT_SUCCESS != hcd_set_configuration(this_device,
554 HCD_SET_CONFIG_NUM(HCD_DEFAULT_CONFIG))) {
555 USB_MSG("Failed to set configuration");
556 return EXIT_FAILURE;
557 }
558
559 USB_DBG("Enumeration completed");
560
561 return EXIT_SUCCESS;
562 }
563
564
565 /*===========================================================================*
566 * hcd_get_device_descriptor *
567 *===========================================================================*/
568 static int
hcd_get_device_descriptor(hcd_device_state * this_device)569 hcd_get_device_descriptor(hcd_device_state * this_device)
570 {
571 hcd_ctrlrequest setup;
572 hcd_urb urb;
573
574 DEBUG_DUMP;
575
576 /* TODO: magic numbers, no header for these */
577 /* Format setup packet */
578 setup.bRequestType = 0x80; /* IN */
579 setup.bRequest = 0x06; /* Get descriptor */
580 setup.wValue = 0x0100; /* Device */
581 setup.wIndex = 0x0000;
582 setup.wLength = sizeof(this_device->device_desc);
583
584 /* Prepare self-URB */
585 memset(&urb, 0, sizeof(urb));
586 urb.direction = HCD_DIRECTION_IN;
587 urb.endpoint = HCD_DEFAULT_EP;
588 urb.in_setup = &setup;
589 urb.inout_data = (hcd_reg1 *)(&(this_device->device_desc));
590 urb.target_device = this_device;
591 urb.type = HCD_TRANSFER_CONTROL;
592
593 /* Put it to be scheduled and wait for control to get back */
594 hcd_schedule_internal_urb(&urb);
595 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
596 hcd_handle_urb(this_device);
597
598 /* Check if URB submission completed successfully */
599 if (urb.inout_status) {
600 USB_MSG("URB submission failed");
601 return EXIT_FAILURE;
602 }
603
604 /* Check if expected size was received */
605 if (urb.out_size != setup.wLength) {
606 USB_MSG("URB submission returned invalid amount of data");
607 return EXIT_FAILURE;
608 }
609
610 return EXIT_SUCCESS;
611 }
612
613
614 /*===========================================================================*
615 * hcd_set_address *
616 *===========================================================================*/
617 static int
hcd_set_address(hcd_device_state * this_device)618 hcd_set_address(hcd_device_state * this_device)
619 {
620 hcd_ctrlrequest setup;
621 hcd_urb urb;
622
623 DEBUG_DUMP;
624
625 /* Check for legal USB device address (must be non-zero as well) */
626 USB_ASSERT((this_device->reserved_address > HCD_DEFAULT_ADDR) &&
627 (this_device->reserved_address <= HCD_LAST_ADDR),
628 "Illegal device address supplied");
629
630 /* TODO: magic numbers, no header for these */
631 setup.bRequestType = 0x00; /* OUT */
632 setup.bRequest = 0x05; /* Set address */
633 setup.wValue = this_device->reserved_address;
634 setup.wIndex = 0x0000;
635 setup.wLength = 0x0000;
636
637 /* Prepare self-URB */
638 memset(&urb, 0, sizeof(urb));
639 urb.direction = HCD_DIRECTION_OUT;
640 urb.endpoint = HCD_DEFAULT_EP;
641 urb.in_setup = &setup;
642 urb.inout_data = NULL;
643 urb.target_device = this_device;
644 urb.type = HCD_TRANSFER_CONTROL;
645
646 /* Put it to be scheduled and wait for control to get back */
647 hcd_schedule_internal_urb(&urb);
648 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
649 hcd_handle_urb(this_device);
650
651 /* Check if URB submission completed successfully */
652 if (urb.inout_status) {
653 USB_MSG("URB submission failed");
654 return EXIT_FAILURE;
655 }
656
657 /* Check if expected size was received */
658 if (urb.out_size != setup.wLength) {
659 USB_MSG("URB submission returned invalid amount of data");
660 return EXIT_FAILURE;
661 }
662
663 return EXIT_SUCCESS;
664 }
665
666
667 /*===========================================================================*
668 * hcd_get_descriptor_tree *
669 *===========================================================================*/
670 static int
hcd_get_descriptor_tree(hcd_device_state * this_device)671 hcd_get_descriptor_tree(hcd_device_state * this_device)
672 {
673 hcd_config_descriptor temp_config_descriptor;
674 hcd_ctrlrequest setup;
675 hcd_urb urb;
676
677 /* To receive data */
678 hcd_reg4 expected_length;
679 hcd_reg1 * expected_buffer;
680
681 int retval;
682
683 DEBUG_DUMP;
684
685 /* Initially */
686 retval = EXIT_FAILURE;
687 expected_buffer = NULL;
688
689 /* First part gets only configuration to find out total length */
690 {
691 /* TODO: Default configuration is hard-coded
692 * but others are rarely used anyway */
693 /* TODO: magic numbers, no header for these */
694 setup.bRequestType = 0x80; /* IN */
695 setup.bRequest = 0x06; /* Get descriptor */
696 setup.wValue = 0x0200 | HCD_DEFAULT_CONFIG;
697 setup.wIndex = 0x0000;
698 setup.wLength = sizeof(temp_config_descriptor);
699
700 /* Prepare self-URB */
701 memset(&urb, 0, sizeof(urb));
702 urb.direction = HCD_DIRECTION_IN;
703 urb.endpoint = HCD_DEFAULT_EP;
704 urb.in_setup = &setup;
705 urb.inout_data = (hcd_reg1 *)(&temp_config_descriptor);
706 urb.target_device = this_device;
707 urb.type = HCD_TRANSFER_CONTROL;
708
709 /* Put it to be scheduled and wait for control to get back */
710 hcd_schedule_internal_urb(&urb);
711 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
712 hcd_handle_urb(this_device);
713
714 /* Check if URB submission completed successfully */
715 if (urb.inout_status) {
716 USB_MSG("URB submission failed");
717 goto FINISH;
718 }
719
720 /* Check if expected size was received */
721 if (urb.out_size != setup.wLength) {
722 USB_MSG("URB submission returned "
723 "invalid amount of data");
724 goto FINISH;
725 }
726 }
727
728 /* Get total expected length */
729 expected_length = UGETW(temp_config_descriptor.wTotalLength);
730
731 /* Check for abnormal value */
732 if (expected_length > HCD_SANE_DESCRIPTOR_LENGTH) {
733 USB_MSG("Total descriptor length declared is too high");
734 goto FINISH;
735 }
736
737 /* Get descriptor buffer to hold everything expected */
738 if (NULL == (expected_buffer = malloc(expected_length))) {
739 USB_MSG("Descriptor allocation failed");
740 goto FINISH;
741 }
742
743 /* Second part gets all available descriptors */
744 {
745 /* TODO: Default configuration is hard-coded
746 * but others are rarely used anyway */
747 /* TODO: magic numbers, no header for these */
748 setup.bRequestType = 0x80; /* IN */
749 setup.bRequest = 0x06; /* Get descriptor */
750 setup.wValue = 0x0200 | HCD_DEFAULT_CONFIG;
751 setup.wIndex = 0x0000;
752 setup.wLength = expected_length;
753
754 /* Prepare self-URB */
755 memset(&urb, 0, sizeof(urb));
756 urb.direction = HCD_DIRECTION_IN;
757 urb.endpoint = HCD_DEFAULT_EP;
758 urb.in_setup = &setup;
759 urb.inout_data = expected_buffer;
760 urb.target_device = this_device;
761 urb.type = HCD_TRANSFER_CONTROL;
762
763 /* Put it to be scheduled and wait for control to get back */
764 hcd_schedule_internal_urb(&urb);
765 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
766 hcd_handle_urb(this_device);
767
768 /* Check if URB submission completed successfully */
769 if (urb.inout_status) {
770 USB_MSG("URB submission failed");
771 goto FINISH;
772 }
773
774 /* Check if expected size was received */
775 if (urb.out_size != setup.wLength) {
776 USB_MSG("URB submission returned "
777 "invalid amount of data");
778 goto FINISH;
779 }
780 }
781
782 if (EXIT_SUCCESS != hcd_buffer_to_tree(expected_buffer,
783 (int)expected_length,
784 &(this_device->config_tree))) {
785 USB_MSG("Broken descriptor data");
786 goto FINISH;
787 }
788
789 /* No errors occurred */
790 retval = EXIT_SUCCESS;
791
792 FINISH:
793
794 /* Release allocated buffer */
795 if (expected_buffer)
796 free(expected_buffer);
797
798 return retval;
799 }
800
801
802 /*===========================================================================*
803 * hcd_set_configuration *
804 *===========================================================================*/
805 static int
hcd_set_configuration(hcd_device_state * this_device,hcd_reg1 configuration)806 hcd_set_configuration(hcd_device_state * this_device, hcd_reg1 configuration)
807 {
808 hcd_ctrlrequest setup;
809 hcd_urb urb;
810
811 DEBUG_DUMP;
812
813 /* TODO: magic numbers, no header for these */
814 setup.bRequestType = 0x00; /* OUT */
815 setup.bRequest = 0x09; /* Set configuration */
816 setup.wValue = configuration;
817 setup.wIndex = 0x0000;
818 setup.wLength = 0x0000;
819
820 /* Prepare self-URB */
821 memset(&urb, 0, sizeof(urb));
822 urb.direction = HCD_DIRECTION_OUT;
823 urb.endpoint = HCD_DEFAULT_EP;
824 urb.in_setup = &setup;
825 urb.inout_data = NULL;
826 urb.target_device = this_device;
827 urb.type = HCD_TRANSFER_CONTROL;
828
829 /* Put it to be scheduled and wait for control to get back */
830 hcd_schedule_internal_urb(&urb);
831 hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
832 hcd_handle_urb(this_device);
833
834 return urb.inout_status;
835 }
836
837
838 /*===========================================================================*
839 * hcd_handle_urb *
840 *===========================================================================*/
841 static void
hcd_handle_urb(hcd_device_state * this_device)842 hcd_handle_urb(hcd_device_state * this_device)
843 {
844 hcd_urb * urb;
845 int transfer_status;
846
847 DEBUG_DUMP;
848
849 /* Retrieve URB */
850 urb = this_device->urb;
851
852 USB_ASSERT(NULL != urb, "No URB supplied");
853 USB_ASSERT(this_device == urb->target_device, "Unknown device for URB");
854
855 /* Only if URB parsing was completed... */
856 if (EXIT_SUCCESS == urb->inout_status) {
857
858 transfer_status = EXIT_FAILURE;
859
860 /* ...check for URB to handle */
861 switch (urb->type) {
862 case HCD_TRANSFER_CONTROL:
863 transfer_status = hcd_control_urb(
864 this_device, urb);
865 break;
866
867 case HCD_TRANSFER_BULK:
868 case HCD_TRANSFER_INTERRUPT:
869 transfer_status = hcd_non_control_urb(
870 this_device, urb);
871 break;
872
873 default:
874 USB_MSG("Unsupported transfer type 0x%02X",
875 (int)urb->type);
876 break;
877 }
878
879 /* In case of error, only dump message */
880 if (EXIT_SUCCESS != transfer_status)
881 USB_MSG("USB transfer failed");
882
883 } else
884 USB_MSG("Invalid URB supplied");
885
886 /* Perform completion routine */
887 hcd_complete_urb(this_device);
888 }
889
890
891 /*===========================================================================*
892 * hcd_complete_urb *
893 *===========================================================================*/
894 static void
hcd_complete_urb(hcd_device_state * this_device)895 hcd_complete_urb(hcd_device_state * this_device)
896 {
897 DEBUG_DUMP;
898
899 /* Signal scheduler that URB was handled */
900 this_device->urb->handled(this_device->urb);
901
902 /* Use this callback in case it is an external URB */
903 hcd_completion_cb(this_device->urb);
904
905 /* Make device forget about this URB */
906 this_device->urb = NULL;
907 }
908
909
910 /*===========================================================================*
911 * hcd_control_urb *
912 *===========================================================================*/
913 static int
hcd_control_urb(hcd_device_state * this_device,hcd_urb * urb)914 hcd_control_urb(hcd_device_state * this_device, hcd_urb * urb)
915 {
916 DEBUG_DUMP;
917
918 /* Assume bad values unless something different occurs later */
919 urb->inout_status = EINVAL;
920
921 /* Must have setup packet for control transfer */
922 if (NULL == urb->in_setup) {
923 USB_MSG("No setup packet in URB, for control transfer");
924 return EXIT_FAILURE;
925 }
926
927 /* TODO: Only EP0 can have control transfer */
928 if (HCD_DEFAULT_EP != urb->endpoint) {
929 USB_MSG("Control transfer for non zero EP");
930 return EXIT_FAILURE;
931 }
932
933 /* Setup and URB directions should match */
934 if (((urb->in_setup->bRequestType >> 7) & 0x01) != urb->direction) {
935 USB_MSG("URB Direction mismatch");
936 return EXIT_FAILURE;
937 }
938
939 /* Send setup packet */
940 if (EXIT_SUCCESS != hcd_setup_packet(this_device, urb->in_setup,
941 urb->endpoint)) {
942 USB_MSG("Sending URB setup packet, failed");
943 urb->inout_status = EPIPE;
944 return EXIT_FAILURE;
945 }
946
947 /* Put what was read back into URB */
948 if (EXIT_SUCCESS != hcd_finish_setup(this_device, urb->inout_data))
949 return EXIT_FAILURE;
950
951 /* Write transfer output info to URB */
952 urb->out_size = (hcd_reg4)this_device->control_len;
953 urb->inout_status = EXIT_SUCCESS;
954
955 return EXIT_SUCCESS;
956 }
957
958
959 /*===========================================================================*
960 * hcd_non_control_urb *
961 *===========================================================================*/
962 static int
hcd_non_control_urb(hcd_device_state * this_device,hcd_urb * urb)963 hcd_non_control_urb(hcd_device_state * this_device, hcd_urb * urb)
964 {
965 hcd_endpoint * e;
966 hcd_datarequest request;
967
968 DEBUG_DUMP;
969
970 /* Assume bad values unless something different occurs later */
971 urb->inout_status = EINVAL;
972
973 /* Must have data buffer to send/receive */
974 if (NULL == urb->inout_data) {
975 USB_MSG("No data packet in URB");
976 return EXIT_FAILURE;
977 }
978
979 if (HCD_DEFAULT_EP == urb->endpoint) {
980 USB_MSG("Non-control transfer for EP0");
981 return EXIT_FAILURE;
982 }
983
984 /* Check if EP number is valid within remembered descriptor tree */
985 e = hcd_tree_find_ep(&(this_device->config_tree), urb->endpoint);
986
987 if (NULL == e) {
988 USB_MSG("Invalid EP number for this device");
989 return EXIT_FAILURE;
990 }
991
992 /* Check if remembered descriptor direction, matches the one in URB */
993 if (((e->descriptor.bEndpointAddress >> 7) & 0x01) != urb->direction) {
994 USB_MSG("EP direction mismatch");
995 return EXIT_FAILURE;
996 }
997
998 /* Check if remembered type matches */
999 if (UE_GET_XFERTYPE(e->descriptor.bmAttributes) != urb->type) {
1000 USB_MSG("EP type mismatch");
1001 return EXIT_FAILURE;
1002 }
1003
1004 /* Check if remembered interval matches */
1005 if ((hcd_reg1)e->descriptor.bInterval != urb->interval) {
1006 USB_MSG("EP interval mismatch");
1007 return EXIT_FAILURE;
1008 }
1009
1010 /* Assign URB values to data request structure */
1011 request.type = urb->type;
1012 request.endpoint = urb->endpoint;
1013 request.direction = urb->direction;
1014 request.data_left = (int)urb->in_size;
1015 request.data = urb->inout_data;
1016 /* TODO: This was changed to allow software scheduler to work correctly
1017 * by switching URBs when they NAK, rather than waiting forever if URB
1018 * which requires such waiting, was issued */
1019 #if 0
1020 request.interval = urb->interval;
1021 #else
1022 request.interval = HCD_DEFAULT_NAKLIMIT;
1023 #endif
1024
1025 /* Assign to let know how much data can be transfered at a time */
1026 request.max_packet_size = UGETW(e->descriptor.wMaxPacketSize);
1027
1028 /* Let know how to configure EP for speed */
1029 request.speed = this_device->speed;
1030
1031 /* Start sending data */
1032 if (EXIT_SUCCESS != hcd_data_transfer(this_device, &request)) {
1033 USB_MSG("URB non-control transfer, failed");
1034 urb->inout_status = EPIPE;
1035 return EXIT_FAILURE;
1036 }
1037
1038 /* Transfer successfully completed update URB */
1039 USB_ASSERT(request.data_left >= 0,
1040 "Negative amount of transfer data remains");
1041 urb->out_size = urb->in_size - (hcd_reg4)request.data_left;
1042 urb->inout_status = EXIT_SUCCESS;
1043
1044 return EXIT_SUCCESS;
1045 }
1046
1047
1048 /*===========================================================================*
1049 * hcd_setup_packet *
1050 *===========================================================================*/
1051 static int
hcd_setup_packet(hcd_device_state * this_device,hcd_ctrlrequest * setup,hcd_reg1 ep)1052 hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
1053 hcd_reg1 ep)
1054 {
1055 hcd_driver_state * d;
1056 hcd_reg1 * current_byte;
1057 int rx_len;
1058
1059 DEBUG_DUMP;
1060
1061 /* Should have been set at enumeration or with default values */
1062 USB_ASSERT(this_device->max_packet_size >= HCD_LS_MAXPACKETSIZE,
1063 "Illegal MaxPacketSize");
1064 USB_ASSERT(ep <= HCD_LAST_EP, "Invalid EP number");
1065 USB_ASSERT(this_device->current_address <= HCD_LAST_ADDR,
1066 "Invalid device address");
1067
1068 /* Initially... */
1069 d = this_device->driver;
1070 current_byte = this_device->control_data;/* Start reading into this */
1071 this_device->control_len = 0; /* Nothing read yet */
1072
1073 /* Set parameters for further communication */
1074 d->setup_device(d->private_data, ep, this_device->current_address,
1075 NULL, NULL);
1076
1077 /* Send setup packet */
1078 d->setup_stage(d->private_data, setup);
1079
1080 /* Wait for response */
1081 hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
1082
1083 /* Check response */
1084 if (EXIT_SUCCESS != d->check_error(d->private_data,
1085 HCD_TRANSFER_CONTROL,
1086 ep,
1087 HCD_DIRECTION_UNUSED))
1088 return EXIT_FAILURE;
1089
1090 /* For data packets... */
1091 if (setup->wLength > 0) {
1092
1093 /* TODO: magic number */
1094 /* ...IN data packets */
1095 if (setup->bRequestType & 0x80) {
1096
1097 for(;;) {
1098
1099 /* Try getting data */
1100 d->in_data_stage(d->private_data);
1101
1102 /* Wait for response */
1103 hcd_device_wait(this_device,
1104 HCD_EVENT_ENDPOINT, ep);
1105
1106 /* Check response */
1107 if (EXIT_SUCCESS != d->check_error(
1108 d->private_data,
1109 HCD_TRANSFER_CONTROL,
1110 ep,
1111 HCD_DIRECTION_UNUSED))
1112 return EXIT_FAILURE;
1113
1114 /* Read data received as response */
1115 rx_len = d->read_data(d->private_data,
1116 current_byte, ep);
1117
1118 /* Increment */
1119 current_byte += rx_len;
1120 this_device->control_len += rx_len;
1121
1122 /* If max sized packet was read (or more)... */
1123 if (rx_len >= (int)this_device->max_packet_size)
1124 /* ...try reading next packet even if
1125 * zero bytes may be received */
1126 continue;
1127
1128 /* If less than max data was read... */
1129 if (rx_len < (int)this_device->max_packet_size)
1130 /* ...it must have been
1131 * the last packet */
1132 break;
1133
1134 /* Unreachable during normal operation */
1135 USB_MSG("rx_len: %d; max_packet_size: %d",
1136 rx_len, this_device->max_packet_size);
1137 USB_ASSERT(0, "Illegal state of data "
1138 "receive operation");
1139 }
1140
1141 } else {
1142 /* TODO: Unimplemented OUT DATA stage */
1143 d->out_data_stage(d->private_data);
1144
1145 return EXIT_FAILURE;
1146 }
1147 }
1148
1149 /* Status stages */
1150 if (setup->bRequestType & 0x80) {
1151
1152 /* Try confirming data receive */
1153 d->out_status_stage(d->private_data);
1154
1155 /* Wait for response */
1156 hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
1157
1158 /* Check response */
1159 if (EXIT_SUCCESS != d->check_error(d->private_data,
1160 HCD_TRANSFER_CONTROL,
1161 ep,
1162 HCD_DIRECTION_UNUSED))
1163 return EXIT_FAILURE;
1164
1165 } else {
1166
1167 /* Try getting status confirmation */
1168 d->in_status_stage(d->private_data);
1169
1170 /* Wait for response */
1171 hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
1172
1173 /* Check response */
1174 if (EXIT_SUCCESS != d->check_error(d->private_data,
1175 HCD_TRANSFER_CONTROL,
1176 ep,
1177 HCD_DIRECTION_UNUSED))
1178 return EXIT_FAILURE;
1179
1180 /* Read zero data from response to clear registers */
1181 if (0 != d->read_data(d->private_data, NULL, ep))
1182 return EXIT_FAILURE;
1183 }
1184
1185 return EXIT_SUCCESS;
1186 }
1187
1188
1189 /*===========================================================================*
1190 * hcd_finish_setup *
1191 *===========================================================================*/
1192 static int
hcd_finish_setup(hcd_device_state * this_device,void * output)1193 hcd_finish_setup(hcd_device_state * this_device, void * output)
1194 {
1195 DEBUG_DUMP;
1196
1197 /* Validate setup transfer output length */
1198 if (this_device->control_len < 0) {
1199 USB_MSG("Negative control transfer output length");
1200 return EXIT_FAILURE;
1201 }
1202
1203 /* Length is valid but output not supplied */
1204 if (NULL == output)
1205 return EXIT_SUCCESS;
1206
1207 /* Finally, copy when needed */
1208 memcpy(output, this_device->control_data, this_device->control_len);
1209
1210 return EXIT_SUCCESS;
1211 }
1212
1213
1214 /*===========================================================================*
1215 * hcd_data_transfer *
1216 *===========================================================================*/
1217 static int
hcd_data_transfer(hcd_device_state * this_device,hcd_datarequest * request)1218 hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
1219 {
1220 hcd_driver_state * d;
1221 hcd_datarequest temp_req;
1222 int transfer_len;
1223
1224 DEBUG_DUMP;
1225
1226 USB_ASSERT((request->endpoint <= HCD_LAST_EP) &&
1227 (request->endpoint > HCD_DEFAULT_EP),
1228 "Invalid EP number");
1229 USB_ASSERT((this_device->current_address <= HCD_LAST_ADDR) &&
1230 (this_device->current_address > HCD_DEFAULT_ADDR),
1231 "Invalid device address");
1232
1233 /* Initially... */
1234 d = this_device->driver;
1235
1236 /* Set parameters for further communication */
1237 d->setup_device(d->private_data, request->endpoint,
1238 this_device->current_address,
1239 &(this_device->ep_tx_tog[request->endpoint]),
1240 &(this_device->ep_rx_tog[request->endpoint]));
1241
1242 /* Check transfer direction first */
1243 if (HCD_DIRECTION_IN == request->direction) {
1244
1245 do {
1246 /* Start actual data transfer */
1247 d->rx_stage(d->private_data, request);
1248
1249 /* Wait for response */
1250 hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
1251 request->endpoint);
1252
1253 /* Check response */
1254 if (EXIT_SUCCESS != d->check_error(d->private_data,
1255 request->type,
1256 request->endpoint,
1257 HCD_DIRECTION_IN))
1258 return EXIT_FAILURE;
1259
1260 /* Read data received as response */
1261 transfer_len = d->read_data(d->private_data,
1262 request->data,
1263 request->endpoint);
1264
1265 request->data_left -= transfer_len;
1266 request->data += transfer_len;
1267
1268 /* Total length shall not become negative */
1269 if (request->data_left < 0) {
1270 USB_MSG("Invalid amount of data received");
1271 return EXIT_FAILURE;
1272 }
1273
1274 } while (0 != request->data_left);
1275
1276 } else if (HCD_DIRECTION_OUT == request->direction) {
1277
1278 do {
1279 temp_req = *request;
1280
1281 /* Decide temporary transfer size */
1282 if (temp_req.data_left > (int)temp_req.max_packet_size)
1283 temp_req.data_left =
1284 (int)temp_req.max_packet_size;
1285
1286 /* Alter actual transfer size */
1287 request->data += temp_req.data_left;
1288 request->data_left -= temp_req.data_left;
1289
1290 /* Total length shall not become negative */
1291 USB_ASSERT(request->data_left >= 0,
1292 "Invalid amount of transfer data calculated");
1293
1294 /* Start actual data transfer */
1295 d->tx_stage(d->private_data, &temp_req);
1296
1297 /* Wait for response */
1298 hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
1299 request->endpoint);
1300
1301 /* Check response */
1302 if (EXIT_SUCCESS != d->check_error(d->private_data,
1303 request->type,
1304 request->endpoint,
1305 HCD_DIRECTION_OUT))
1306 return EXIT_FAILURE;
1307
1308 } while (0 != request->data_left);
1309
1310 } else
1311 USB_ASSERT(0, "Invalid transfer direction");
1312
1313 return EXIT_SUCCESS;
1314 }
1315