xref: /minix/minix/drivers/usb/usbd/hcd/hcd_common.c (revision 66318031)
1 /*
2  * Implementation of commonly used procedures for HCD handling/initialization
3  * If possible, everything OS specific should be here
4  */
5 
6 #include <string.h>			/* memset... */
7 #include <time.h>			/* nanosleep */
8 
9 #include <sys/mman.h>			/* Physical to virtual memory mapping */
10 
11 #include <ddekit/interrupt.h>		/* DDEKit based interrupt handling */
12 
13 #include <minix/clkconf.h>		/* clkconf_* */
14 #include <minix/syslib.h>		/* sys_privctl */
15 
16 #include <usbd/hcd_common.h>
17 #include <usbd/hcd_interface.h>
18 #include <usbd/usbd_common.h>
19 
20 
21 /*===========================================================================*
22  *    Local prototypes                                                       *
23  *===========================================================================*/
24 /* Descriptor related operations */
25 static int hcd_fill_configuration(hcd_reg1 *, int, hcd_configuration *, int);
26 static int hcd_fill_interface(hcd_reg1 *, int, hcd_interface *, int);
27 static int hcd_fill_endpoint(hcd_reg1 *, int, hcd_endpoint *);
28 
29 /* Handling free USB device addresses */
30 static hcd_reg1 hcd_reserve_addr(hcd_driver_state *);
31 static void hcd_release_addr(hcd_driver_state *, hcd_reg1);
32 
33 
34 /*===========================================================================*
35  *    Local definitions                                                      *
36  *===========================================================================*/
37 /* List of all allocated devices */
38 static hcd_device_state * dev_list = NULL;
39 
40 
41 /*===========================================================================*
42  *    hcd_os_interrupt_attach                                                *
43  *===========================================================================*/
44 int
hcd_os_interrupt_attach(int irq,void (* init)(void *),void (* isr)(void *),void * priv)45 hcd_os_interrupt_attach(int irq, void (*init)(void *),
46 			void (*isr)(void *), void *priv)
47 {
48 	DEBUG_DUMP;
49 
50 	if (NULL == ddekit_interrupt_attach(irq, 0, init, isr, priv)) {
51 		USB_MSG("Attaching interrupt %d failed", irq);
52 		return EXIT_FAILURE;
53 	}
54 
55 	return EXIT_SUCCESS;
56 }
57 
58 
59 /*===========================================================================*
60  *    hcd_os_interrupt_detach                                                *
61  *===========================================================================*/
62 void
hcd_os_interrupt_detach(int irq)63 hcd_os_interrupt_detach(int irq)
64 {
65 	DEBUG_DUMP;
66 	ddekit_interrupt_detach(irq);
67 }
68 
69 
70 /*===========================================================================*
71  *    hcd_os_interrupt_enable                                                *
72  *===========================================================================*/
73 void
hcd_os_interrupt_enable(int irq)74 hcd_os_interrupt_enable(int irq)
75 {
76 	DEBUG_DUMP;
77 	ddekit_interrupt_enable(irq);
78 }
79 
80 
81 /*===========================================================================*
82  *    hcd_os_interrupt_disable                                               *
83  *===========================================================================*/
84 void
hcd_os_interrupt_disable(int irq)85 hcd_os_interrupt_disable(int irq)
86 {
87 	DEBUG_DUMP;
88 	ddekit_interrupt_disable(irq);
89 }
90 
91 
92 /*===========================================================================*
93  *    hcd_os_regs_init                                                       *
94  *===========================================================================*/
95 void *
hcd_os_regs_init(hcd_addr phys_addr,unsigned long addr_len)96 hcd_os_regs_init(hcd_addr phys_addr, unsigned long addr_len)
97 {
98 	/* Memory range where we need privileged access */
99 	struct minix_mem_range mr;
100 
101 	/* NULL unless initialization was fully completed */
102 	void * virt_reg_base;
103 
104 	DEBUG_DUMP;
105 
106 	virt_reg_base = NULL;
107 
108 	/* Must have been set before */
109 	USB_ASSERT(0 != phys_addr, "Invalid base address!");
110 	USB_ASSERT(0 != addr_len, "Invalid base length!");
111 
112 	/* Set memory range for peripheral */
113 	mr.mr_base = phys_addr;
114 	mr.mr_limit = phys_addr + addr_len;
115 
116 	/* Try getting access to memory range */
117 	if (EXIT_SUCCESS == sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr)) {
118 
119 		/* And map it where we want it */
120 		virt_reg_base = vm_map_phys(SELF, (void *)phys_addr, addr_len);
121 
122 		/* Check for mapping errors to allow us returning NULL */
123 		if (MAP_FAILED == virt_reg_base) {
124 			USB_MSG("Mapping memory with vm_map_phys() failed");
125 			virt_reg_base = NULL;
126 		}
127 
128 	} else
129 		USB_MSG("Acquiring memory with sys_privctl() failed");
130 
131 	return virt_reg_base;
132 }
133 
134 
135 /*===========================================================================*
136  *    hcd_os_regs_deinit                                                     *
137  *===========================================================================*/
138 int
hcd_os_regs_deinit(hcd_addr virt_addr,unsigned long addr_len)139 hcd_os_regs_deinit(hcd_addr virt_addr, unsigned long addr_len)
140 {
141 	DEBUG_DUMP;
142 
143 	/* To keep USBD return value convention */
144 	return (0 == vm_unmap_phys(SELF, (void*)virt_addr, addr_len)) ?
145 		EXIT_SUCCESS : EXIT_FAILURE;
146 }
147 
148 
149 /*===========================================================================*
150  *    hcd_os_clkconf                                                         *
151  *===========================================================================*/
152 int
hcd_os_clkconf(unsigned long clk,unsigned long mask,unsigned long value)153 hcd_os_clkconf(unsigned long clk, unsigned long mask, unsigned long value)
154 {
155 	DEBUG_DUMP;
156 
157 	/* Apparently clkconf_init may be called more than once anyway */
158 	if ((0 == clkconf_init()) && (0 == clkconf_set(clk, mask, value)))
159 		return EXIT_SUCCESS;
160 	else
161 		return EXIT_FAILURE;
162 }
163 
164 
165 /*===========================================================================*
166  *    hcd_os_clkconf_release                                                 *
167  *===========================================================================*/
168 int
hcd_os_clkconf_release(void)169 hcd_os_clkconf_release(void)
170 {
171 	DEBUG_DUMP;
172 	return clkconf_release();
173 }
174 
175 
176 /*===========================================================================*
177  *    hcd_os_nanosleep                                                       *
178  *===========================================================================*/
179 void
hcd_os_nanosleep(int nanosec)180 hcd_os_nanosleep(int nanosec)
181 {
182 	struct timespec nanotm;
183 	int r;
184 
185 	DEBUG_DUMP;
186 
187 	if (nanosec >= HCD_NANO) {
188 		nanotm.tv_sec = nanosec / HCD_NANO;
189 		nanotm.tv_nsec = nanosec % HCD_NANO;
190 	} else {
191 		nanotm.tv_sec = 0;
192 		nanotm.tv_nsec = nanosec;
193 	}
194 
195 	/* TODO: Since it is not likely to be ever interrupted, we do not try
196 	 * to sleep for a remaining time in case of signal handling */
197 	/* Signal handling will most likely end up with termination anyway */
198 	r = nanosleep(&nanotm, NULL);
199 	USB_ASSERT(EXIT_SUCCESS == r, "Calling nanosleep() failed");
200 }
201 
202 
203 /*===========================================================================*
204  *    hcd_connect_device                                                     *
205  *===========================================================================*/
206 int
hcd_connect_device(hcd_device_state * this_device,hcd_thread_function funct)207 hcd_connect_device(hcd_device_state * this_device, hcd_thread_function funct)
208 {
209 	DEBUG_DUMP;
210 
211 	/* This is meant to allow thread name distinction
212 	 * and should not be used for anything else */
213 	static unsigned int devnum = 0;
214 
215 	/* Should be able to hold device prefix and some number */
216 	char devname[] = "dev..........";
217 
218 	USB_ASSERT((NULL == this_device->lock) &&
219 		(NULL == this_device->thread) &&
220 		(HCD_DEFAULT_ADDR == this_device->reserved_address) &&
221 		(HCD_STATE_DISCONNECTED == this_device->state),
222 		"Device structure not clean");
223 
224 	/* Mark as 'plugged in' to avoid treating device
225 	 * as 'disconnected' in case of errors below */
226 	this_device->state = HCD_STATE_CONNECTION_PENDING;
227 
228 	/* Reserve device address for further use if available */
229 	if (HCD_DEFAULT_ADDR == (this_device->reserved_address =
230 				hcd_reserve_addr(this_device->driver))) {
231 		USB_MSG("No free device addresses");
232 		return EXIT_FAILURE;
233 	}
234 
235 	/* Get 'lock' that makes device thread wait for events to occur */
236 	if (NULL == (this_device->lock = ddekit_sem_init(0))) {
237 		USB_MSG("Failed to initialize thread lock");
238 		return EXIT_FAILURE;
239 	}
240 
241 	/* Prepare name */
242 	snprintf(devname, sizeof(devname), "dev%u", devnum++);
243 
244 	/* Get thread itself */
245 	if (NULL == (this_device->thread = ddekit_thread_create(funct,
246 						this_device,
247 						(const char *)devname))) {
248 		USB_MSG("Failed to initialize USB device thread");
249 		return EXIT_FAILURE;
250 	}
251 
252 	return EXIT_SUCCESS;
253 }
254 
255 
256 /*===========================================================================*
257  *    hcd_disconnect_device                                                  *
258  *===========================================================================*/
259 void
hcd_disconnect_device(hcd_device_state * this_device)260 hcd_disconnect_device(hcd_device_state * this_device)
261 {
262 	DEBUG_DUMP;
263 
264 	/* TODO: This should disconnect all the children if they exist */
265 
266 	/* Clean configuration tree in case it was acquired */
267 	hcd_tree_cleanup(&(this_device->config_tree));
268 
269 	/* Release allocated resources */
270 	if (NULL != this_device->thread)
271 		ddekit_thread_terminate(this_device->thread);
272 	if (NULL != this_device->lock)
273 		ddekit_sem_deinit(this_device->lock);
274 
275 	/* Release reserved address */
276 	if (HCD_DEFAULT_ADDR != this_device->reserved_address)
277 		hcd_release_addr(this_device->driver,
278 				this_device->reserved_address);
279 
280 	/* Mark as disconnected */
281 	this_device->state = HCD_STATE_DISCONNECTED;
282 }
283 
284 
285 /*===========================================================================*
286  *    hcd_device_wait                                                        *
287  *===========================================================================*/
288 void
hcd_device_wait(hcd_device_state * device,hcd_event event,hcd_reg1 ep)289 hcd_device_wait(hcd_device_state * device, hcd_event event, hcd_reg1 ep)
290 {
291 	DEBUG_DUMP;
292 
293 	USB_DBG("0x%08X wait (0x%02X, 0x%02X)", device, event, ep);
294 
295 	device->wait_event = event;
296 	device->wait_ep = ep;
297 
298 	ddekit_sem_down(device->lock);
299 }
300 
301 
302 /*===========================================================================*
303  *    hcd_device_continue                                                    *
304  *===========================================================================*/
305 void
hcd_device_continue(hcd_device_state * device,hcd_event event,hcd_reg1 ep)306 hcd_device_continue(hcd_device_state * device, hcd_event event, hcd_reg1 ep)
307 {
308 	DEBUG_DUMP;
309 
310 	USB_DBG("0x%08X continue (0x%02X, 0x%02X)", device, event, ep);
311 
312 	USB_ASSERT(device->wait_event == event, "Unexpected event");
313 	USB_ASSERT(device->wait_ep == ep, "Unexpected endpoint");
314 
315 	ddekit_sem_up(device->lock);
316 }
317 
318 
319 /*===========================================================================*
320  *    hcd_new_device                                                         *
321  *===========================================================================*/
322 hcd_device_state *
hcd_new_device(void)323 hcd_new_device(void)
324 {
325 	hcd_device_state * d;
326 
327 	DEBUG_DUMP;
328 
329 	/* One new blank device */
330 	d = calloc(1, sizeof(*d));
331 
332 	USB_ASSERT(NULL != d, "Failed to allocate device");
333 
334 	if (NULL == dev_list) {
335 		dev_list = d;
336 	} else {
337 		d->_next = dev_list;
338 		dev_list = d;
339 	}
340 
341 #ifdef HCD_DUMP_DEVICE_LIST
342 	/* Dump updated state of device list */
343 	hcd_dump_devices();
344 #endif
345 
346 	return d;
347 }
348 
349 
350 /*===========================================================================*
351  *    hcd_delete_device                                                      *
352  *===========================================================================*/
353 void
hcd_delete_device(hcd_device_state * d)354 hcd_delete_device(hcd_device_state * d)
355 {
356 	hcd_device_state * temp;
357 
358 	DEBUG_DUMP;
359 
360 	if (d == dev_list) {
361 		dev_list = dev_list->_next;
362 	} else {
363 		temp = dev_list;
364 
365 		/* Find the device and ... */
366 		while (temp->_next != d) {
367 			USB_ASSERT(NULL != temp->_next,
368 				"Invalid state of device list");
369 			temp = temp->_next;
370 		}
371 
372 		/* ...make device list forget about it */
373 		temp->_next = temp->_next->_next;
374 	}
375 
376 	free(d);
377 
378 #ifdef HCD_DUMP_DEVICE_LIST
379 	/* Dump updated state of device list */
380 	hcd_dump_devices();
381 #endif
382 }
383 
384 
385 /*===========================================================================*
386  *    hcd_dump_devices                                                       *
387  *===========================================================================*/
388 void
hcd_dump_devices(void)389 hcd_dump_devices(void)
390 {
391 	hcd_device_state * temp;
392 
393 	DEBUG_DUMP;
394 
395 	temp = dev_list;
396 
397 	USB_MSG("Allocated devices:");
398 
399 	while (NULL != temp) {
400 		USB_MSG("0x%08X", (int)temp);
401 		temp = temp->_next;
402 	}
403 }
404 
405 
406 /*===========================================================================*
407  *    hcd_check_device                                                       *
408  *===========================================================================*/
409 int
hcd_check_device(hcd_device_state * d)410 hcd_check_device(hcd_device_state * d)
411 {
412 	hcd_device_state * temp;
413 
414 	DEBUG_DUMP;
415 
416 	temp = dev_list;
417 
418 	/* Traverse the list of allocated devices
419 	 * to determine validity of this one */
420 	while (NULL != temp) {
421 		if (temp == d)
422 			return EXIT_SUCCESS; /* Device found within the list */
423 		temp = temp->_next;
424 	}
425 
426 	/* Device was not found, may have been removed earlier */
427 	return EXIT_FAILURE;
428 }
429 
430 
431 /*===========================================================================*
432  *    hcd_buffer_to_tree                                                     *
433  *===========================================================================*/
434 int
hcd_buffer_to_tree(hcd_reg1 * buf,int len,hcd_configuration * c)435 hcd_buffer_to_tree(hcd_reg1 * buf, int len, hcd_configuration * c)
436 {
437 	hcd_interface * i;
438 	hcd_endpoint * e;
439 	hcd_descriptor * desc;
440 	int cfg_num;
441 	int if_num;
442 	int ep_num;
443 
444 	DEBUG_DUMP;
445 
446 	cfg_num = 0;
447 	if_num = 0;
448 	ep_num = 0;
449 
450 	i = NULL;
451 	e = NULL;
452 
453 	/* Cleanup initially to NULL pointers before any allocation */
454 	memset(c, 0, sizeof(*c));
455 
456 	while (len > (int)sizeof(*desc)) {
457 		/* Check descriptor type */
458 		desc = (hcd_descriptor *)buf;
459 
460 		if (0 == desc->bLength) {
461 			USB_MSG("Zero length descriptor");
462 			goto PARSE_ERROR;
463 		}
464 
465 		if (UDESC_CONFIG == desc->bDescriptorType) {
466 			if (EXIT_SUCCESS != hcd_fill_configuration(buf, len,
467 								c, cfg_num++))
468 				goto PARSE_ERROR;
469 
470 			if_num = 0;
471 		}
472 		else if (UDESC_INTERFACE == desc->bDescriptorType) {
473 			if (NULL == c->interface)
474 				goto PARSE_ERROR;
475 
476 			i = &(c->interface[if_num]);
477 
478 			if (EXIT_SUCCESS != hcd_fill_interface(buf, len,
479 								i, if_num++))
480 				goto PARSE_ERROR;
481 
482 			ep_num = 0;
483 		}
484 		else if (UDESC_ENDPOINT == desc->bDescriptorType) {
485 			if (NULL == c->interface)
486 				goto PARSE_ERROR;
487 
488 			if (NULL == i)
489 				goto PARSE_ERROR;
490 
491 			e = &(i->endpoint[ep_num++]);
492 
493 			if (EXIT_SUCCESS != hcd_fill_endpoint(buf, len, e))
494 				goto PARSE_ERROR;
495 		} else
496 			USB_DBG("Unhandled descriptor type 0x%02X",
497 				desc->bDescriptorType);
498 
499 		len -= desc->bLength;
500 		buf += desc->bLength;
501 	}
502 
503 	if (0 != len) {
504 		USB_MSG("After parsing, some descriptor data remains");
505 		goto PARSE_ERROR;
506 	}
507 
508 	return EXIT_SUCCESS;
509 
510 	PARSE_ERROR:
511 	hcd_tree_cleanup(c);
512 	return EXIT_FAILURE;
513 }
514 
515 
516 /*===========================================================================*
517  *    hcd_tree_cleanup                                                       *
518  *===========================================================================*/
519 void
hcd_tree_cleanup(hcd_configuration * c)520 hcd_tree_cleanup(hcd_configuration * c)
521 {
522 	int if_idx;
523 
524 	DEBUG_DUMP;
525 
526 	/* Free if anything was allocated */
527 	if (NULL != c->interface) {
528 
529 		USB_ASSERT(c->num_interfaces > 0, "Interface number error");
530 
531 		for (if_idx = 0; if_idx < c->num_interfaces; if_idx++) {
532 			if (NULL != c->interface[if_idx].endpoint) {
533 				USB_DBG("Freeing ep for interface #%d", if_idx);
534 				free(c->interface[if_idx].endpoint);
535 			}
536 		}
537 
538 		USB_DBG("Freeing interfaces");
539 		free(c->interface);
540 		c->interface = NULL;
541 	}
542 }
543 
544 
545 /*===========================================================================*
546  *    hcd_tree_find_ep                                                       *
547  *===========================================================================*/
548 hcd_endpoint *
hcd_tree_find_ep(hcd_configuration * c,hcd_reg1 ep)549 hcd_tree_find_ep(hcd_configuration * c, hcd_reg1 ep)
550 {
551 	hcd_interface * i;
552 	hcd_endpoint * e;
553 	int if_idx;
554 	int ep_idx;
555 
556 	DEBUG_DUMP;
557 
558 	/* Free if anything was allocated */
559 	USB_ASSERT(NULL != c->interface, "No interfaces available");
560 	USB_ASSERT(c->num_interfaces > 0, "Interface number error");
561 
562 	for (if_idx = 0; if_idx < c->num_interfaces; if_idx++) {
563 		i = &(c->interface[if_idx]);
564 		for (ep_idx = 0; ep_idx < i->num_endpoints; ep_idx++) {
565 			e = &(i->endpoint[ep_idx]);
566 			if (UE_GET_ADDR(e->descriptor.bEndpointAddress) == ep)
567 				return e;
568 		}
569 	}
570 
571 	return NULL;
572 }
573 
574 
575 /*===========================================================================*
576  *    hcd_fill_configuration                                                 *
577  *===========================================================================*/
578 static int
hcd_fill_configuration(hcd_reg1 * buf,int len,hcd_configuration * c,int num)579 hcd_fill_configuration(hcd_reg1 * buf, int len, hcd_configuration * c, int num)
580 {
581 	hcd_config_descriptor * desc;
582 	int interfaces_size;
583 
584 	DEBUG_DUMP;
585 
586 	desc = (hcd_config_descriptor *)buf;
587 
588 	USB_DBG("Configuration #%d", num);
589 
590 	if (num > 0) {
591 		USB_DBG("Only one configuration possible");
592 		return EXIT_SUCCESS;
593 	}
594 
595 	if (UDESC_CONFIG != desc->bDescriptorType)
596 		return EXIT_FAILURE;
597 
598 	if (desc->bLength > len)
599 		return EXIT_FAILURE;
600 
601 	if (sizeof(*desc) != desc->bLength)
602 		return EXIT_FAILURE;
603 
604 	memcpy(&(c->descriptor), buf, sizeof(c->descriptor));
605 
606 	c->num_interfaces = c->descriptor.bNumInterface;
607 
608 	interfaces_size = c->num_interfaces * sizeof(*(c->interface));
609 
610 	USB_DBG("Allocating interfaces, %dB", interfaces_size);
611 	c->interface = malloc(interfaces_size);
612 
613 	memset(c->interface, 0, interfaces_size);
614 
615 	/* Dump configuration in debug mode */
616 	USB_DBG("<<CONFIGURATION>>");
617 	USB_DBG("bLength %02X",			desc->bLength);
618 	USB_DBG("bDescriptorType %02X",		desc->bDescriptorType);
619 	USB_DBG("wTotalLength %04X",		UGETW(desc->wTotalLength));
620 	USB_DBG("bNumInterface %02X",		desc->bNumInterface);
621 	USB_DBG("bConfigurationValue %02X",	desc->bConfigurationValue);
622 	USB_DBG("iConfiguration %02X",		desc->iConfiguration);
623 	USB_DBG("bmAttributes %02X",		desc->bmAttributes);
624 	USB_DBG("bMaxPower %02X",		desc->bMaxPower);
625 
626 	return EXIT_SUCCESS;
627 }
628 
629 
630 /*===========================================================================*
631  *    hcd_fill_interface                                                     *
632  *===========================================================================*/
633 static int
hcd_fill_interface(hcd_reg1 * buf,int len,hcd_interface * i,int num)634 hcd_fill_interface(hcd_reg1 * buf, int len, hcd_interface * i, int num)
635 {
636 	hcd_interface_descriptor * desc;
637 	int endpoints_size;
638 
639 	DEBUG_DUMP;
640 
641 	desc = (hcd_interface_descriptor *)buf;
642 
643 	USB_DBG("Interface #%d", num);
644 
645 	if (UDESC_INTERFACE != desc->bDescriptorType)
646 		return EXIT_FAILURE;
647 
648 	if (desc->bLength > len)
649 		return EXIT_FAILURE;
650 
651 	if (sizeof(*desc) != desc->bLength)
652 		return EXIT_FAILURE;
653 
654 	/* It is mandatory to supply interfaces in correct order */
655 	if (desc->bInterfaceNumber != num)
656 		return EXIT_FAILURE;
657 
658 	memcpy(&(i->descriptor), buf, sizeof(i->descriptor));
659 
660 	i->num_endpoints = i->descriptor.bNumEndpoints;
661 
662 	endpoints_size = i->num_endpoints * sizeof(*(i->endpoint));
663 
664 	USB_DBG("Allocating endpoints, %dB", endpoints_size);
665 	i->endpoint = malloc(endpoints_size);
666 
667 	memset(i->endpoint, 0, endpoints_size);
668 
669 	/* Dump interface in debug mode */
670 	USB_DBG("<<INTERFACE>>");
671 	USB_DBG("bLength %02X",			desc->bLength);
672 	USB_DBG("bDescriptorType %02X",		desc->bDescriptorType);
673 	USB_DBG("bInterfaceNumber %02X",	desc->bInterfaceNumber);
674 	USB_DBG("bAlternateSetting %02X",	desc->bAlternateSetting);
675 	USB_DBG("bNumEndpoints %02X",		desc->bNumEndpoints);
676 	USB_DBG("bInterfaceClass %02X",		desc->bInterfaceClass);
677 	USB_DBG("bInterfaceSubClass %02X",	desc->bInterfaceSubClass);
678 	USB_DBG("bInterfaceProtocol %02X",	desc->bInterfaceProtocol);
679 	USB_DBG("iInterface %02X",		desc->iInterface);
680 
681 	return EXIT_SUCCESS;
682 }
683 
684 
685 /*===========================================================================*
686  *    hcd_fill_endpoint                                                      *
687  *===========================================================================*/
688 static int
hcd_fill_endpoint(hcd_reg1 * buf,int len,hcd_endpoint * e)689 hcd_fill_endpoint(hcd_reg1 * buf, int len, hcd_endpoint * e)
690 {
691 	hcd_endpoint_descriptor * desc;
692 
693 	DEBUG_DUMP;
694 
695 	desc = (hcd_endpoint_descriptor *)buf;
696 
697 	USB_DBG("Endpoint #%d", UE_GET_ADDR(desc->bEndpointAddress));
698 
699 	if (UDESC_ENDPOINT != desc->bDescriptorType)
700 		return EXIT_FAILURE;
701 
702 	if (desc->bLength > len)
703 		return EXIT_FAILURE;
704 
705 	if (sizeof(*desc) != desc->bLength)
706 		return EXIT_FAILURE;
707 
708 	memcpy(&(e->descriptor), buf, sizeof(e->descriptor));
709 
710 	/* Dump endpoint in debug mode */
711 	USB_DBG("<<ENDPOINT>>");
712 	USB_DBG("bLength %02X",			desc->bLength);
713 	USB_DBG("bDescriptorType %02X",		desc->bDescriptorType);
714 	USB_DBG("bEndpointAddress %02X",	desc->bEndpointAddress);
715 	USB_DBG("bmAttributes %02X",		desc->bmAttributes);
716 	USB_DBG("wMaxPacketSize %04X",		UGETW(desc->wMaxPacketSize));
717 	USB_DBG("bInterval %02X",		desc->bInterval);
718 
719 	return EXIT_SUCCESS;
720 }
721 
722 
723 /*===========================================================================*
724  *    hcd_reserve_addr                                                       *
725  *===========================================================================*/
726 static hcd_reg1
hcd_reserve_addr(hcd_driver_state * driver)727 hcd_reserve_addr(hcd_driver_state * driver)
728 {
729 	hcd_reg1 addr;
730 
731 	DEBUG_DUMP;
732 
733 	for (addr = HCD_FIRST_ADDR; addr <= HCD_LAST_ADDR; addr++) {
734 		if (HCD_ADDR_AVAILABLE == driver->dev_addr[addr]) {
735 			USB_DBG("Reserved address: %u", addr);
736 			driver->dev_addr[addr] = HCD_ADDR_USED;
737 			return addr;
738 		}
739 	}
740 
741 	/* This means error */
742 	return HCD_DEFAULT_ADDR;
743 }
744 
745 
746 /*===========================================================================*
747  *    hcd_release_addr                                                       *
748  *===========================================================================*/
749 static void
hcd_release_addr(hcd_driver_state * driver,hcd_reg1 addr)750 hcd_release_addr(hcd_driver_state * driver, hcd_reg1 addr)
751 {
752 	DEBUG_DUMP;
753 
754 	USB_ASSERT((addr > HCD_DEFAULT_ADDR) && (addr <= HCD_LAST_ADDR),
755 		"Invalid device address to be released");
756 	USB_ASSERT(HCD_ADDR_USED == driver->dev_addr[addr],
757 		"Attempted to release unused address");
758 
759 	USB_DBG("Released address: %u", addr);
760 	driver->dev_addr[addr] = HCD_ADDR_AVAILABLE;
761 }
762