xref: /minix/minix/drivers/usb/usbd/hcd/hcd.c (revision 9f988b79)
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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