2 * Implementation of generic HCD
5 #include <string.h> /* memcpy */
7 #include <minix/drivers.h> /* errno with sign */
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>
16 /*===========================================================================*
17 * Local declarations *
18 *===========================================================================*/
19 /* Thread to handle device logic */
20 static void hcd_device_thread(void *);
22 /* Procedure that locks device thread forever in case of error/completion */
23 static void hcd_device_finish(hcd_device_state
*, const char *);
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
);
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
);
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
*);
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
*);
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);
55 /*===========================================================================*
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
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
67 /*===========================================================================*
69 *===========================================================================*/
71 hcd_handle_event(hcd_device_state
* device
, hcd_event event
, hcd_reg1 val
)
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",
82 #ifdef HCD_DUMP_DEVICE_TREE
83 /* This can be unlocked to dump current USB device tree on event */
85 /* Go to the base of USB device tree and
86 * print the current state of it */
87 hcd_device_state
* base
;
91 while (NULL
!= base
->parent
)
94 USB_MSG("Current state of USB device tree:");
95 hcd_dump_tree(base
, 0);
99 /* Handle event and forward control to device thread when required */
101 case HCD_EVENT_CONNECTED
:
102 USB_ASSERT((HCD_STATE_DISCONNECTED
== device
->state
),
103 "Device not marked as 'disconnected' "
104 "for 'connection' event");
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");
113 case HCD_EVENT_DISCONNECTED
:
114 USB_ASSERT((HCD_STATE_DISCONNECTED
!= device
->state
),
115 "Device is marked as 'disconnected' "
116 "for 'disconnection' event");
118 /* Make this device and all attached children
119 * disconnect recursively */
120 hcd_disconnect_tree(device
);
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");
129 USB_MSG("Low speed device connected at "
130 "hub 0x%08X, port %u", device
, val
);
132 hcd_add_child(device
, val
, HCD_SPEED_LOW
);
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");
140 USB_MSG("Full speed device connected at "
141 "hub 0x%08X, port %u", device
, val
);
143 hcd_add_child(device
, val
, HCD_SPEED_FULL
);
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");
151 USB_MSG("High speed device connected at "
152 "hub 0x%08X, port %u", device
, val
);
154 hcd_add_child(device
, val
, HCD_SPEED_HIGH
);
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");
162 hcd_delete_child(device
, val
);
164 USB_MSG("Device disconnected from "
165 "hub 0x%08X, port %u", device
, val
);
169 case HCD_EVENT_ENDPOINT
:
170 USB_ASSERT((HCD_STATE_DISCONNECTED
!= device
->state
),
171 "Parent device is marked as 'disconnected' "
172 "for 'endpoint' event");
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
);
179 /* Check if anything at all, waits for such endpoint */
181 /* Allow device thread, waiting for endpoint
182 * event, to continue with its logic */
183 hcd_device_continue(device
, event
, val
);
185 USB_MSG("No device waits for endpoint %u", val
);
190 USB_ASSERT((HCD_STATE_DISCONNECTED
!= device
->state
),
191 "Device is marked as 'disconnected' "
194 /* Allow device thread to continue with it's logic */
195 hcd_device_continue(device
, event
, val
);
200 USB_ASSERT(0, "Illegal HCD event");
205 /*===========================================================================*
207 *===========================================================================*/
209 hcd_update_port(hcd_driver_state
* driver
, hcd_event 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");
220 /* Assign new blank device */
221 driver
->port_device
= hcd_new_device();
223 /* Associate this device with driver */
224 driver
->port_device
->driver
= driver
;
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");
234 hcd_delete_device(driver
->port_device
);
236 /* Clear port device pointer */
237 driver
->port_device
= NULL
;
241 USB_ASSERT(0, "Illegal port update event");
246 /*===========================================================================*
247 * hcd_device_thread *
248 *===========================================================================*/
250 hcd_device_thread(void * thread_args
)
252 hcd_device_state
* this_device
;
256 /* Set device thread priority higher so it
257 * won't change context unless explicitly locked */
258 _ddekit_thread_set_myprio(2);
260 /* Retrieve structures from generic data */
261 this_device
= (hcd_device_state
*)thread_args
;
263 /* Enumeration sequence */
264 if (EXIT_SUCCESS
!= hcd_enumerate(this_device
))
265 hcd_device_finish(this_device
, "USB device enumeration failed");
267 /* Tell everyone that device was connected */
268 hcd_connect_cb(this_device
);
270 /* Fully configured */
271 this_device
->state
= HCD_STATE_CONNECTED
;
273 USB_DBG("Waiting for URBs");
275 /* Start handling URB's */
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
);
282 /* Finish device handling to avoid leaving thread */
283 hcd_device_finish(this_device
, "USB device handling completed");
287 /*===========================================================================*
288 * hcd_device_finish *
289 *===========================================================================*/
291 hcd_device_finish(hcd_device_state
* this_device
, const char * finish_msg
)
295 USB_MSG("USB device handling finished with message: '%s'", finish_msg
);
299 hcd_device_wait(this_device
, HCD_EVENT_URB
, HCD_UNUSED_VAL
);
300 USB_MSG("Failed attempt to continue finished thread");
305 /*===========================================================================*
306 * hcd_get_child_for_ep *
307 *===========================================================================*/
308 static hcd_device_state
*
309 hcd_get_child_for_ep(hcd_device_state
* device
, hcd_reg1 ep
)
311 hcd_device_state
* child_found
;
312 hcd_device_state
* final_found
;
313 hcd_device_state
* child
;
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
];
327 /* ...but only if attached */
329 /* Look deeper first */
330 child_found
= hcd_get_child_for_ep(child
, ep
);
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
;
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
;
356 /*===========================================================================*
358 *===========================================================================*/
360 hcd_add_child(hcd_device_state
* parent
, hcd_reg1 port
, hcd_speed speed
)
364 USB_ASSERT(port
< HCD_CHILDREN
, "Port number too high");
365 USB_ASSERT(NULL
== parent
->child
[port
], "Child device already exists");
368 parent
->child
[port
] = hcd_new_device();
369 parent
->child
[port
]->parent
= parent
;
371 /* Inherit parent's driver */
372 parent
->child
[port
]->driver
= parent
->driver
;
374 /* Remember speed, determined by hub driver */
375 parent
->child
[port
]->speed
= speed
;
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");
384 /*===========================================================================*
386 *===========================================================================*/
388 hcd_delete_child(hcd_device_state
* parent
, hcd_reg1 port
)
390 hcd_device_state
* child
;
394 USB_ASSERT(port
< HCD_CHILDREN
, "Port number too high");
396 child
= parent
->child
[port
]; /* Child to be detached */
398 USB_ASSERT(NULL
!= child
, "Child device does not exist");
400 /* Make this child device and all its attached children
401 * disconnect recursively */
402 hcd_disconnect_tree(child
);
404 /* Delete to release device itself */
405 hcd_delete_device(child
);
407 /* Mark as released */
408 parent
->child
[port
] = NULL
;
412 /*===========================================================================*
413 * hcd_disconnect_tree *
414 *===========================================================================*/
416 hcd_disconnect_tree(hcd_device_state
* device
)
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
,
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
);
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
);
444 /* Handle device disconnection (freeing memory etc.) */
445 hcd_disconnect_device(device
);
449 /*===========================================================================*
451 *===========================================================================*/
453 hcd_dump_tree(hcd_device_state
* device
, hcd_reg1 level
)
457 /* DEBUG_DUMP; */ /* Let's keep tree output cleaner */
459 USB_MSG("Device on level %03u: 0x%08X", level
, device
);
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);
469 /*===========================================================================*
471 *===========================================================================*/
473 hcd_enumerate(hcd_device_state
* this_device
)
475 hcd_driver_state
* d
;
479 d
= this_device
->driver
;
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");
492 /* Default MaxPacketSize, based on speed */
493 if (HCD_SPEED_HIGH
== this_device
->speed
)
494 this_device
->max_packet_size
= HCD_HS_MAXPACKETSIZE
;
496 this_device
->max_packet_size
= HCD_LS_MAXPACKETSIZE
;
498 /* Get device descriptor */
499 if (EXIT_SUCCESS
!= hcd_get_device_descriptor(this_device
)) {
500 USB_MSG("Failed to get device descriptor");
504 /* Remember max packet size from device descriptor */
505 this_device
->max_packet_size
= this_device
->device_desc
.bMaxPacketSize
;
507 /* Dump device descriptor in debug mode */
510 hcd_device_descriptor
* d
;
511 d
= &(this_device
->device_desc
);
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
);
531 /* Set reserved address */
532 if (EXIT_SUCCESS
!= hcd_set_address(this_device
)) {
533 USB_MSG("Failed to set device address");
537 /* Sleep 5msec to allow addressing */
538 hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(5));
540 /* Remember what was assigned in hardware */
541 this_device
->current_address
= this_device
->reserved_address
;
543 /* Get other descriptors */
544 if (EXIT_SUCCESS
!= hcd_get_descriptor_tree(this_device
)) {
545 USB_MSG("Failed to get configuration descriptor tree");
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");
559 USB_DBG("Enumeration completed");
565 /*===========================================================================*
566 * hcd_get_device_descriptor *
567 *===========================================================================*/
569 hcd_get_device_descriptor(hcd_device_state
* this_device
)
571 hcd_ctrlrequest setup
;
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
);
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
;
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
);
598 /* Check if URB submission completed successfully */
599 if (urb
.inout_status
) {
600 USB_MSG("URB submission failed");
604 /* Check if expected size was received */
605 if (urb
.out_size
!= setup
.wLength
) {
606 USB_MSG("URB submission returned invalid amount of data");
614 /*===========================================================================*
616 *===========================================================================*/
618 hcd_set_address(hcd_device_state
* this_device
)
620 hcd_ctrlrequest setup
;
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");
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;
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
;
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
);
651 /* Check if URB submission completed successfully */
652 if (urb
.inout_status
) {
653 USB_MSG("URB submission failed");
657 /* Check if expected size was received */
658 if (urb
.out_size
!= setup
.wLength
) {
659 USB_MSG("URB submission returned invalid amount of data");
667 /*===========================================================================*
668 * hcd_get_descriptor_tree *
669 *===========================================================================*/
671 hcd_get_descriptor_tree(hcd_device_state
* this_device
)
673 hcd_config_descriptor temp_config_descriptor
;
674 hcd_ctrlrequest setup
;
677 /* To receive data */
678 hcd_reg4 expected_length
;
679 hcd_reg1
* expected_buffer
;
686 retval
= EXIT_FAILURE
;
687 expected_buffer
= NULL
;
689 /* First part gets only configuration to find out total length */
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
);
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
;
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
);
714 /* Check if URB submission completed successfully */
715 if (urb
.inout_status
) {
716 USB_MSG("URB submission failed");
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");
728 /* Get total expected length */
729 expected_length
= UGETW(temp_config_descriptor
.wTotalLength
);
731 /* Check for abnormal value */
732 if (expected_length
> HCD_SANE_DESCRIPTOR_LENGTH
) {
733 USB_MSG("Total descriptor length declared is too high");
737 /* Get descriptor buffer to hold everything expected */
738 if (NULL
== (expected_buffer
= malloc(expected_length
))) {
739 USB_MSG("Descriptor allocation failed");
743 /* Second part gets all available descriptors */
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
;
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
;
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
);
768 /* Check if URB submission completed successfully */
769 if (urb
.inout_status
) {
770 USB_MSG("URB submission failed");
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");
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");
789 /* No errors occurred */
790 retval
= EXIT_SUCCESS
;
794 /* Release allocated buffer */
796 free(expected_buffer
);
802 /*===========================================================================*
803 * hcd_set_configuration *
804 *===========================================================================*/
806 hcd_set_configuration(hcd_device_state
* this_device
, hcd_reg1 configuration
)
808 hcd_ctrlrequest setup
;
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;
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
;
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
);
834 return urb
.inout_status
;
838 /*===========================================================================*
840 *===========================================================================*/
842 hcd_handle_urb(hcd_device_state
* this_device
)
850 urb
= this_device
->urb
;
852 USB_ASSERT(NULL
!= urb
, "No URB supplied");
853 USB_ASSERT(this_device
== urb
->target_device
, "Unknown device for URB");
855 /* Only if URB parsing was completed... */
856 if (EXIT_SUCCESS
== urb
->inout_status
) {
858 transfer_status
= EXIT_FAILURE
;
860 /* ...check for URB to handle */
862 case HCD_TRANSFER_CONTROL
:
863 transfer_status
= hcd_control_urb(
867 case HCD_TRANSFER_BULK
:
868 case HCD_TRANSFER_INTERRUPT
:
869 transfer_status
= hcd_non_control_urb(
874 USB_MSG("Unsupported transfer type 0x%02X",
879 /* In case of error, only dump message */
880 if (EXIT_SUCCESS
!= transfer_status
)
881 USB_MSG("USB transfer failed");
884 USB_MSG("Invalid URB supplied");
886 /* Perform completion routine */
887 hcd_complete_urb(this_device
);
891 /*===========================================================================*
893 *===========================================================================*/
895 hcd_complete_urb(hcd_device_state
* this_device
)
899 /* Signal scheduler that URB was handled */
900 this_device
->urb
->handled(this_device
->urb
);
902 /* Use this callback in case it is an external URB */
903 hcd_completion_cb(this_device
->urb
);
905 /* Make device forget about this URB */
906 this_device
->urb
= NULL
;
910 /*===========================================================================*
912 *===========================================================================*/
914 hcd_control_urb(hcd_device_state
* this_device
, hcd_urb
* urb
)
918 /* Assume bad values unless something different occurs later */
919 urb
->inout_status
= EINVAL
;
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");
927 /* TODO: Only EP0 can have control transfer */
928 if (HCD_DEFAULT_EP
!= urb
->endpoint
) {
929 USB_MSG("Control transfer for non zero EP");
933 /* Setup and URB directions should match */
934 if (((urb
->in_setup
->bRequestType
>> 7) & 0x01) != urb
->direction
) {
935 USB_MSG("URB Direction mismatch");
939 /* Send setup packet */
940 if (EXIT_SUCCESS
!= hcd_setup_packet(this_device
, urb
->in_setup
,
942 USB_MSG("Sending URB setup packet, failed");
943 urb
->inout_status
= EPIPE
;
947 /* Put what was read back into URB */
948 if (EXIT_SUCCESS
!= hcd_finish_setup(this_device
, urb
->inout_data
))
951 /* Write transfer output info to URB */
952 urb
->out_size
= (hcd_reg4
)this_device
->control_len
;
953 urb
->inout_status
= EXIT_SUCCESS
;
959 /*===========================================================================*
960 * hcd_non_control_urb *
961 *===========================================================================*/
963 hcd_non_control_urb(hcd_device_state
* this_device
, hcd_urb
* urb
)
966 hcd_datarequest request
;
970 /* Assume bad values unless something different occurs later */
971 urb
->inout_status
= EINVAL
;
973 /* Must have data buffer to send/receive */
974 if (NULL
== urb
->inout_data
) {
975 USB_MSG("No data packet in URB");
979 if (HCD_DEFAULT_EP
== urb
->endpoint
) {
980 USB_MSG("Non-control transfer for EP0");
984 /* Check if EP number is valid within remembered descriptor tree */
985 e
= hcd_tree_find_ep(&(this_device
->config_tree
), urb
->endpoint
);
988 USB_MSG("Invalid EP number for this device");
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");
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
;
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
;
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 */
1020 request
.interval
= urb
->interval
;
1022 request
.interval
= HCD_DEFAULT_NAKLIMIT
;
1025 /* Assign to let know how much data can be transfered at a time */
1026 request
.max_packet_size
= UGETW(e
->descriptor
.wMaxPacketSize
);
1028 /* Let know how to configure EP for speed */
1029 request
.speed
= this_device
->speed
;
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
;
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
;
1044 return EXIT_SUCCESS
;
1048 /*===========================================================================*
1049 * hcd_setup_packet *
1050 *===========================================================================*/
1052 hcd_setup_packet(hcd_device_state
* this_device
, hcd_ctrlrequest
* setup
,
1055 hcd_driver_state
* d
;
1056 hcd_reg1
* current_byte
;
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");
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 */
1073 /* Set parameters for further communication */
1074 d
->setup_device(d
->private_data
, ep
, this_device
->current_address
,
1077 /* Send setup packet */
1078 d
->setup_stage(d
->private_data
, setup
);
1080 /* Wait for response */
1081 hcd_device_wait(this_device
, HCD_EVENT_ENDPOINT
, ep
);
1083 /* Check response */
1084 if (EXIT_SUCCESS
!= d
->check_error(d
->private_data
,
1085 HCD_TRANSFER_CONTROL
,
1087 HCD_DIRECTION_UNUSED
))
1088 return EXIT_FAILURE
;
1090 /* For data packets... */
1091 if (setup
->wLength
> 0) {
1093 /* TODO: magic number */
1094 /* ...IN data packets */
1095 if (setup
->bRequestType
& 0x80) {
1099 /* Try getting data */
1100 d
->in_data_stage(d
->private_data
);
1102 /* Wait for response */
1103 hcd_device_wait(this_device
,
1104 HCD_EVENT_ENDPOINT
, ep
);
1106 /* Check response */
1107 if (EXIT_SUCCESS
!= d
->check_error(
1109 HCD_TRANSFER_CONTROL
,
1111 HCD_DIRECTION_UNUSED
))
1112 return EXIT_FAILURE
;
1114 /* Read data received as response */
1115 rx_len
= d
->read_data(d
->private_data
,
1119 current_byte
+= rx_len
;
1120 this_device
->control_len
+= rx_len
;
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 */
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 */
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");
1142 /* TODO: Unimplemented OUT DATA stage */
1143 d
->out_data_stage(d
->private_data
);
1145 return EXIT_FAILURE
;
1150 if (setup
->bRequestType
& 0x80) {
1152 /* Try confirming data receive */
1153 d
->out_status_stage(d
->private_data
);
1155 /* Wait for response */
1156 hcd_device_wait(this_device
, HCD_EVENT_ENDPOINT
, ep
);
1158 /* Check response */
1159 if (EXIT_SUCCESS
!= d
->check_error(d
->private_data
,
1160 HCD_TRANSFER_CONTROL
,
1162 HCD_DIRECTION_UNUSED
))
1163 return EXIT_FAILURE
;
1167 /* Try getting status confirmation */
1168 d
->in_status_stage(d
->private_data
);
1170 /* Wait for response */
1171 hcd_device_wait(this_device
, HCD_EVENT_ENDPOINT
, ep
);
1173 /* Check response */
1174 if (EXIT_SUCCESS
!= d
->check_error(d
->private_data
,
1175 HCD_TRANSFER_CONTROL
,
1177 HCD_DIRECTION_UNUSED
))
1178 return EXIT_FAILURE
;
1180 /* Read zero data from response to clear registers */
1181 if (0 != d
->read_data(d
->private_data
, NULL
, ep
))
1182 return EXIT_FAILURE
;
1185 return EXIT_SUCCESS
;
1189 /*===========================================================================*
1190 * hcd_finish_setup *
1191 *===========================================================================*/
1193 hcd_finish_setup(hcd_device_state
* this_device
, void * output
)
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
;
1203 /* Length is valid but output not supplied */
1205 return EXIT_SUCCESS
;
1207 /* Finally, copy when needed */
1208 memcpy(output
, this_device
->control_data
, this_device
->control_len
);
1210 return EXIT_SUCCESS
;
1214 /*===========================================================================*
1215 * hcd_data_transfer *
1216 *===========================================================================*/
1218 hcd_data_transfer(hcd_device_state
* this_device
, hcd_datarequest
* request
)
1220 hcd_driver_state
* d
;
1221 hcd_datarequest temp_req
;
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");
1234 d
= this_device
->driver
;
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
]));
1242 /* Check transfer direction first */
1243 if (HCD_DIRECTION_IN
== request
->direction
) {
1246 /* Start actual data transfer */
1247 d
->rx_stage(d
->private_data
, request
);
1249 /* Wait for response */
1250 hcd_device_wait(this_device
, HCD_EVENT_ENDPOINT
,
1253 /* Check response */
1254 if (EXIT_SUCCESS
!= d
->check_error(d
->private_data
,
1258 return EXIT_FAILURE
;
1260 /* Read data received as response */
1261 transfer_len
= d
->read_data(d
->private_data
,
1265 request
->data_left
-= transfer_len
;
1266 request
->data
+= transfer_len
;
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
;
1274 } while (0 != request
->data_left
);
1276 } else if (HCD_DIRECTION_OUT
== request
->direction
) {
1279 temp_req
= *request
;
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
;
1286 /* Alter actual transfer size */
1287 request
->data
+= temp_req
.data_left
;
1288 request
->data_left
-= temp_req
.data_left
;
1290 /* Total length shall not become negative */
1291 USB_ASSERT(request
->data_left
>= 0,
1292 "Invalid amount of transfer data calculated");
1294 /* Start actual data transfer */
1295 d
->tx_stage(d
->private_data
, &temp_req
);
1297 /* Wait for response */
1298 hcd_device_wait(this_device
, HCD_EVENT_ENDPOINT
,
1301 /* Check response */
1302 if (EXIT_SUCCESS
!= d
->check_error(d
->private_data
,
1306 return EXIT_FAILURE
;
1308 } while (0 != request
->data_left
);
1311 USB_ASSERT(0, "Invalid transfer direction");
1313 return EXIT_SUCCESS
;