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