xref: /freebsd/sys/dev/usb/template/usb_template.c (revision 7aa383846770374466b1dcb2cefd71bde9acf463)
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 /*
28  * This file contains sub-routines to build up USB descriptors from
29  * USB templates.
30  */
31 
32 #include <sys/stdint.h>
33 #include <sys/stddef.h>
34 #include <sys/param.h>
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/bus.h>
40 #include <sys/linker_set.h>
41 #include <sys/module.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/condvar.h>
45 #include <sys/sysctl.h>
46 #include <sys/sx.h>
47 #include <sys/unistd.h>
48 #include <sys/callout.h>
49 #include <sys/malloc.h>
50 #include <sys/priv.h>
51 
52 #include <dev/usb/usb.h>
53 #include <dev/usb/usbdi.h>
54 #include <dev/usb/usbdi_util.h>
55 #include "usbdevs.h"
56 
57 #include <dev/usb/usb_cdc.h>
58 #include <dev/usb/usb_core.h>
59 #include <dev/usb/usb_dynamic.h>
60 #include <dev/usb/usb_busdma.h>
61 #include <dev/usb/usb_process.h>
62 #include <dev/usb/usb_device.h>
63 
64 #define	USB_DEBUG_VAR usb_debug
65 #include <dev/usb/usb_debug.h>
66 
67 #include <dev/usb/usb_controller.h>
68 #include <dev/usb/usb_bus.h>
69 #include <dev/usb/template/usb_template.h>
70 
71 MODULE_DEPEND(usb_template, usb, 1, 1, 1);
72 MODULE_VERSION(usb_template, 1);
73 
74 /* function prototypes */
75 
76 static void	usb_make_raw_desc(struct usb_temp_setup *, const uint8_t *);
77 static void	usb_make_endpoint_desc(struct usb_temp_setup *,
78 		    const struct usb_temp_endpoint_desc *);
79 static void	usb_make_interface_desc(struct usb_temp_setup *,
80 		    const struct usb_temp_interface_desc *);
81 static void	usb_make_config_desc(struct usb_temp_setup *,
82 		    const struct usb_temp_config_desc *);
83 static void	usb_make_device_desc(struct usb_temp_setup *,
84 		    const struct usb_temp_device_desc *);
85 static uint8_t	usb_hw_ep_match(const struct usb_hw_ep_profile *, uint8_t,
86 		    uint8_t);
87 static uint8_t	usb_hw_ep_find_match(struct usb_hw_ep_scratch *,
88 		    struct usb_hw_ep_scratch_sub *, uint8_t);
89 static uint8_t	usb_hw_ep_get_needs(struct usb_hw_ep_scratch *, uint8_t,
90 		    uint8_t);
91 static usb_error_t usb_hw_ep_resolve(struct usb_device *,
92 		    struct usb_descriptor *);
93 static const struct usb_temp_device_desc *usb_temp_get_tdd(struct usb_device *);
94 static void	*usb_temp_get_device_desc(struct usb_device *);
95 static void	*usb_temp_get_qualifier_desc(struct usb_device *);
96 static void	*usb_temp_get_config_desc(struct usb_device *, uint16_t *,
97 		    uint8_t);
98 static const void *usb_temp_get_string_desc(struct usb_device *, uint16_t,
99 		    uint8_t);
100 static const void *usb_temp_get_vendor_desc(struct usb_device *,
101 		    const struct usb_device_request *, uint16_t *plen);
102 static const void *usb_temp_get_hub_desc(struct usb_device *);
103 static usb_error_t usb_temp_get_desc(struct usb_device *,
104 		    struct usb_device_request *, const void **, uint16_t *);
105 static usb_error_t usb_temp_setup_by_index(struct usb_device *,
106 		    uint16_t index);
107 static void	usb_temp_init(void *);
108 
109 /*------------------------------------------------------------------------*
110  *	usb_make_raw_desc
111  *
112  * This function will insert a raw USB descriptor into the generated
113  * USB configuration.
114  *------------------------------------------------------------------------*/
115 static void
116 usb_make_raw_desc(struct usb_temp_setup *temp,
117     const uint8_t *raw)
118 {
119 	void *dst;
120 	uint8_t len;
121 
122 	/*
123          * The first byte of any USB descriptor gives the length.
124          */
125 	if (raw) {
126 		len = raw[0];
127 		if (temp->buf) {
128 			dst = USB_ADD_BYTES(temp->buf, temp->size);
129 			bcopy(raw, dst, len);
130 
131 			/* check if we have got a CDC union descriptor */
132 
133 			if ((raw[0] >= sizeof(struct usb_cdc_union_descriptor)) &&
134 			    (raw[1] == UDESC_CS_INTERFACE) &&
135 			    (raw[2] == UDESCSUB_CDC_UNION)) {
136 				struct usb_cdc_union_descriptor *ud = (void *)dst;
137 
138 				/* update the interface numbers */
139 
140 				ud->bMasterInterface +=
141 				    temp->bInterfaceNumber;
142 				ud->bSlaveInterface[0] +=
143 				    temp->bInterfaceNumber;
144 			}
145 		}
146 		temp->size += len;
147 	}
148 }
149 
150 /*------------------------------------------------------------------------*
151  *	usb_make_endpoint_desc
152  *
153  * This function will generate an USB endpoint descriptor from the
154  * given USB template endpoint descriptor, which will be inserted into
155  * the USB configuration.
156  *------------------------------------------------------------------------*/
157 static void
158 usb_make_endpoint_desc(struct usb_temp_setup *temp,
159     const struct usb_temp_endpoint_desc *ted)
160 {
161 	struct usb_endpoint_descriptor *ed;
162 	const void **rd;
163 	uint16_t old_size;
164 	uint16_t mps;
165 	uint8_t ea;			/* Endpoint Address */
166 	uint8_t et;			/* Endpiont Type */
167 
168 	/* Reserve memory */
169 	old_size = temp->size;
170 
171 	ea = (ted->bEndpointAddress & (UE_ADDR | UE_DIR_IN | UE_DIR_OUT));
172 	et = (ted->bmAttributes & UE_XFERTYPE);
173 
174 	if (et == UE_ISOCHRONOUS) {
175 		/* account for extra byte fields */
176 		temp->size += sizeof(*ed) + 2;
177 	} else {
178 		temp->size += sizeof(*ed);
179 	}
180 
181 	/* Scan all Raw Descriptors first */
182 	rd = ted->ppRawDesc;
183 	if (rd) {
184 		while (*rd) {
185 			usb_make_raw_desc(temp, *rd);
186 			rd++;
187 		}
188 	}
189 	if (ted->pPacketSize == NULL) {
190 		/* not initialized */
191 		temp->err = USB_ERR_INVAL;
192 		return;
193 	}
194 	mps = ted->pPacketSize->mps[temp->usb_speed];
195 	if (mps == 0) {
196 		/* not initialized */
197 		temp->err = USB_ERR_INVAL;
198 		return;
199 	} else if (mps == UE_ZERO_MPS) {
200 		/* escape for Zero Max Packet Size */
201 		mps = 0;
202 	}
203 
204 	/*
205 	 * Fill out the real USB endpoint descriptor
206 	 * in case there is a buffer present:
207 	 */
208 	if (temp->buf) {
209 		ed = USB_ADD_BYTES(temp->buf, old_size);
210 		if (et == UE_ISOCHRONOUS)
211 			ed->bLength = sizeof(*ed) + 2;
212 		else
213 			ed->bLength = sizeof(*ed);
214 		ed->bDescriptorType = UDESC_ENDPOINT;
215 		ed->bEndpointAddress = ea;
216 		ed->bmAttributes = ted->bmAttributes;
217 		USETW(ed->wMaxPacketSize, mps);
218 
219 		/* setup bInterval parameter */
220 
221 		if (ted->pIntervals &&
222 		    ted->pIntervals->bInterval[temp->usb_speed]) {
223 			ed->bInterval =
224 			    ted->pIntervals->bInterval[temp->usb_speed];
225 		} else {
226 			switch (et) {
227 			case UE_BULK:
228 			case UE_CONTROL:
229 				ed->bInterval = 0;	/* not used */
230 				break;
231 			case UE_INTERRUPT:
232 				switch (temp->usb_speed) {
233 				case USB_SPEED_LOW:
234 				case USB_SPEED_FULL:
235 					ed->bInterval = 1;	/* 1 ms */
236 					break;
237 				default:
238 					ed->bInterval = 8;	/* 8*125 us */
239 					break;
240 				}
241 				break;
242 			default:	/* UE_ISOCHRONOUS */
243 				switch (temp->usb_speed) {
244 				case USB_SPEED_LOW:
245 				case USB_SPEED_FULL:
246 					ed->bInterval = 1;	/* 1 ms */
247 					break;
248 				default:
249 					ed->bInterval = 1;	/* 125 us */
250 					break;
251 				}
252 				break;
253 			}
254 		}
255 	}
256 	temp->bNumEndpoints++;
257 }
258 
259 /*------------------------------------------------------------------------*
260  *	usb_make_interface_desc
261  *
262  * This function will generate an USB interface descriptor from the
263  * given USB template interface descriptor, which will be inserted
264  * into the USB configuration.
265  *------------------------------------------------------------------------*/
266 static void
267 usb_make_interface_desc(struct usb_temp_setup *temp,
268     const struct usb_temp_interface_desc *tid)
269 {
270 	struct usb_interface_descriptor *id;
271 	const struct usb_temp_endpoint_desc **ted;
272 	const void **rd;
273 	uint16_t old_size;
274 
275 	/* Reserve memory */
276 
277 	old_size = temp->size;
278 	temp->size += sizeof(*id);
279 
280 	/* Update interface and alternate interface numbers */
281 
282 	if (tid->isAltInterface == 0) {
283 		temp->bAlternateSetting = 0;
284 		temp->bInterfaceNumber++;
285 	} else {
286 		temp->bAlternateSetting++;
287 	}
288 
289 	/* Scan all Raw Descriptors first */
290 
291 	rd = tid->ppRawDesc;
292 
293 	if (rd) {
294 		while (*rd) {
295 			usb_make_raw_desc(temp, *rd);
296 			rd++;
297 		}
298 	}
299 	/* Reset some counters */
300 
301 	temp->bNumEndpoints = 0;
302 
303 	/* Scan all Endpoint Descriptors second */
304 
305 	ted = tid->ppEndpoints;
306 	if (ted) {
307 		while (*ted) {
308 			usb_make_endpoint_desc(temp, *ted);
309 			ted++;
310 		}
311 	}
312 	/*
313 	 * Fill out the real USB interface descriptor
314 	 * in case there is a buffer present:
315 	 */
316 	if (temp->buf) {
317 		id = USB_ADD_BYTES(temp->buf, old_size);
318 		id->bLength = sizeof(*id);
319 		id->bDescriptorType = UDESC_INTERFACE;
320 		id->bInterfaceNumber = temp->bInterfaceNumber;
321 		id->bAlternateSetting = temp->bAlternateSetting;
322 		id->bNumEndpoints = temp->bNumEndpoints;
323 		id->bInterfaceClass = tid->bInterfaceClass;
324 		id->bInterfaceSubClass = tid->bInterfaceSubClass;
325 		id->bInterfaceProtocol = tid->bInterfaceProtocol;
326 		id->iInterface = tid->iInterface;
327 	}
328 }
329 
330 /*------------------------------------------------------------------------*
331  *	usb_make_config_desc
332  *
333  * This function will generate an USB config descriptor from the given
334  * USB template config descriptor, which will be inserted into the USB
335  * configuration.
336  *------------------------------------------------------------------------*/
337 static void
338 usb_make_config_desc(struct usb_temp_setup *temp,
339     const struct usb_temp_config_desc *tcd)
340 {
341 	struct usb_config_descriptor *cd;
342 	const struct usb_temp_interface_desc **tid;
343 	uint16_t old_size;
344 
345 	/* Reserve memory */
346 
347 	old_size = temp->size;
348 	temp->size += sizeof(*cd);
349 
350 	/* Reset some counters */
351 
352 	temp->bInterfaceNumber = 0 - 1;
353 	temp->bAlternateSetting = 0;
354 
355 	/* Scan all the USB interfaces */
356 
357 	tid = tcd->ppIfaceDesc;
358 	if (tid) {
359 		while (*tid) {
360 			usb_make_interface_desc(temp, *tid);
361 			tid++;
362 		}
363 	}
364 	/*
365 	 * Fill out the real USB config descriptor
366 	 * in case there is a buffer present:
367 	 */
368 	if (temp->buf) {
369 		cd = USB_ADD_BYTES(temp->buf, old_size);
370 
371 		/* compute total size */
372 		old_size = temp->size - old_size;
373 
374 		cd->bLength = sizeof(*cd);
375 		cd->bDescriptorType = UDESC_CONFIG;
376 		USETW(cd->wTotalLength, old_size);
377 		cd->bNumInterface = temp->bInterfaceNumber + 1;
378 		cd->bConfigurationValue = temp->bConfigurationValue;
379 		cd->iConfiguration = tcd->iConfiguration;
380 		cd->bmAttributes = tcd->bmAttributes;
381 		cd->bMaxPower = tcd->bMaxPower;
382 		cd->bmAttributes |= (UC_REMOTE_WAKEUP | UC_BUS_POWERED);
383 
384 		if (temp->self_powered) {
385 			cd->bmAttributes |= UC_SELF_POWERED;
386 		} else {
387 			cd->bmAttributes &= ~UC_SELF_POWERED;
388 		}
389 	}
390 }
391 
392 /*------------------------------------------------------------------------*
393  *	usb_make_device_desc
394  *
395  * This function will generate an USB device descriptor from the
396  * given USB template device descriptor.
397  *------------------------------------------------------------------------*/
398 static void
399 usb_make_device_desc(struct usb_temp_setup *temp,
400     const struct usb_temp_device_desc *tdd)
401 {
402 	struct usb_temp_data *utd;
403 	const struct usb_temp_config_desc **tcd;
404 	uint16_t old_size;
405 
406 	/* Reserve memory */
407 
408 	old_size = temp->size;
409 	temp->size += sizeof(*utd);
410 
411 	/* Scan all the USB configs */
412 
413 	temp->bConfigurationValue = 1;
414 	tcd = tdd->ppConfigDesc;
415 	if (tcd) {
416 		while (*tcd) {
417 			usb_make_config_desc(temp, *tcd);
418 			temp->bConfigurationValue++;
419 			tcd++;
420 		}
421 	}
422 	/*
423 	 * Fill out the real USB device descriptor
424 	 * in case there is a buffer present:
425 	 */
426 
427 	if (temp->buf) {
428 		utd = USB_ADD_BYTES(temp->buf, old_size);
429 
430 		/* Store a pointer to our template device descriptor */
431 		utd->tdd = tdd;
432 
433 		/* Fill out USB device descriptor */
434 		utd->udd.bLength = sizeof(utd->udd);
435 		utd->udd.bDescriptorType = UDESC_DEVICE;
436 		utd->udd.bDeviceClass = tdd->bDeviceClass;
437 		utd->udd.bDeviceSubClass = tdd->bDeviceSubClass;
438 		utd->udd.bDeviceProtocol = tdd->bDeviceProtocol;
439 		USETW(utd->udd.idVendor, tdd->idVendor);
440 		USETW(utd->udd.idProduct, tdd->idProduct);
441 		USETW(utd->udd.bcdDevice, tdd->bcdDevice);
442 		utd->udd.iManufacturer = tdd->iManufacturer;
443 		utd->udd.iProduct = tdd->iProduct;
444 		utd->udd.iSerialNumber = tdd->iSerialNumber;
445 		utd->udd.bNumConfigurations = temp->bConfigurationValue - 1;
446 
447 		/*
448 		 * Fill out the USB device qualifier. Pretend that we
449 		 * don't support any other speeds by setting
450 		 * "bNumConfigurations" equal to zero. That saves us
451 		 * generating an extra set of configuration
452 		 * descriptors.
453 		 */
454 		utd->udq.bLength = sizeof(utd->udq);
455 		utd->udq.bDescriptorType = UDESC_DEVICE_QUALIFIER;
456 		utd->udq.bDeviceClass = tdd->bDeviceClass;
457 		utd->udq.bDeviceSubClass = tdd->bDeviceSubClass;
458 		utd->udq.bDeviceProtocol = tdd->bDeviceProtocol;
459 		utd->udq.bNumConfigurations = 0;
460 		USETW(utd->udq.bcdUSB, 0x0200);
461 		utd->udq.bMaxPacketSize0 = 0;
462 
463 		switch (temp->usb_speed) {
464 		case USB_SPEED_LOW:
465 			USETW(utd->udd.bcdUSB, 0x0110);
466 			utd->udd.bMaxPacketSize = 8;
467 			break;
468 		case USB_SPEED_FULL:
469 			USETW(utd->udd.bcdUSB, 0x0110);
470 			utd->udd.bMaxPacketSize = 32;
471 			break;
472 		case USB_SPEED_HIGH:
473 			USETW(utd->udd.bcdUSB, 0x0200);
474 			utd->udd.bMaxPacketSize = 64;
475 			break;
476 		case USB_SPEED_VARIABLE:
477 			USETW(utd->udd.bcdUSB, 0x0250);
478 			utd->udd.bMaxPacketSize = 255;	/* 512 bytes */
479 			break;
480 		default:
481 			temp->err = USB_ERR_INVAL;
482 			break;
483 		}
484 	}
485 }
486 
487 /*------------------------------------------------------------------------*
488  *	usb_hw_ep_match
489  *
490  * Return values:
491  *    0: The endpoint profile does not match the criterias
492  * Else: The endpoint profile matches the criterias
493  *------------------------------------------------------------------------*/
494 static uint8_t
495 usb_hw_ep_match(const struct usb_hw_ep_profile *pf,
496     uint8_t ep_type, uint8_t ep_dir_in)
497 {
498 	if (ep_type == UE_CONTROL) {
499 		/* special */
500 		return (pf->support_control);
501 	}
502 	if ((pf->support_in && ep_dir_in) ||
503 	    (pf->support_out && !ep_dir_in)) {
504 		if ((pf->support_interrupt && (ep_type == UE_INTERRUPT)) ||
505 		    (pf->support_isochronous && (ep_type == UE_ISOCHRONOUS)) ||
506 		    (pf->support_bulk && (ep_type == UE_BULK))) {
507 			return (1);
508 		}
509 	}
510 	return (0);
511 }
512 
513 /*------------------------------------------------------------------------*
514  *	usb_hw_ep_find_match
515  *
516  * This function is used to find the best matching endpoint profile
517  * for and endpoint belonging to an USB descriptor.
518  *
519  * Return values:
520  *    0: Success. Got a match.
521  * Else: Failure. No match.
522  *------------------------------------------------------------------------*/
523 static uint8_t
524 usb_hw_ep_find_match(struct usb_hw_ep_scratch *ues,
525     struct usb_hw_ep_scratch_sub *ep, uint8_t is_simplex)
526 {
527 	const struct usb_hw_ep_profile *pf;
528 	uint16_t distance;
529 	uint16_t temp;
530 	uint16_t max_frame_size;
531 	uint8_t n;
532 	uint8_t best_n;
533 	uint8_t dir_in;
534 	uint8_t dir_out;
535 
536 	distance = 0xFFFF;
537 	best_n = 0;
538 
539 	if ((!ep->needs_in) && (!ep->needs_out)) {
540 		return (0);		/* we are done */
541 	}
542 	if (ep->needs_ep_type == UE_CONTROL) {
543 		dir_in = 1;
544 		dir_out = 1;
545 	} else {
546 		if (ep->needs_in) {
547 			dir_in = 1;
548 			dir_out = 0;
549 		} else {
550 			dir_in = 0;
551 			dir_out = 1;
552 		}
553 	}
554 
555 	for (n = 1; n != (USB_EP_MAX / 2); n++) {
556 
557 		/* get HW endpoint profile */
558 		(ues->methods->get_hw_ep_profile) (ues->udev, &pf, n);
559 		if (pf == NULL) {
560 			/* end of profiles */
561 			break;
562 		}
563 		/* check if IN-endpoint is reserved */
564 		if (dir_in || pf->is_simplex) {
565 			if (ues->bmInAlloc[n / 8] & (1 << (n % 8))) {
566 				/* mismatch */
567 				continue;
568 			}
569 		}
570 		/* check if OUT-endpoint is reserved */
571 		if (dir_out || pf->is_simplex) {
572 			if (ues->bmOutAlloc[n / 8] & (1 << (n % 8))) {
573 				/* mismatch */
574 				continue;
575 			}
576 		}
577 		/* check simplex */
578 		if (pf->is_simplex == is_simplex) {
579 			/* mismatch */
580 			continue;
581 		}
582 		/* check if HW endpoint matches */
583 		if (!usb_hw_ep_match(pf, ep->needs_ep_type, dir_in)) {
584 			/* mismatch */
585 			continue;
586 		}
587 		/* get maximum frame size */
588 		if (dir_in)
589 			max_frame_size = pf->max_in_frame_size;
590 		else
591 			max_frame_size = pf->max_out_frame_size;
592 
593 		/* check if we have a matching profile */
594 		if (max_frame_size >= ep->max_frame_size) {
595 			temp = (max_frame_size - ep->max_frame_size);
596 			if (distance > temp) {
597 				distance = temp;
598 				best_n = n;
599 				ep->pf = pf;
600 			}
601 		}
602 	}
603 
604 	/* see if we got a match */
605 	if (best_n != 0) {
606 		/* get the correct profile */
607 		pf = ep->pf;
608 
609 		/* reserve IN-endpoint */
610 		if (dir_in) {
611 			ues->bmInAlloc[best_n / 8] |=
612 			    (1 << (best_n % 8));
613 			ep->hw_endpoint_in = best_n | UE_DIR_IN;
614 			ep->needs_in = 0;
615 		}
616 		/* reserve OUT-endpoint */
617 		if (dir_out) {
618 			ues->bmOutAlloc[best_n / 8] |=
619 			    (1 << (best_n % 8));
620 			ep->hw_endpoint_out = best_n | UE_DIR_OUT;
621 			ep->needs_out = 0;
622 		}
623 		return (0);		/* got a match */
624 	}
625 	return (1);			/* failure */
626 }
627 
628 /*------------------------------------------------------------------------*
629  *	usb_hw_ep_get_needs
630  *
631  * This function will figure out the type and number of endpoints
632  * which are needed for an USB configuration.
633  *
634  * Return values:
635  *    0: Success.
636  * Else: Failure.
637  *------------------------------------------------------------------------*/
638 static uint8_t
639 usb_hw_ep_get_needs(struct usb_hw_ep_scratch *ues,
640     uint8_t ep_type, uint8_t is_complete)
641 {
642 	const struct usb_hw_ep_profile *pf;
643 	struct usb_hw_ep_scratch_sub *ep_iface;
644 	struct usb_hw_ep_scratch_sub *ep_curr;
645 	struct usb_hw_ep_scratch_sub *ep_max;
646 	struct usb_hw_ep_scratch_sub *ep_end;
647 	struct usb_descriptor *desc;
648 	struct usb_interface_descriptor *id;
649 	struct usb_endpoint_descriptor *ed;
650 	enum usb_dev_speed speed;
651 	uint16_t wMaxPacketSize;
652 	uint16_t temp;
653 	uint8_t ep_no;
654 
655 	ep_iface = ues->ep_max;
656 	ep_curr = ues->ep_max;
657 	ep_end = ues->ep + USB_EP_MAX;
658 	ep_max = ues->ep_max;
659 	desc = NULL;
660 	speed = usbd_get_speed(ues->udev);
661 
662 repeat:
663 
664 	while ((desc = usb_desc_foreach(ues->cd, desc))) {
665 
666 		if ((desc->bDescriptorType == UDESC_INTERFACE) &&
667 		    (desc->bLength >= sizeof(*id))) {
668 
669 			id = (void *)desc;
670 
671 			if (id->bAlternateSetting == 0) {
672 				/* going forward */
673 				ep_iface = ep_max;
674 			} else {
675 				/* reset */
676 				ep_curr = ep_iface;
677 			}
678 		}
679 		if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
680 		    (desc->bLength >= sizeof(*ed))) {
681 
682 			ed = (void *)desc;
683 
684 			goto handle_endpoint_desc;
685 		}
686 	}
687 	ues->ep_max = ep_max;
688 	return (0);
689 
690 handle_endpoint_desc:
691 	temp = (ed->bmAttributes & UE_XFERTYPE);
692 
693 	if (temp == ep_type) {
694 
695 		if (ep_curr == ep_end) {
696 			/* too many endpoints */
697 			return (1);	/* failure */
698 		}
699 		wMaxPacketSize = UGETW(ed->wMaxPacketSize);
700 		if ((wMaxPacketSize & 0xF800) &&
701 		    (speed == USB_SPEED_HIGH)) {
702 			/* handle packet multiplier */
703 			temp = (wMaxPacketSize >> 11) & 3;
704 			wMaxPacketSize &= 0x7FF;
705 			if (temp == 1) {
706 				wMaxPacketSize *= 2;
707 			} else {
708 				wMaxPacketSize *= 3;
709 			}
710 		}
711 		/*
712 		 * Check if we have a fixed endpoint number, else the
713 		 * endpoint number is allocated dynamically:
714 		 */
715 		ep_no = (ed->bEndpointAddress & UE_ADDR);
716 		if (ep_no != 0) {
717 
718 			/* get HW endpoint profile */
719 			(ues->methods->get_hw_ep_profile)
720 			    (ues->udev, &pf, ep_no);
721 			if (pf == NULL) {
722 				/* HW profile does not exist - failure */
723 				DPRINTFN(0, "Endpoint profile %u "
724 				    "does not exist\n", ep_no);
725 				return (1);
726 			}
727 			/* reserve fixed endpoint number */
728 			if (ep_type == UE_CONTROL) {
729 				ues->bmInAlloc[ep_no / 8] |=
730 				    (1 << (ep_no % 8));
731 				ues->bmOutAlloc[ep_no / 8] |=
732 				    (1 << (ep_no % 8));
733 				if ((pf->max_in_frame_size < wMaxPacketSize) ||
734 				    (pf->max_out_frame_size < wMaxPacketSize)) {
735 					DPRINTFN(0, "Endpoint profile %u "
736 					    "has too small buffer\n", ep_no);
737 					return (1);
738 				}
739 			} else if (ed->bEndpointAddress & UE_DIR_IN) {
740 				ues->bmInAlloc[ep_no / 8] |=
741 				    (1 << (ep_no % 8));
742 				if (pf->max_in_frame_size < wMaxPacketSize) {
743 					DPRINTFN(0, "Endpoint profile %u "
744 					    "has too small buffer\n", ep_no);
745 					return (1);
746 				}
747 			} else {
748 				ues->bmOutAlloc[ep_no / 8] |=
749 				    (1 << (ep_no % 8));
750 				if (pf->max_out_frame_size < wMaxPacketSize) {
751 					DPRINTFN(0, "Endpoint profile %u "
752 					    "has too small buffer\n", ep_no);
753 					return (1);
754 				}
755 			}
756 		} else if (is_complete) {
757 
758 			/* check if we have enough buffer space */
759 			if (wMaxPacketSize >
760 			    ep_curr->max_frame_size) {
761 				return (1);	/* failure */
762 			}
763 			if (ed->bEndpointAddress & UE_DIR_IN) {
764 				ed->bEndpointAddress =
765 				    ep_curr->hw_endpoint_in;
766 			} else {
767 				ed->bEndpointAddress =
768 				    ep_curr->hw_endpoint_out;
769 			}
770 
771 		} else {
772 
773 			/* compute the maximum frame size */
774 			if (ep_curr->max_frame_size < wMaxPacketSize) {
775 				ep_curr->max_frame_size = wMaxPacketSize;
776 			}
777 			if (temp == UE_CONTROL) {
778 				ep_curr->needs_in = 1;
779 				ep_curr->needs_out = 1;
780 			} else {
781 				if (ed->bEndpointAddress & UE_DIR_IN) {
782 					ep_curr->needs_in = 1;
783 				} else {
784 					ep_curr->needs_out = 1;
785 				}
786 			}
787 			ep_curr->needs_ep_type = ep_type;
788 		}
789 
790 		ep_curr++;
791 		if (ep_max < ep_curr) {
792 			ep_max = ep_curr;
793 		}
794 	}
795 	goto repeat;
796 }
797 
798 /*------------------------------------------------------------------------*
799  *	usb_hw_ep_resolve
800  *
801  * This function will try to resolve endpoint requirements by the
802  * given endpoint profiles that the USB hardware reports.
803  *
804  * Return values:
805  *    0: Success
806  * Else: Failure
807  *------------------------------------------------------------------------*/
808 static usb_error_t
809 usb_hw_ep_resolve(struct usb_device *udev,
810     struct usb_descriptor *desc)
811 {
812 	struct usb_hw_ep_scratch *ues;
813 	struct usb_hw_ep_scratch_sub *ep;
814 	const struct usb_hw_ep_profile *pf;
815 	struct usb_bus_methods *methods;
816 	struct usb_device_descriptor *dd;
817 	uint16_t mps;
818 
819 	if (desc == NULL) {
820 		return (USB_ERR_INVAL);
821 	}
822 	/* get bus methods */
823 	methods = udev->bus->methods;
824 
825 	if (methods->get_hw_ep_profile == NULL) {
826 		return (USB_ERR_INVAL);
827 	}
828 	if (desc->bDescriptorType == UDESC_DEVICE) {
829 
830 		if (desc->bLength < sizeof(*dd)) {
831 			return (USB_ERR_INVAL);
832 		}
833 		dd = (void *)desc;
834 
835 		/* get HW control endpoint 0 profile */
836 		(methods->get_hw_ep_profile) (udev, &pf, 0);
837 		if (pf == NULL) {
838 			return (USB_ERR_INVAL);
839 		}
840 		if (!usb_hw_ep_match(pf, UE_CONTROL, 0)) {
841 			DPRINTFN(0, "Endpoint 0 does not "
842 			    "support control\n");
843 			return (USB_ERR_INVAL);
844 		}
845 		mps = dd->bMaxPacketSize;
846 
847 		if (udev->speed == USB_SPEED_FULL) {
848 			/*
849 			 * We can optionally choose another packet size !
850 			 */
851 			while (1) {
852 				/* check if "mps" is ok */
853 				if (pf->max_in_frame_size >= mps) {
854 					break;
855 				}
856 				/* reduce maximum packet size */
857 				mps /= 2;
858 
859 				/* check if "mps" is too small */
860 				if (mps < 8) {
861 					return (USB_ERR_INVAL);
862 				}
863 			}
864 
865 			dd->bMaxPacketSize = mps;
866 
867 		} else {
868 			/* We only have one choice */
869 			if (mps == 255) {
870 				mps = 512;
871 			}
872 			/* Check if we support the specified wMaxPacketSize */
873 			if (pf->max_in_frame_size < mps) {
874 				return (USB_ERR_INVAL);
875 			}
876 		}
877 		return (0);		/* success */
878 	}
879 	if (desc->bDescriptorType != UDESC_CONFIG) {
880 		return (USB_ERR_INVAL);
881 	}
882 	if (desc->bLength < sizeof(*(ues->cd))) {
883 		return (USB_ERR_INVAL);
884 	}
885 	ues = udev->bus->scratch[0].hw_ep_scratch;
886 
887 	bzero(ues, sizeof(*ues));
888 
889 	ues->ep_max = ues->ep;
890 	ues->cd = (void *)desc;
891 	ues->methods = methods;
892 	ues->udev = udev;
893 
894 	/* Get all the endpoints we need */
895 
896 	if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 0) ||
897 	    usb_hw_ep_get_needs(ues, UE_INTERRUPT, 0) ||
898 	    usb_hw_ep_get_needs(ues, UE_CONTROL, 0) ||
899 	    usb_hw_ep_get_needs(ues, UE_BULK, 0)) {
900 		DPRINTFN(0, "Could not get needs\n");
901 		return (USB_ERR_INVAL);
902 	}
903 	for (ep = ues->ep; ep != ues->ep_max; ep++) {
904 
905 		while (ep->needs_in || ep->needs_out) {
906 
907 			/*
908 		         * First try to use a simplex endpoint.
909 		         * Then try to use a duplex endpoint.
910 		         */
911 			if (usb_hw_ep_find_match(ues, ep, 1) &&
912 			    usb_hw_ep_find_match(ues, ep, 0)) {
913 				DPRINTFN(0, "Could not find match\n");
914 				return (USB_ERR_INVAL);
915 			}
916 		}
917 	}
918 
919 	ues->ep_max = ues->ep;
920 
921 	/* Update all endpoint addresses */
922 
923 	if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 1) ||
924 	    usb_hw_ep_get_needs(ues, UE_INTERRUPT, 1) ||
925 	    usb_hw_ep_get_needs(ues, UE_CONTROL, 1) ||
926 	    usb_hw_ep_get_needs(ues, UE_BULK, 1)) {
927 		DPRINTFN(0, "Could not update endpoint address\n");
928 		return (USB_ERR_INVAL);
929 	}
930 	return (0);			/* success */
931 }
932 
933 /*------------------------------------------------------------------------*
934  *	usb_temp_get_tdd
935  *
936  * Returns:
937  *  NULL: No USB template device descriptor found.
938  *  Else: Pointer to the USB template device descriptor.
939  *------------------------------------------------------------------------*/
940 static const struct usb_temp_device_desc *
941 usb_temp_get_tdd(struct usb_device *udev)
942 {
943 	if (udev->usb_template_ptr == NULL) {
944 		return (NULL);
945 	}
946 	return (udev->usb_template_ptr->tdd);
947 }
948 
949 /*------------------------------------------------------------------------*
950  *	usb_temp_get_device_desc
951  *
952  * Returns:
953  *  NULL: No USB device descriptor found.
954  *  Else: Pointer to USB device descriptor.
955  *------------------------------------------------------------------------*/
956 static void *
957 usb_temp_get_device_desc(struct usb_device *udev)
958 {
959 	struct usb_device_descriptor *dd;
960 
961 	if (udev->usb_template_ptr == NULL) {
962 		return (NULL);
963 	}
964 	dd = &udev->usb_template_ptr->udd;
965 	if (dd->bDescriptorType != UDESC_DEVICE) {
966 		/* sanity check failed */
967 		return (NULL);
968 	}
969 	return (dd);
970 }
971 
972 /*------------------------------------------------------------------------*
973  *	usb_temp_get_qualifier_desc
974  *
975  * Returns:
976  *  NULL: No USB device_qualifier descriptor found.
977  *  Else: Pointer to USB device_qualifier descriptor.
978  *------------------------------------------------------------------------*/
979 static void *
980 usb_temp_get_qualifier_desc(struct usb_device *udev)
981 {
982 	struct usb_device_qualifier *dq;
983 
984 	if (udev->usb_template_ptr == NULL) {
985 		return (NULL);
986 	}
987 	dq = &udev->usb_template_ptr->udq;
988 	if (dq->bDescriptorType != UDESC_DEVICE_QUALIFIER) {
989 		/* sanity check failed */
990 		return (NULL);
991 	}
992 	return (dq);
993 }
994 
995 /*------------------------------------------------------------------------*
996  *	usb_temp_get_config_desc
997  *
998  * Returns:
999  *  NULL: No USB config descriptor found.
1000  *  Else: Pointer to USB config descriptor having index "index".
1001  *------------------------------------------------------------------------*/
1002 static void *
1003 usb_temp_get_config_desc(struct usb_device *udev,
1004     uint16_t *pLength, uint8_t index)
1005 {
1006 	struct usb_device_descriptor *dd;
1007 	struct usb_config_descriptor *cd;
1008 	uint16_t temp;
1009 
1010 	if (udev->usb_template_ptr == NULL) {
1011 		return (NULL);
1012 	}
1013 	dd = &udev->usb_template_ptr->udd;
1014 	cd = (void *)(udev->usb_template_ptr + 1);
1015 
1016 	if (index >= dd->bNumConfigurations) {
1017 		/* out of range */
1018 		return (NULL);
1019 	}
1020 	while (index--) {
1021 		if (cd->bDescriptorType != UDESC_CONFIG) {
1022 			/* sanity check failed */
1023 			return (NULL);
1024 		}
1025 		temp = UGETW(cd->wTotalLength);
1026 		cd = USB_ADD_BYTES(cd, temp);
1027 	}
1028 
1029 	if (pLength) {
1030 		*pLength = UGETW(cd->wTotalLength);
1031 	}
1032 	return (cd);
1033 }
1034 
1035 /*------------------------------------------------------------------------*
1036  *	usb_temp_get_vendor_desc
1037  *
1038  * Returns:
1039  *  NULL: No vendor descriptor found.
1040  *  Else: Pointer to a vendor descriptor.
1041  *------------------------------------------------------------------------*/
1042 static const void *
1043 usb_temp_get_vendor_desc(struct usb_device *udev,
1044     const struct usb_device_request *req, uint16_t *plen)
1045 {
1046 	const struct usb_temp_device_desc *tdd;
1047 
1048 	tdd = usb_temp_get_tdd(udev);
1049 	if (tdd == NULL) {
1050 		return (NULL);
1051 	}
1052 	if (tdd->getVendorDesc == NULL) {
1053 		return (NULL);
1054 	}
1055 	return ((tdd->getVendorDesc) (req, plen));
1056 }
1057 
1058 /*------------------------------------------------------------------------*
1059  *	usb_temp_get_string_desc
1060  *
1061  * Returns:
1062  *  NULL: No string descriptor found.
1063  *  Else: Pointer to a string descriptor.
1064  *------------------------------------------------------------------------*/
1065 static const void *
1066 usb_temp_get_string_desc(struct usb_device *udev,
1067     uint16_t lang_id, uint8_t string_index)
1068 {
1069 	const struct usb_temp_device_desc *tdd;
1070 
1071 	tdd = usb_temp_get_tdd(udev);
1072 	if (tdd == NULL) {
1073 		return (NULL);
1074 	}
1075 	if (tdd->getStringDesc == NULL) {
1076 		return (NULL);
1077 	}
1078 	return ((tdd->getStringDesc) (lang_id, string_index));
1079 }
1080 
1081 /*------------------------------------------------------------------------*
1082  *	usb_temp_get_hub_desc
1083  *
1084  * Returns:
1085  *  NULL: No USB HUB descriptor found.
1086  *  Else: Pointer to a USB HUB descriptor.
1087  *------------------------------------------------------------------------*/
1088 static const void *
1089 usb_temp_get_hub_desc(struct usb_device *udev)
1090 {
1091 	return (NULL);			/* needs to be implemented */
1092 }
1093 
1094 /*------------------------------------------------------------------------*
1095  *	usb_temp_get_desc
1096  *
1097  * This function is a demultiplexer for local USB device side control
1098  * endpoint requests.
1099  *------------------------------------------------------------------------*/
1100 static usb_error_t
1101 usb_temp_get_desc(struct usb_device *udev, struct usb_device_request *req,
1102     const void **pPtr, uint16_t *pLength)
1103 {
1104 	const uint8_t *buf;
1105 	uint16_t len;
1106 
1107 	buf = NULL;
1108 	len = 0;
1109 
1110 	switch (req->bmRequestType) {
1111 	case UT_READ_DEVICE:
1112 		switch (req->bRequest) {
1113 		case UR_GET_DESCRIPTOR:
1114 			goto tr_handle_get_descriptor;
1115 		default:
1116 			goto tr_stalled;
1117 		}
1118 	case UT_READ_CLASS_DEVICE:
1119 		switch (req->bRequest) {
1120 		case UR_GET_DESCRIPTOR:
1121 			goto tr_handle_get_class_descriptor;
1122 		default:
1123 			goto tr_stalled;
1124 		}
1125 	default:
1126 		goto tr_stalled;
1127 	}
1128 
1129 tr_handle_get_descriptor:
1130 	switch (req->wValue[1]) {
1131 	case UDESC_DEVICE:
1132 		if (req->wValue[0]) {
1133 			goto tr_stalled;
1134 		}
1135 		buf = usb_temp_get_device_desc(udev);
1136 		goto tr_valid;
1137 	case UDESC_DEVICE_QUALIFIER:
1138 		if (udev->speed != USB_SPEED_HIGH) {
1139 			goto tr_stalled;
1140 		}
1141 		if (req->wValue[0]) {
1142 			goto tr_stalled;
1143 		}
1144 		buf = usb_temp_get_qualifier_desc(udev);
1145 		goto tr_valid;
1146 	case UDESC_OTHER_SPEED_CONFIGURATION:
1147 		if (udev->speed != USB_SPEED_HIGH) {
1148 			goto tr_stalled;
1149 		}
1150 	case UDESC_CONFIG:
1151 		buf = usb_temp_get_config_desc(udev,
1152 		    &len, req->wValue[0]);
1153 		goto tr_valid;
1154 	case UDESC_STRING:
1155 		buf = usb_temp_get_string_desc(udev,
1156 		    UGETW(req->wIndex), req->wValue[0]);
1157 		goto tr_valid;
1158 	default:
1159 		goto tr_stalled;
1160 	}
1161 
1162 tr_handle_get_class_descriptor:
1163 	if (req->wValue[0]) {
1164 		goto tr_stalled;
1165 	}
1166 	buf = usb_temp_get_hub_desc(udev);
1167 	goto tr_valid;
1168 
1169 tr_valid:
1170 	if (buf == NULL)
1171 		goto tr_stalled;
1172 	if (len == 0)
1173 		len = buf[0];
1174 	*pPtr = buf;
1175 	*pLength = len;
1176 	return (0);	/* success */
1177 
1178 tr_stalled:
1179 	/* try to get a vendor specific descriptor */
1180 	len = 0;
1181 	buf = usb_temp_get_vendor_desc(udev, req, &len);
1182 	if (buf != NULL)
1183 		goto tr_valid;
1184 	*pPtr = NULL;
1185 	*pLength = 0;
1186 	return (0);	/* we ignore failures */
1187 }
1188 
1189 /*------------------------------------------------------------------------*
1190  *	usb_temp_setup
1191  *
1192  * This function generates USB descriptors according to the given USB
1193  * template device descriptor. It will also try to figure out the best
1194  * matching endpoint addresses using the hardware endpoint profiles.
1195  *
1196  * Returns:
1197  *    0: Success
1198  * Else: Failure
1199  *------------------------------------------------------------------------*/
1200 usb_error_t
1201 usb_temp_setup(struct usb_device *udev,
1202     const struct usb_temp_device_desc *tdd)
1203 {
1204 	struct usb_temp_setup *uts;
1205 	void *buf;
1206 	uint8_t n;
1207 
1208 	if (tdd == NULL) {
1209 		/* be NULL safe */
1210 		return (0);
1211 	}
1212 	uts = udev->bus->scratch[0].temp_setup;
1213 
1214 	bzero(uts, sizeof(*uts));
1215 
1216 	uts->usb_speed = udev->speed;
1217 	uts->self_powered = udev->flags.self_powered;
1218 
1219 	/* first pass */
1220 
1221 	usb_make_device_desc(uts, tdd);
1222 
1223 	if (uts->err) {
1224 		/* some error happened */
1225 		return (uts->err);
1226 	}
1227 	/* sanity check */
1228 	if (uts->size == 0) {
1229 		return (USB_ERR_INVAL);
1230 	}
1231 	/* allocate zeroed memory */
1232 	uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO);
1233 	if (uts->buf == NULL) {
1234 		/* could not allocate memory */
1235 		return (USB_ERR_NOMEM);
1236 	}
1237 	/* second pass */
1238 
1239 	uts->size = 0;
1240 
1241 	usb_make_device_desc(uts, tdd);
1242 
1243 	/*
1244 	 * Store a pointer to our descriptors:
1245 	 */
1246 	udev->usb_template_ptr = uts->buf;
1247 
1248 	if (uts->err) {
1249 		/* some error happened during second pass */
1250 		goto error;
1251 	}
1252 	/*
1253 	 * Resolve all endpoint addresses !
1254 	 */
1255 	buf = usb_temp_get_device_desc(udev);
1256 	uts->err = usb_hw_ep_resolve(udev, buf);
1257 	if (uts->err) {
1258 		DPRINTFN(0, "Could not resolve endpoints for "
1259 		    "Device Descriptor, error = %s\n",
1260 		    usbd_errstr(uts->err));
1261 		goto error;
1262 	}
1263 	for (n = 0;; n++) {
1264 
1265 		buf = usb_temp_get_config_desc(udev, NULL, n);
1266 		if (buf == NULL) {
1267 			break;
1268 		}
1269 		uts->err = usb_hw_ep_resolve(udev, buf);
1270 		if (uts->err) {
1271 			DPRINTFN(0, "Could not resolve endpoints for "
1272 			    "Config Descriptor %u, error = %s\n", n,
1273 			    usbd_errstr(uts->err));
1274 			goto error;
1275 		}
1276 	}
1277 	return (uts->err);
1278 
1279 error:
1280 	usb_temp_unsetup(udev);
1281 	return (uts->err);
1282 }
1283 
1284 /*------------------------------------------------------------------------*
1285  *	usb_temp_unsetup
1286  *
1287  * This function frees any memory associated with the currently
1288  * setup template, if any.
1289  *------------------------------------------------------------------------*/
1290 void
1291 usb_temp_unsetup(struct usb_device *udev)
1292 {
1293 	if (udev->usb_template_ptr) {
1294 
1295 		free(udev->usb_template_ptr, M_USB);
1296 
1297 		udev->usb_template_ptr = NULL;
1298 	}
1299 }
1300 
1301 static usb_error_t
1302 usb_temp_setup_by_index(struct usb_device *udev, uint16_t index)
1303 {
1304 	usb_error_t err;
1305 
1306 	switch (index) {
1307 	case 0:
1308 		err = usb_temp_setup(udev, &usb_template_msc);
1309 		break;
1310 	case 1:
1311 		err = usb_temp_setup(udev, &usb_template_cdce);
1312 		break;
1313 	case 2:
1314 		err = usb_temp_setup(udev, &usb_template_mtp);
1315 		break;
1316 	default:
1317 		return (USB_ERR_INVAL);
1318 	}
1319 
1320 	return (err);
1321 }
1322 
1323 static void
1324 usb_temp_init(void *arg)
1325 {
1326 	/* register our functions */
1327 	usb_temp_get_desc_p = &usb_temp_get_desc;
1328 	usb_temp_setup_by_index_p = &usb_temp_setup_by_index;
1329 	usb_temp_unsetup_p = &usb_temp_unsetup;
1330 }
1331 
1332 SYSINIT(usb_temp_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_temp_init, NULL);
1333 SYSUNINIT(usb_temp_unload, SI_SUB_LOCK, SI_ORDER_ANY, usb_temp_unload, NULL);
1334