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