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