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