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