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