3 * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 * This file contains sub-routines to build up USB descriptors from
32 #ifdef USB_GLOBAL_INCLUDE_FILE
33 #include USB_GLOBAL_INCLUDE_FILE
35 #include <sys/stdint.h>
36 #include <sys/stddef.h>
37 #include <sys/param.h>
38 #include <sys/queue.h>
39 #include <sys/types.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
43 #include <sys/module.h>
45 #include <sys/mutex.h>
46 #include <sys/condvar.h>
47 #include <sys/sysctl.h>
49 #include <sys/unistd.h>
50 #include <sys/callout.h>
51 #include <sys/malloc.h>
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usb_ioctl.h>
56 #include <dev/usb/usbdi.h>
57 #include <dev/usb/usbdi_util.h>
60 #include <dev/usb/usb_cdc.h>
61 #include <dev/usb/usb_core.h>
62 #include <dev/usb/usb_dynamic.h>
63 #include <dev/usb/usb_busdma.h>
64 #include <dev/usb/usb_process.h>
65 #include <dev/usb/usb_device.h>
67 #define USB_DEBUG_VAR usb_debug
68 #include <dev/usb/usb_debug.h>
70 #include <dev/usb/usb_controller.h>
71 #include <dev/usb/usb_bus.h>
72 #include <dev/usb/usb_request.h>
73 #include <dev/usb/template/usb_template.h>
74 #endif /* USB_GLOBAL_INCLUDE_FILE */
76 MODULE_DEPEND(usb_template, usb, 1, 1, 1);
77 MODULE_VERSION(usb_template, 1);
79 /* function prototypes */
81 static void usb_make_raw_desc(struct usb_temp_setup *, const uint8_t *);
82 static void usb_make_endpoint_desc(struct usb_temp_setup *,
83 const struct usb_temp_endpoint_desc *);
84 static void usb_make_interface_desc(struct usb_temp_setup *,
85 const struct usb_temp_interface_desc *);
86 static void usb_make_config_desc(struct usb_temp_setup *,
87 const struct usb_temp_config_desc *);
88 static void usb_make_device_desc(struct usb_temp_setup *,
89 const struct usb_temp_device_desc *);
90 static uint8_t usb_hw_ep_match(const struct usb_hw_ep_profile *, uint8_t,
92 static uint8_t usb_hw_ep_find_match(struct usb_hw_ep_scratch *,
93 struct usb_hw_ep_scratch_sub *, uint8_t);
94 static uint8_t usb_hw_ep_get_needs(struct usb_hw_ep_scratch *, uint8_t,
96 static usb_error_t usb_hw_ep_resolve(struct usb_device *,
97 struct usb_descriptor *);
98 static const struct usb_temp_device_desc *usb_temp_get_tdd(struct usb_device *);
99 static void *usb_temp_get_device_desc(struct usb_device *);
100 static void *usb_temp_get_qualifier_desc(struct usb_device *);
101 static void *usb_temp_get_config_desc(struct usb_device *, uint16_t *,
103 static const void *usb_temp_get_string_desc(struct usb_device *, uint16_t,
105 static const void *usb_temp_get_vendor_desc(struct usb_device *,
106 const struct usb_device_request *, uint16_t *plen);
107 static const void *usb_temp_get_hub_desc(struct usb_device *);
108 static usb_error_t usb_temp_get_desc(struct usb_device *,
109 struct usb_device_request *, const void **, uint16_t *);
110 static usb_error_t usb_temp_setup_by_index(struct usb_device *,
112 static void usb_temp_init(void *);
114 /*------------------------------------------------------------------------*
117 * This function will insert a raw USB descriptor into the generated
119 *------------------------------------------------------------------------*/
121 usb_make_raw_desc(struct usb_temp_setup *temp,
128 * The first byte of any USB descriptor gives the length.
133 dst = USB_ADD_BYTES(temp->buf, temp->size);
134 memcpy(dst, raw, len);
136 /* check if we have got a CDC union descriptor */
138 if ((raw[0] >= sizeof(struct usb_cdc_union_descriptor)) &&
139 (raw[1] == UDESC_CS_INTERFACE) &&
140 (raw[2] == UDESCSUB_CDC_UNION)) {
141 struct usb_cdc_union_descriptor *ud = (void *)dst;
143 /* update the interface numbers */
145 ud->bMasterInterface +=
146 temp->bInterfaceNumber;
147 ud->bSlaveInterface[0] +=
148 temp->bInterfaceNumber;
151 /* check if we have got an interface association descriptor */
153 if ((raw[0] >= sizeof(struct usb_interface_assoc_descriptor)) &&
154 (raw[1] == UDESC_IFACE_ASSOC)) {
155 struct usb_interface_assoc_descriptor *iad = (void *)dst;
157 /* update the interface number */
159 iad->bFirstInterface +=
160 temp->bInterfaceNumber;
163 /* check if we have got a call management descriptor */
165 if ((raw[0] >= sizeof(struct usb_cdc_cm_descriptor)) &&
166 (raw[1] == UDESC_CS_INTERFACE) &&
167 (raw[2] == UDESCSUB_CDC_CM)) {
168 struct usb_cdc_cm_descriptor *ccd = (void *)dst;
170 /* update the interface number */
172 ccd->bDataInterface +=
173 temp->bInterfaceNumber;
180 /*------------------------------------------------------------------------*
181 * usb_make_endpoint_desc
183 * This function will generate an USB endpoint descriptor from the
184 * given USB template endpoint descriptor, which will be inserted into
185 * the USB configuration.
186 *------------------------------------------------------------------------*/
188 usb_make_endpoint_desc(struct usb_temp_setup *temp,
189 const struct usb_temp_endpoint_desc *ted)
191 struct usb_endpoint_descriptor *ed;
195 uint8_t ea; /* Endpoint Address */
196 uint8_t et; /* Endpiont Type */
199 old_size = temp->size;
201 ea = (ted->bEndpointAddress & (UE_ADDR | UE_DIR_IN | UE_DIR_OUT));
202 et = (ted->bmAttributes & UE_XFERTYPE);
204 if (et == UE_ISOCHRONOUS) {
205 /* account for extra byte fields */
206 temp->size += sizeof(*ed) + 2;
208 temp->size += sizeof(*ed);
211 /* Scan all Raw Descriptors first */
215 usb_make_raw_desc(temp, *rd);
219 if (ted->pPacketSize == NULL) {
220 /* not initialized */
221 temp->err = USB_ERR_INVAL;
224 mps = ted->pPacketSize->mps[temp->usb_speed];
226 /* not initialized */
227 temp->err = USB_ERR_INVAL;
229 } else if (mps == UE_ZERO_MPS) {
230 /* escape for Zero Max Packet Size */
235 * Fill out the real USB endpoint descriptor
236 * in case there is a buffer present:
239 ed = USB_ADD_BYTES(temp->buf, old_size);
240 if (et == UE_ISOCHRONOUS)
241 ed->bLength = sizeof(*ed) + 2;
243 ed->bLength = sizeof(*ed);
244 ed->bDescriptorType = UDESC_ENDPOINT;
245 ed->bEndpointAddress = ea;
246 ed->bmAttributes = ted->bmAttributes;
247 USETW(ed->wMaxPacketSize, mps);
249 /* setup bInterval parameter */
251 if (ted->pIntervals &&
252 ted->pIntervals->bInterval[temp->usb_speed]) {
254 ted->pIntervals->bInterval[temp->usb_speed];
259 ed->bInterval = 0; /* not used */
262 switch (temp->usb_speed) {
265 ed->bInterval = 1; /* 1 ms */
268 ed->bInterval = 4; /* 1 ms */
272 default: /* UE_ISOCHRONOUS */
273 switch (temp->usb_speed) {
276 ed->bInterval = 1; /* 1 ms */
279 ed->bInterval = 1; /* 125 us */
286 temp->bNumEndpoints++;
289 /*------------------------------------------------------------------------*
290 * usb_make_interface_desc
292 * This function will generate an USB interface descriptor from the
293 * given USB template interface descriptor, which will be inserted
294 * into the USB configuration.
295 *------------------------------------------------------------------------*/
297 usb_make_interface_desc(struct usb_temp_setup *temp,
298 const struct usb_temp_interface_desc *tid)
300 struct usb_interface_descriptor *id;
301 const struct usb_temp_endpoint_desc **ted;
307 old_size = temp->size;
308 temp->size += sizeof(*id);
310 /* Update interface and alternate interface numbers */
312 if (tid->isAltInterface == 0) {
313 temp->bAlternateSetting = 0;
314 temp->bInterfaceNumber++;
316 temp->bAlternateSetting++;
319 /* Scan all Raw Descriptors first */
325 usb_make_raw_desc(temp, *rd);
329 /* Reset some counters */
331 temp->bNumEndpoints = 0;
333 /* Scan all Endpoint Descriptors second */
335 ted = tid->ppEndpoints;
338 usb_make_endpoint_desc(temp, *ted);
343 * Fill out the real USB interface descriptor
344 * in case there is a buffer present:
347 id = USB_ADD_BYTES(temp->buf, old_size);
348 id->bLength = sizeof(*id);
349 id->bDescriptorType = UDESC_INTERFACE;
350 id->bInterfaceNumber = temp->bInterfaceNumber;
351 id->bAlternateSetting = temp->bAlternateSetting;
352 id->bNumEndpoints = temp->bNumEndpoints;
353 id->bInterfaceClass = tid->bInterfaceClass;
354 id->bInterfaceSubClass = tid->bInterfaceSubClass;
355 id->bInterfaceProtocol = tid->bInterfaceProtocol;
356 id->iInterface = tid->iInterface;
360 /*------------------------------------------------------------------------*
361 * usb_make_config_desc
363 * This function will generate an USB config descriptor from the given
364 * USB template config descriptor, which will be inserted into the USB
366 *------------------------------------------------------------------------*/
368 usb_make_config_desc(struct usb_temp_setup *temp,
369 const struct usb_temp_config_desc *tcd)
371 struct usb_config_descriptor *cd;
372 const struct usb_temp_interface_desc **tid;
377 old_size = temp->size;
378 temp->size += sizeof(*cd);
380 /* Reset some counters */
382 temp->bInterfaceNumber = 0xFF;
383 temp->bAlternateSetting = 0;
385 /* Scan all the USB interfaces */
387 tid = tcd->ppIfaceDesc;
390 usb_make_interface_desc(temp, *tid);
395 * Fill out the real USB config descriptor
396 * in case there is a buffer present:
399 cd = USB_ADD_BYTES(temp->buf, old_size);
401 /* compute total size */
402 old_size = temp->size - old_size;
404 cd->bLength = sizeof(*cd);
405 cd->bDescriptorType = UDESC_CONFIG;
406 USETW(cd->wTotalLength, old_size);
407 cd->bNumInterface = temp->bInterfaceNumber + 1;
408 cd->bConfigurationValue = temp->bConfigurationValue;
409 cd->iConfiguration = tcd->iConfiguration;
410 cd->bmAttributes = tcd->bmAttributes;
411 cd->bMaxPower = tcd->bMaxPower;
412 cd->bmAttributes |= (UC_REMOTE_WAKEUP | UC_BUS_POWERED);
414 if (temp->self_powered) {
415 cd->bmAttributes |= UC_SELF_POWERED;
417 cd->bmAttributes &= ~UC_SELF_POWERED;
422 /*------------------------------------------------------------------------*
423 * usb_make_device_desc
425 * This function will generate an USB device descriptor from the
426 * given USB template device descriptor.
427 *------------------------------------------------------------------------*/
429 usb_make_device_desc(struct usb_temp_setup *temp,
430 const struct usb_temp_device_desc *tdd)
432 struct usb_temp_data *utd;
433 const struct usb_temp_config_desc **tcd;
438 old_size = temp->size;
439 temp->size += sizeof(*utd);
441 /* Scan all the USB configs */
443 temp->bConfigurationValue = 1;
444 tcd = tdd->ppConfigDesc;
447 usb_make_config_desc(temp, *tcd);
448 temp->bConfigurationValue++;
453 * Fill out the real USB device descriptor
454 * in case there is a buffer present:
458 utd = USB_ADD_BYTES(temp->buf, old_size);
460 /* Store a pointer to our template device descriptor */
463 /* Fill out USB device descriptor */
464 utd->udd.bLength = sizeof(utd->udd);
465 utd->udd.bDescriptorType = UDESC_DEVICE;
466 utd->udd.bDeviceClass = tdd->bDeviceClass;
467 utd->udd.bDeviceSubClass = tdd->bDeviceSubClass;
468 utd->udd.bDeviceProtocol = tdd->bDeviceProtocol;
469 USETW(utd->udd.idVendor, tdd->idVendor);
470 USETW(utd->udd.idProduct, tdd->idProduct);
471 USETW(utd->udd.bcdDevice, tdd->bcdDevice);
472 utd->udd.iManufacturer = tdd->iManufacturer;
473 utd->udd.iProduct = tdd->iProduct;
474 utd->udd.iSerialNumber = tdd->iSerialNumber;
475 utd->udd.bNumConfigurations = temp->bConfigurationValue - 1;
478 * Fill out the USB device qualifier. Pretend that we
479 * don't support any other speeds by setting
480 * "bNumConfigurations" equal to zero. That saves us
481 * generating an extra set of configuration
484 utd->udq.bLength = sizeof(utd->udq);
485 utd->udq.bDescriptorType = UDESC_DEVICE_QUALIFIER;
486 utd->udq.bDeviceClass = tdd->bDeviceClass;
487 utd->udq.bDeviceSubClass = tdd->bDeviceSubClass;
488 utd->udq.bDeviceProtocol = tdd->bDeviceProtocol;
489 utd->udq.bNumConfigurations = 0;
490 USETW(utd->udq.bcdUSB, 0x0200);
491 utd->udq.bMaxPacketSize0 = 0;
493 switch (temp->usb_speed) {
495 USETW(utd->udd.bcdUSB, 0x0110);
496 utd->udd.bMaxPacketSize = 8;
499 USETW(utd->udd.bcdUSB, 0x0110);
500 utd->udd.bMaxPacketSize = 32;
503 USETW(utd->udd.bcdUSB, 0x0200);
504 utd->udd.bMaxPacketSize = 64;
506 case USB_SPEED_VARIABLE:
507 USETW(utd->udd.bcdUSB, 0x0250);
508 utd->udd.bMaxPacketSize = 255; /* 512 bytes */
510 case USB_SPEED_SUPER:
511 USETW(utd->udd.bcdUSB, 0x0300);
512 utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */
515 temp->err = USB_ERR_INVAL;
521 /*------------------------------------------------------------------------*
525 * 0: The endpoint profile does not match the criterias
526 * Else: The endpoint profile matches the criterias
527 *------------------------------------------------------------------------*/
529 usb_hw_ep_match(const struct usb_hw_ep_profile *pf,
530 uint8_t ep_type, uint8_t ep_dir_in)
532 if (ep_type == UE_CONTROL) {
534 return (pf->support_control);
536 if ((pf->support_in && ep_dir_in) ||
537 (pf->support_out && !ep_dir_in)) {
538 if ((pf->support_interrupt && (ep_type == UE_INTERRUPT)) ||
539 (pf->support_isochronous && (ep_type == UE_ISOCHRONOUS)) ||
540 (pf->support_bulk && (ep_type == UE_BULK))) {
547 /*------------------------------------------------------------------------*
548 * usb_hw_ep_find_match
550 * This function is used to find the best matching endpoint profile
551 * for and endpoint belonging to an USB descriptor.
554 * 0: Success. Got a match.
555 * Else: Failure. No match.
556 *------------------------------------------------------------------------*/
558 usb_hw_ep_find_match(struct usb_hw_ep_scratch *ues,
559 struct usb_hw_ep_scratch_sub *ep, uint8_t is_simplex)
561 const struct usb_hw_ep_profile *pf;
564 uint16_t max_frame_size;
573 if ((!ep->needs_in) && (!ep->needs_out)) {
574 return (0); /* we are done */
576 if (ep->needs_ep_type == UE_CONTROL) {
589 for (n = 1; n != (USB_EP_MAX / 2); n++) {
591 /* get HW endpoint profile */
592 (ues->methods->get_hw_ep_profile) (ues->udev, &pf, n);
594 /* end of profiles */
597 /* check if IN-endpoint is reserved */
598 if (dir_in || pf->is_simplex) {
599 if (ues->bmInAlloc[n / 8] & (1 << (n % 8))) {
604 /* check if OUT-endpoint is reserved */
605 if (dir_out || pf->is_simplex) {
606 if (ues->bmOutAlloc[n / 8] & (1 << (n % 8))) {
612 if (pf->is_simplex == is_simplex) {
616 /* check if HW endpoint matches */
617 if (!usb_hw_ep_match(pf, ep->needs_ep_type, dir_in)) {
621 /* get maximum frame size */
623 max_frame_size = pf->max_in_frame_size;
625 max_frame_size = pf->max_out_frame_size;
627 /* check if we have a matching profile */
628 if (max_frame_size >= ep->max_frame_size) {
629 temp = (max_frame_size - ep->max_frame_size);
630 if (distance > temp) {
638 /* see if we got a match */
640 /* get the correct profile */
643 /* reserve IN-endpoint */
645 ues->bmInAlloc[best_n / 8] |=
647 ep->hw_endpoint_in = best_n | UE_DIR_IN;
650 /* reserve OUT-endpoint */
652 ues->bmOutAlloc[best_n / 8] |=
654 ep->hw_endpoint_out = best_n | UE_DIR_OUT;
657 return (0); /* got a match */
659 return (1); /* failure */
662 /*------------------------------------------------------------------------*
663 * usb_hw_ep_get_needs
665 * This function will figure out the type and number of endpoints
666 * which are needed for an USB configuration.
671 *------------------------------------------------------------------------*/
673 usb_hw_ep_get_needs(struct usb_hw_ep_scratch *ues,
674 uint8_t ep_type, uint8_t is_complete)
676 const struct usb_hw_ep_profile *pf;
677 struct usb_hw_ep_scratch_sub *ep_iface;
678 struct usb_hw_ep_scratch_sub *ep_curr;
679 struct usb_hw_ep_scratch_sub *ep_max;
680 struct usb_hw_ep_scratch_sub *ep_end;
681 struct usb_descriptor *desc;
682 struct usb_interface_descriptor *id;
683 struct usb_endpoint_descriptor *ed;
684 enum usb_dev_speed speed;
685 uint16_t wMaxPacketSize;
689 ep_iface = ues->ep_max;
690 ep_curr = ues->ep_max;
691 ep_end = ues->ep + USB_EP_MAX;
692 ep_max = ues->ep_max;
694 speed = usbd_get_speed(ues->udev);
698 while ((desc = usb_desc_foreach(ues->cd, desc))) {
700 if ((desc->bDescriptorType == UDESC_INTERFACE) &&
701 (desc->bLength >= sizeof(*id))) {
705 if (id->bAlternateSetting == 0) {
713 if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
714 (desc->bLength >= sizeof(*ed))) {
718 goto handle_endpoint_desc;
721 ues->ep_max = ep_max;
724 handle_endpoint_desc:
725 temp = (ed->bmAttributes & UE_XFERTYPE);
727 if (temp == ep_type) {
729 if (ep_curr == ep_end) {
730 /* too many endpoints */
731 return (1); /* failure */
733 wMaxPacketSize = UGETW(ed->wMaxPacketSize);
734 if ((wMaxPacketSize & 0xF800) &&
735 (speed == USB_SPEED_HIGH)) {
736 /* handle packet multiplier */
737 temp = (wMaxPacketSize >> 11) & 3;
738 wMaxPacketSize &= 0x7FF;
746 * Check if we have a fixed endpoint number, else the
747 * endpoint number is allocated dynamically:
749 ep_no = (ed->bEndpointAddress & UE_ADDR);
752 /* get HW endpoint profile */
753 (ues->methods->get_hw_ep_profile)
754 (ues->udev, &pf, ep_no);
756 /* HW profile does not exist - failure */
757 DPRINTFN(0, "Endpoint profile %u "
758 "does not exist\n", ep_no);
761 /* reserve fixed endpoint number */
762 if (ep_type == UE_CONTROL) {
763 ues->bmInAlloc[ep_no / 8] |=
765 ues->bmOutAlloc[ep_no / 8] |=
767 if ((pf->max_in_frame_size < wMaxPacketSize) ||
768 (pf->max_out_frame_size < wMaxPacketSize)) {
769 DPRINTFN(0, "Endpoint profile %u "
770 "has too small buffer\n", ep_no);
773 } else if (ed->bEndpointAddress & UE_DIR_IN) {
774 ues->bmInAlloc[ep_no / 8] |=
776 if (pf->max_in_frame_size < wMaxPacketSize) {
777 DPRINTFN(0, "Endpoint profile %u "
778 "has too small buffer\n", ep_no);
782 ues->bmOutAlloc[ep_no / 8] |=
784 if (pf->max_out_frame_size < wMaxPacketSize) {
785 DPRINTFN(0, "Endpoint profile %u "
786 "has too small buffer\n", ep_no);
790 } else if (is_complete) {
792 /* check if we have enough buffer space */
794 ep_curr->max_frame_size) {
795 return (1); /* failure */
797 if (ed->bEndpointAddress & UE_DIR_IN) {
798 ed->bEndpointAddress =
799 ep_curr->hw_endpoint_in;
801 ed->bEndpointAddress =
802 ep_curr->hw_endpoint_out;
807 /* compute the maximum frame size */
808 if (ep_curr->max_frame_size < wMaxPacketSize) {
809 ep_curr->max_frame_size = wMaxPacketSize;
811 if (temp == UE_CONTROL) {
812 ep_curr->needs_in = 1;
813 ep_curr->needs_out = 1;
815 if (ed->bEndpointAddress & UE_DIR_IN) {
816 ep_curr->needs_in = 1;
818 ep_curr->needs_out = 1;
821 ep_curr->needs_ep_type = ep_type;
825 if (ep_max < ep_curr) {
832 /*------------------------------------------------------------------------*
835 * This function will try to resolve endpoint requirements by the
836 * given endpoint profiles that the USB hardware reports.
841 *------------------------------------------------------------------------*/
843 usb_hw_ep_resolve(struct usb_device *udev,
844 struct usb_descriptor *desc)
846 struct usb_hw_ep_scratch *ues;
847 struct usb_hw_ep_scratch_sub *ep;
848 const struct usb_hw_ep_profile *pf;
849 struct usb_bus_methods *methods;
850 struct usb_device_descriptor *dd;
854 return (USB_ERR_INVAL);
856 /* get bus methods */
857 methods = udev->bus->methods;
859 if (methods->get_hw_ep_profile == NULL)
860 return (USB_ERR_INVAL);
862 if (desc->bDescriptorType == UDESC_DEVICE) {
864 if (desc->bLength < sizeof(*dd))
865 return (USB_ERR_INVAL);
869 /* get HW control endpoint 0 profile */
870 (methods->get_hw_ep_profile) (udev, &pf, 0);
872 return (USB_ERR_INVAL);
874 if (!usb_hw_ep_match(pf, UE_CONTROL, 0)) {
875 DPRINTFN(0, "Endpoint 0 does not "
876 "support control\n");
877 return (USB_ERR_INVAL);
879 mps = dd->bMaxPacketSize;
881 if (udev->speed == USB_SPEED_FULL) {
883 * We can optionally choose another packet size !
886 /* check if "mps" is ok */
887 if (pf->max_in_frame_size >= mps) {
890 /* reduce maximum packet size */
893 /* check if "mps" is too small */
895 return (USB_ERR_INVAL);
899 dd->bMaxPacketSize = mps;
902 /* We only have one choice */
906 /* Check if we support the specified wMaxPacketSize */
907 if (pf->max_in_frame_size < mps) {
908 return (USB_ERR_INVAL);
911 return (0); /* success */
913 if (desc->bDescriptorType != UDESC_CONFIG)
914 return (USB_ERR_INVAL);
915 if (desc->bLength < sizeof(*(ues->cd)))
916 return (USB_ERR_INVAL);
918 ues = udev->scratch.hw_ep_scratch;
920 memset(ues, 0, sizeof(*ues));
922 ues->ep_max = ues->ep;
923 ues->cd = (void *)desc;
924 ues->methods = methods;
927 /* Get all the endpoints we need */
929 if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 0) ||
930 usb_hw_ep_get_needs(ues, UE_INTERRUPT, 0) ||
931 usb_hw_ep_get_needs(ues, UE_CONTROL, 0) ||
932 usb_hw_ep_get_needs(ues, UE_BULK, 0)) {
933 DPRINTFN(0, "Could not get needs\n");
934 return (USB_ERR_INVAL);
936 for (ep = ues->ep; ep != ues->ep_max; ep++) {
938 while (ep->needs_in || ep->needs_out) {
941 * First try to use a simplex endpoint.
942 * Then try to use a duplex endpoint.
944 if (usb_hw_ep_find_match(ues, ep, 1) &&
945 usb_hw_ep_find_match(ues, ep, 0)) {
946 DPRINTFN(0, "Could not find match\n");
947 return (USB_ERR_INVAL);
952 ues->ep_max = ues->ep;
954 /* Update all endpoint addresses */
956 if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 1) ||
957 usb_hw_ep_get_needs(ues, UE_INTERRUPT, 1) ||
958 usb_hw_ep_get_needs(ues, UE_CONTROL, 1) ||
959 usb_hw_ep_get_needs(ues, UE_BULK, 1)) {
960 DPRINTFN(0, "Could not update endpoint address\n");
961 return (USB_ERR_INVAL);
963 return (0); /* success */
966 /*------------------------------------------------------------------------*
970 * NULL: No USB template device descriptor found.
971 * Else: Pointer to the USB template device descriptor.
972 *------------------------------------------------------------------------*/
973 static const struct usb_temp_device_desc *
974 usb_temp_get_tdd(struct usb_device *udev)
976 if (udev->usb_template_ptr == NULL) {
979 return (udev->usb_template_ptr->tdd);
982 /*------------------------------------------------------------------------*
983 * usb_temp_get_device_desc
986 * NULL: No USB device descriptor found.
987 * Else: Pointer to USB device descriptor.
988 *------------------------------------------------------------------------*/
990 usb_temp_get_device_desc(struct usb_device *udev)
992 struct usb_device_descriptor *dd;
994 if (udev->usb_template_ptr == NULL) {
997 dd = &udev->usb_template_ptr->udd;
998 if (dd->bDescriptorType != UDESC_DEVICE) {
999 /* sanity check failed */
1005 /*------------------------------------------------------------------------*
1006 * usb_temp_get_qualifier_desc
1009 * NULL: No USB device_qualifier descriptor found.
1010 * Else: Pointer to USB device_qualifier descriptor.
1011 *------------------------------------------------------------------------*/
1013 usb_temp_get_qualifier_desc(struct usb_device *udev)
1015 struct usb_device_qualifier *dq;
1017 if (udev->usb_template_ptr == NULL) {
1020 dq = &udev->usb_template_ptr->udq;
1021 if (dq->bDescriptorType != UDESC_DEVICE_QUALIFIER) {
1022 /* sanity check failed */
1028 /*------------------------------------------------------------------------*
1029 * usb_temp_get_config_desc
1032 * NULL: No USB config descriptor found.
1033 * Else: Pointer to USB config descriptor having index "index".
1034 *------------------------------------------------------------------------*/
1036 usb_temp_get_config_desc(struct usb_device *udev,
1037 uint16_t *pLength, uint8_t index)
1039 struct usb_device_descriptor *dd;
1040 struct usb_config_descriptor *cd;
1043 if (udev->usb_template_ptr == NULL) {
1046 dd = &udev->usb_template_ptr->udd;
1047 cd = (void *)(udev->usb_template_ptr + 1);
1049 if (index >= dd->bNumConfigurations) {
1054 if (cd->bDescriptorType != UDESC_CONFIG) {
1055 /* sanity check failed */
1058 temp = UGETW(cd->wTotalLength);
1059 cd = USB_ADD_BYTES(cd, temp);
1063 *pLength = UGETW(cd->wTotalLength);
1068 /*------------------------------------------------------------------------*
1069 * usb_temp_get_vendor_desc
1072 * NULL: No vendor descriptor found.
1073 * Else: Pointer to a vendor descriptor.
1074 *------------------------------------------------------------------------*/
1076 usb_temp_get_vendor_desc(struct usb_device *udev,
1077 const struct usb_device_request *req, uint16_t *plen)
1079 const struct usb_temp_device_desc *tdd;
1081 tdd = usb_temp_get_tdd(udev);
1085 if (tdd->getVendorDesc == NULL) {
1088 return ((tdd->getVendorDesc) (req, plen));
1091 /*------------------------------------------------------------------------*
1092 * usb_temp_get_string_desc
1095 * NULL: No string descriptor found.
1096 * Else: Pointer to a string descriptor.
1097 *------------------------------------------------------------------------*/
1099 usb_temp_get_string_desc(struct usb_device *udev,
1100 uint16_t lang_id, uint8_t string_index)
1102 const struct usb_temp_device_desc *tdd;
1104 tdd = usb_temp_get_tdd(udev);
1108 if (tdd->getStringDesc == NULL) {
1111 return ((tdd->getStringDesc) (lang_id, string_index));
1114 /*------------------------------------------------------------------------*
1115 * usb_temp_get_hub_desc
1118 * NULL: No USB HUB descriptor found.
1119 * Else: Pointer to a USB HUB descriptor.
1120 *------------------------------------------------------------------------*/
1122 usb_temp_get_hub_desc(struct usb_device *udev)
1124 return (NULL); /* needs to be implemented */
1127 /*------------------------------------------------------------------------*
1130 * This function is a demultiplexer for local USB device side control
1131 * endpoint requests.
1132 *------------------------------------------------------------------------*/
1134 usb_temp_get_desc(struct usb_device *udev, struct usb_device_request *req,
1135 const void **pPtr, uint16_t *pLength)
1143 switch (req->bmRequestType) {
1144 case UT_READ_DEVICE:
1145 switch (req->bRequest) {
1146 case UR_GET_DESCRIPTOR:
1147 goto tr_handle_get_descriptor;
1151 case UT_READ_CLASS_DEVICE:
1152 switch (req->bRequest) {
1153 case UR_GET_DESCRIPTOR:
1154 goto tr_handle_get_class_descriptor;
1162 tr_handle_get_descriptor:
1163 switch (req->wValue[1]) {
1165 if (req->wValue[0]) {
1168 buf = usb_temp_get_device_desc(udev);
1170 case UDESC_DEVICE_QUALIFIER:
1171 if (udev->speed != USB_SPEED_HIGH) {
1174 if (req->wValue[0]) {
1177 buf = usb_temp_get_qualifier_desc(udev);
1179 case UDESC_OTHER_SPEED_CONFIGURATION:
1180 if (udev->speed != USB_SPEED_HIGH) {
1184 buf = usb_temp_get_config_desc(udev,
1185 &len, req->wValue[0]);
1188 buf = usb_temp_get_string_desc(udev,
1189 UGETW(req->wIndex), req->wValue[0]);
1195 tr_handle_get_class_descriptor:
1196 if (req->wValue[0]) {
1199 buf = usb_temp_get_hub_desc(udev);
1209 return (0); /* success */
1212 /* try to get a vendor specific descriptor */
1214 buf = usb_temp_get_vendor_desc(udev, req, &len);
1219 return (0); /* we ignore failures */
1222 /*------------------------------------------------------------------------*
1225 * This function generates USB descriptors according to the given USB
1226 * template device descriptor. It will also try to figure out the best
1227 * matching endpoint addresses using the hardware endpoint profiles.
1232 *------------------------------------------------------------------------*/
1234 usb_temp_setup(struct usb_device *udev,
1235 const struct usb_temp_device_desc *tdd)
1237 struct usb_temp_setup *uts;
1247 /* Protect scratch area */
1248 do_unlock = usbd_enum_lock(udev);
1250 uts = udev->scratch.temp_setup;
1252 memset(uts, 0, sizeof(*uts));
1254 uts->usb_speed = udev->speed;
1255 uts->self_powered = udev->flags.self_powered;
1259 usb_make_device_desc(uts, tdd);
1262 /* some error happened */
1266 if (uts->size == 0) {
1267 uts->err = USB_ERR_INVAL;
1270 /* allocate zeroed memory */
1271 uts->buf = usbd_alloc_config_desc(udev, uts->size);
1273 * Allow malloc() to return NULL regardless of M_WAITOK flag.
1274 * This helps when porting the software to non-FreeBSD
1277 if (uts->buf == NULL) {
1278 /* could not allocate memory */
1279 uts->err = USB_ERR_NOMEM;
1286 usb_make_device_desc(uts, tdd);
1289 * Store a pointer to our descriptors:
1291 udev->usb_template_ptr = uts->buf;
1294 /* some error happened during second pass */
1298 * Resolve all endpoint addresses !
1300 buf = usb_temp_get_device_desc(udev);
1301 uts->err = usb_hw_ep_resolve(udev, buf);
1303 DPRINTFN(0, "Could not resolve endpoints for "
1304 "Device Descriptor, error = %s\n",
1305 usbd_errstr(uts->err));
1310 buf = usb_temp_get_config_desc(udev, NULL, n);
1314 uts->err = usb_hw_ep_resolve(udev, buf);
1316 DPRINTFN(0, "Could not resolve endpoints for "
1317 "Config Descriptor %u, error = %s\n", n,
1318 usbd_errstr(uts->err));
1325 usb_temp_unsetup(udev);
1327 usbd_enum_unlock(udev);
1331 /*------------------------------------------------------------------------*
1334 * This function frees any memory associated with the currently
1335 * setup template, if any.
1336 *------------------------------------------------------------------------*/
1338 usb_temp_unsetup(struct usb_device *udev)
1340 usbd_free_config_desc(udev, udev->usb_template_ptr);
1341 udev->usb_template_ptr = NULL;
1345 usb_temp_setup_by_index(struct usb_device *udev, uint16_t index)
1351 err = usb_temp_setup(udev, &usb_template_msc);
1354 err = usb_temp_setup(udev, &usb_template_cdce);
1357 err = usb_temp_setup(udev, &usb_template_mtp);
1359 case USB_TEMP_MODEM:
1360 err = usb_temp_setup(udev, &usb_template_modem);
1362 case USB_TEMP_AUDIO:
1363 err = usb_temp_setup(udev, &usb_template_audio);
1366 err = usb_temp_setup(udev, &usb_template_kbd);
1368 case USB_TEMP_MOUSE:
1369 err = usb_temp_setup(udev, &usb_template_mouse);
1372 return (USB_ERR_INVAL);
1379 usb_temp_init(void *arg)
1381 /* register our functions */
1382 usb_temp_get_desc_p = &usb_temp_get_desc;
1383 usb_temp_setup_by_index_p = &usb_temp_setup_by_index;
1384 usb_temp_unsetup_p = &usb_temp_unsetup;
1387 SYSINIT(usb_temp_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_temp_init, NULL);
1388 SYSUNINIT(usb_temp_unload, SI_SUB_LOCK, SI_ORDER_ANY, usb_temp_unload, NULL);