3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * This file contains sub-routines to build up USB descriptors from
34 #ifdef USB_GLOBAL_INCLUDE_FILE
35 #include USB_GLOBAL_INCLUDE_FILE
37 #include <sys/stdint.h>
38 #include <sys/stddef.h>
39 #include <sys/param.h>
40 #include <sys/queue.h>
41 #include <sys/types.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
45 #include <sys/module.h>
47 #include <sys/mutex.h>
48 #include <sys/condvar.h>
49 #include <sys/sysctl.h>
51 #include <sys/unistd.h>
52 #include <sys/callout.h>
53 #include <sys/malloc.h>
56 #include <dev/usb/usb.h>
57 #include <dev/usb/usb_ioctl.h>
58 #include <dev/usb/usbdi.h>
59 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/usb_cdc.h>
63 #include <dev/usb/usb_core.h>
64 #include <dev/usb/usb_dynamic.h>
65 #include <dev/usb/usb_busdma.h>
66 #include <dev/usb/usb_process.h>
67 #include <dev/usb/usb_device.h>
68 #include <dev/usb/usb_util.h>
70 #define USB_DEBUG_VAR usb_debug
71 #include <dev/usb/usb_debug.h>
73 #include <dev/usb/usb_controller.h>
74 #include <dev/usb/usb_bus.h>
75 #include <dev/usb/usb_request.h>
76 #include <dev/usb/template/usb_template.h>
77 #endif /* USB_GLOBAL_INCLUDE_FILE */
79 MODULE_DEPEND(usb_template, usb, 1, 1, 1);
80 MODULE_VERSION(usb_template, 1);
82 /* function prototypes */
84 static int sysctl_hw_usb_template_power(SYSCTL_HANDLER_ARGS);
85 static void usb_make_raw_desc(struct usb_temp_setup *, const uint8_t *);
86 static void usb_make_endpoint_desc(struct usb_temp_setup *,
87 const struct usb_temp_endpoint_desc *);
88 static void usb_make_interface_desc(struct usb_temp_setup *,
89 const struct usb_temp_interface_desc *);
90 static void usb_make_config_desc(struct usb_temp_setup *,
91 const struct usb_temp_config_desc *);
92 static void usb_make_device_desc(struct usb_temp_setup *,
93 const struct usb_temp_device_desc *);
94 static uint8_t usb_hw_ep_match(const struct usb_hw_ep_profile *, uint8_t,
96 static uint8_t usb_hw_ep_find_match(struct usb_hw_ep_scratch *,
97 struct usb_hw_ep_scratch_sub *, uint8_t);
98 static uint8_t usb_hw_ep_get_needs(struct usb_hw_ep_scratch *, uint8_t,
100 static usb_error_t usb_hw_ep_resolve(struct usb_device *,
101 struct usb_descriptor *);
102 static const struct usb_temp_device_desc *usb_temp_get_tdd(struct usb_device *);
103 static void *usb_temp_get_device_desc(struct usb_device *);
104 static void *usb_temp_get_qualifier_desc(struct usb_device *);
105 static void *usb_temp_get_config_desc(struct usb_device *, uint16_t *,
107 static const void *usb_temp_get_string_desc(struct usb_device *, uint16_t,
109 static const void *usb_temp_get_vendor_desc(struct usb_device *,
110 const struct usb_device_request *, uint16_t *plen);
111 static const void *usb_temp_get_hub_desc(struct usb_device *);
112 static usb_error_t usb_temp_get_desc(struct usb_device *,
113 struct usb_device_request *, const void **, uint16_t *);
114 static usb_error_t usb_temp_setup_by_index(struct usb_device *,
116 static void usb_temp_init(void *);
118 SYSCTL_NODE(_hw_usb, OID_AUTO, templates, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
119 "USB device side templates");
120 SYSCTL_PROC(_hw_usb, OID_AUTO, template_power,
121 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
122 NULL, 0, sysctl_hw_usb_template_power,
123 "I", "USB bus power consumption in mA at 5V");
125 static int usb_template_power = 500; /* 500mA */
128 sysctl_hw_usb_template_power(SYSCTL_HANDLER_ARGS)
132 val = usb_template_power;
133 error = sysctl_handle_int(oidp, &val, 0, req);
134 if (error != 0 || req->newptr == NULL)
137 if (val < 0 || val > 500)
140 usb_template_power = val;
145 /*------------------------------------------------------------------------*
146 * usb_decode_str_desc
148 * Helper function to decode string descriptors into a C string.
149 *------------------------------------------------------------------------*/
151 usb_decode_str_desc(struct usb_string_descriptor *sd, char *buf, size_t buflen)
155 if (sd->bLength < 2) {
160 for (i = 0; i < buflen - 1 && i < (sd->bLength / 2) - 1; i++)
161 buf[i] = UGETW(sd->bString[i]);
166 /*------------------------------------------------------------------------*
169 * Callback for SYSCTL_PROC(9), to set and retrieve template string
171 *------------------------------------------------------------------------*/
173 usb_temp_sysctl(SYSCTL_HANDLER_ARGS)
176 struct usb_string_descriptor *sd = arg1;
177 size_t len, sdlen = arg2;
180 usb_decode_str_desc(sd, buf, sizeof(buf));
182 error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
183 if (error != 0 || req->newptr == NULL)
186 len = usb_make_str_desc(sd, sdlen, buf);
193 /*------------------------------------------------------------------------*
196 * This function will insert a raw USB descriptor into the generated
198 *------------------------------------------------------------------------*/
200 usb_make_raw_desc(struct usb_temp_setup *temp,
207 * The first byte of any USB descriptor gives the length.
212 dst = USB_ADD_BYTES(temp->buf, temp->size);
213 memcpy(dst, raw, len);
215 /* check if we have got a CDC union descriptor */
217 if ((raw[0] == sizeof(struct usb_cdc_union_descriptor)) &&
218 (raw[1] == UDESC_CS_INTERFACE) &&
219 (raw[2] == UDESCSUB_CDC_UNION)) {
220 struct usb_cdc_union_descriptor *ud = (void *)dst;
222 /* update the interface numbers */
224 ud->bMasterInterface +=
225 temp->bInterfaceNumber;
226 ud->bSlaveInterface[0] +=
227 temp->bInterfaceNumber;
230 /* check if we have got an interface association descriptor */
232 if ((raw[0] == sizeof(struct usb_interface_assoc_descriptor)) &&
233 (raw[1] == UDESC_IFACE_ASSOC)) {
234 struct usb_interface_assoc_descriptor *iad = (void *)dst;
236 /* update the interface number */
238 iad->bFirstInterface +=
239 temp->bInterfaceNumber;
242 /* check if we have got a call management descriptor */
244 if ((raw[0] == sizeof(struct usb_cdc_cm_descriptor)) &&
245 (raw[1] == UDESC_CS_INTERFACE) &&
246 (raw[2] == UDESCSUB_CDC_CM)) {
247 struct usb_cdc_cm_descriptor *ccd = (void *)dst;
249 /* update the interface number */
251 ccd->bDataInterface +=
252 temp->bInterfaceNumber;
259 /*------------------------------------------------------------------------*
260 * usb_make_endpoint_desc
262 * This function will generate an USB endpoint descriptor from the
263 * given USB template endpoint descriptor, which will be inserted into
264 * the USB configuration.
265 *------------------------------------------------------------------------*/
267 usb_make_endpoint_desc(struct usb_temp_setup *temp,
268 const struct usb_temp_endpoint_desc *ted)
270 struct usb_endpoint_descriptor *ed;
274 uint8_t ea; /* Endpoint Address */
275 uint8_t et; /* Endpiont Type */
278 old_size = temp->size;
280 ea = (ted->bEndpointAddress & (UE_ADDR | UE_DIR_IN | UE_DIR_OUT));
281 et = (ted->bmAttributes & UE_XFERTYPE);
283 if (et == UE_ISOCHRONOUS) {
284 /* account for extra byte fields */
285 temp->size += sizeof(*ed) + 2;
287 temp->size += sizeof(*ed);
290 /* Scan all Raw Descriptors first */
294 usb_make_raw_desc(temp, *rd);
298 if (ted->pPacketSize == NULL) {
299 /* not initialized */
300 temp->err = USB_ERR_INVAL;
303 mps = ted->pPacketSize->mps[temp->usb_speed];
305 /* not initialized */
306 temp->err = USB_ERR_INVAL;
308 } else if (mps == UE_ZERO_MPS) {
309 /* escape for Zero Max Packet Size */
314 * Fill out the real USB endpoint descriptor
315 * in case there is a buffer present:
318 ed = USB_ADD_BYTES(temp->buf, old_size);
319 if (et == UE_ISOCHRONOUS)
320 ed->bLength = sizeof(*ed) + 2;
322 ed->bLength = sizeof(*ed);
323 ed->bDescriptorType = UDESC_ENDPOINT;
324 ed->bEndpointAddress = ea;
325 ed->bmAttributes = ted->bmAttributes;
326 USETW(ed->wMaxPacketSize, mps);
328 /* setup bInterval parameter */
330 if (ted->pIntervals &&
331 ted->pIntervals->bInterval[temp->usb_speed]) {
333 ted->pIntervals->bInterval[temp->usb_speed];
338 ed->bInterval = 0; /* not used */
341 switch (temp->usb_speed) {
344 ed->bInterval = 1; /* 1 ms */
347 ed->bInterval = 4; /* 1 ms */
351 default: /* UE_ISOCHRONOUS */
352 switch (temp->usb_speed) {
355 ed->bInterval = 1; /* 1 ms */
358 ed->bInterval = 1; /* 125 us */
365 temp->bNumEndpoints++;
368 /*------------------------------------------------------------------------*
369 * usb_make_interface_desc
371 * This function will generate an USB interface descriptor from the
372 * given USB template interface descriptor, which will be inserted
373 * into the USB configuration.
374 *------------------------------------------------------------------------*/
376 usb_make_interface_desc(struct usb_temp_setup *temp,
377 const struct usb_temp_interface_desc *tid)
379 struct usb_interface_descriptor *id;
380 const struct usb_temp_endpoint_desc **ted;
386 old_size = temp->size;
387 temp->size += sizeof(*id);
389 /* Update interface and alternate interface numbers */
391 if (tid->isAltInterface == 0) {
392 temp->bAlternateSetting = 0;
393 temp->bInterfaceNumber++;
395 temp->bAlternateSetting++;
398 /* Scan all Raw Descriptors first */
404 usb_make_raw_desc(temp, *rd);
408 /* Reset some counters */
410 temp->bNumEndpoints = 0;
412 /* Scan all Endpoint Descriptors second */
414 ted = tid->ppEndpoints;
417 usb_make_endpoint_desc(temp, *ted);
422 * Fill out the real USB interface descriptor
423 * in case there is a buffer present:
426 id = USB_ADD_BYTES(temp->buf, old_size);
427 id->bLength = sizeof(*id);
428 id->bDescriptorType = UDESC_INTERFACE;
429 id->bInterfaceNumber = temp->bInterfaceNumber;
430 id->bAlternateSetting = temp->bAlternateSetting;
431 id->bNumEndpoints = temp->bNumEndpoints;
432 id->bInterfaceClass = tid->bInterfaceClass;
433 id->bInterfaceSubClass = tid->bInterfaceSubClass;
434 id->bInterfaceProtocol = tid->bInterfaceProtocol;
435 id->iInterface = tid->iInterface;
439 /*------------------------------------------------------------------------*
440 * usb_make_config_desc
442 * This function will generate an USB config descriptor from the given
443 * USB template config descriptor, which will be inserted into the USB
445 *------------------------------------------------------------------------*/
447 usb_make_config_desc(struct usb_temp_setup *temp,
448 const struct usb_temp_config_desc *tcd)
450 struct usb_config_descriptor *cd;
451 const struct usb_temp_interface_desc **tid;
457 old_size = temp->size;
458 temp->size += sizeof(*cd);
460 /* Reset some counters */
462 temp->bInterfaceNumber = 0xFF;
463 temp->bAlternateSetting = 0;
465 /* Scan all the USB interfaces */
467 tid = tcd->ppIfaceDesc;
470 usb_make_interface_desc(temp, *tid);
475 * Fill out the real USB config descriptor
476 * in case there is a buffer present:
479 cd = USB_ADD_BYTES(temp->buf, old_size);
481 /* compute total size */
482 old_size = temp->size - old_size;
484 cd->bLength = sizeof(*cd);
485 cd->bDescriptorType = UDESC_CONFIG;
486 USETW(cd->wTotalLength, old_size);
487 cd->bNumInterface = temp->bInterfaceNumber + 1;
488 cd->bConfigurationValue = temp->bConfigurationValue;
489 cd->iConfiguration = tcd->iConfiguration;
490 cd->bmAttributes = tcd->bmAttributes;
492 power = usb_template_power;
493 cd->bMaxPower = power / 2; /* 2 mA units */
494 cd->bmAttributes |= UC_REMOTE_WAKEUP;
496 cd->bmAttributes |= UC_BUS_POWERED;
497 cd->bmAttributes &= ~UC_SELF_POWERED;
499 cd->bmAttributes &= ~UC_BUS_POWERED;
500 cd->bmAttributes |= UC_SELF_POWERED;
505 /*------------------------------------------------------------------------*
506 * usb_make_device_desc
508 * This function will generate an USB device descriptor from the
509 * given USB template device descriptor.
510 *------------------------------------------------------------------------*/
512 usb_make_device_desc(struct usb_temp_setup *temp,
513 const struct usb_temp_device_desc *tdd)
515 struct usb_temp_data *utd;
516 const struct usb_temp_config_desc **tcd;
521 old_size = temp->size;
522 temp->size += sizeof(*utd);
524 /* Scan all the USB configs */
526 temp->bConfigurationValue = 1;
527 tcd = tdd->ppConfigDesc;
530 usb_make_config_desc(temp, *tcd);
531 temp->bConfigurationValue++;
536 * Fill out the real USB device descriptor
537 * in case there is a buffer present:
541 utd = USB_ADD_BYTES(temp->buf, old_size);
543 /* Store a pointer to our template device descriptor */
546 /* Fill out USB device descriptor */
547 utd->udd.bLength = sizeof(utd->udd);
548 utd->udd.bDescriptorType = UDESC_DEVICE;
549 utd->udd.bDeviceClass = tdd->bDeviceClass;
550 utd->udd.bDeviceSubClass = tdd->bDeviceSubClass;
551 utd->udd.bDeviceProtocol = tdd->bDeviceProtocol;
552 USETW(utd->udd.idVendor, tdd->idVendor);
553 USETW(utd->udd.idProduct, tdd->idProduct);
554 USETW(utd->udd.bcdDevice, tdd->bcdDevice);
555 utd->udd.iManufacturer = tdd->iManufacturer;
556 utd->udd.iProduct = tdd->iProduct;
557 utd->udd.iSerialNumber = tdd->iSerialNumber;
558 utd->udd.bNumConfigurations = temp->bConfigurationValue - 1;
561 * Fill out the USB device qualifier. Pretend that we
562 * don't support any other speeds by setting
563 * "bNumConfigurations" equal to zero. That saves us
564 * generating an extra set of configuration
567 utd->udq.bLength = sizeof(utd->udq);
568 utd->udq.bDescriptorType = UDESC_DEVICE_QUALIFIER;
569 utd->udq.bDeviceClass = tdd->bDeviceClass;
570 utd->udq.bDeviceSubClass = tdd->bDeviceSubClass;
571 utd->udq.bDeviceProtocol = tdd->bDeviceProtocol;
572 utd->udq.bNumConfigurations = 0;
573 USETW(utd->udq.bcdUSB, 0x0200);
574 utd->udq.bMaxPacketSize0 = 0;
576 switch (temp->usb_speed) {
578 USETW(utd->udd.bcdUSB, 0x0110);
579 utd->udd.bMaxPacketSize = 8;
582 USETW(utd->udd.bcdUSB, 0x0110);
583 utd->udd.bMaxPacketSize = 32;
586 USETW(utd->udd.bcdUSB, 0x0200);
587 utd->udd.bMaxPacketSize = 64;
589 case USB_SPEED_VARIABLE:
590 USETW(utd->udd.bcdUSB, 0x0250);
591 utd->udd.bMaxPacketSize = 255; /* 512 bytes */
593 case USB_SPEED_SUPER:
594 USETW(utd->udd.bcdUSB, 0x0300);
595 utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */
598 temp->err = USB_ERR_INVAL;
604 /*------------------------------------------------------------------------*
608 * 0: The endpoint profile does not match the criteria
609 * Else: The endpoint profile matches the criteria
610 *------------------------------------------------------------------------*/
612 usb_hw_ep_match(const struct usb_hw_ep_profile *pf,
613 uint8_t ep_type, uint8_t ep_dir_in)
615 if (ep_type == UE_CONTROL) {
617 return (pf->support_control);
619 if ((pf->support_in && ep_dir_in) ||
620 (pf->support_out && !ep_dir_in)) {
621 if ((pf->support_interrupt && (ep_type == UE_INTERRUPT)) ||
622 (pf->support_isochronous && (ep_type == UE_ISOCHRONOUS)) ||
623 (pf->support_bulk && (ep_type == UE_BULK))) {
630 /*------------------------------------------------------------------------*
631 * usb_hw_ep_find_match
633 * This function is used to find the best matching endpoint profile
634 * for and endpoint belonging to an USB descriptor.
637 * 0: Success. Got a match.
638 * Else: Failure. No match.
639 *------------------------------------------------------------------------*/
641 usb_hw_ep_find_match(struct usb_hw_ep_scratch *ues,
642 struct usb_hw_ep_scratch_sub *ep, uint8_t is_simplex)
644 const struct usb_hw_ep_profile *pf;
647 uint16_t max_frame_size;
656 if ((!ep->needs_in) && (!ep->needs_out)) {
657 return (0); /* we are done */
659 if (ep->needs_ep_type == UE_CONTROL) {
672 for (n = 1; n != (USB_EP_MAX / 2); n++) {
673 /* get HW endpoint profile */
674 (ues->methods->get_hw_ep_profile) (ues->udev, &pf, n);
676 /* end of profiles */
679 /* check if IN-endpoint is reserved */
680 if (dir_in || pf->is_simplex) {
681 if (ues->bmInAlloc[n / 8] & (1 << (n % 8))) {
686 /* check if OUT-endpoint is reserved */
687 if (dir_out || pf->is_simplex) {
688 if (ues->bmOutAlloc[n / 8] & (1 << (n % 8))) {
694 if (pf->is_simplex == is_simplex) {
698 /* check if HW endpoint matches */
699 if (!usb_hw_ep_match(pf, ep->needs_ep_type, dir_in)) {
703 /* get maximum frame size */
705 max_frame_size = pf->max_in_frame_size;
707 max_frame_size = pf->max_out_frame_size;
709 /* check if we have a matching profile */
710 if (max_frame_size >= ep->max_frame_size) {
711 temp = (max_frame_size - ep->max_frame_size);
712 if (distance > temp) {
720 /* see if we got a match */
722 /* get the correct profile */
725 /* reserve IN-endpoint */
727 ues->bmInAlloc[best_n / 8] |=
729 ep->hw_endpoint_in = best_n | UE_DIR_IN;
732 /* reserve OUT-endpoint */
734 ues->bmOutAlloc[best_n / 8] |=
736 ep->hw_endpoint_out = best_n | UE_DIR_OUT;
739 return (0); /* got a match */
741 return (1); /* failure */
744 /*------------------------------------------------------------------------*
745 * usb_hw_ep_get_needs
747 * This function will figure out the type and number of endpoints
748 * which are needed for an USB configuration.
753 *------------------------------------------------------------------------*/
755 usb_hw_ep_get_needs(struct usb_hw_ep_scratch *ues,
756 uint8_t ep_type, uint8_t is_complete)
758 const struct usb_hw_ep_profile *pf;
759 struct usb_hw_ep_scratch_sub *ep_iface;
760 struct usb_hw_ep_scratch_sub *ep_curr;
761 struct usb_hw_ep_scratch_sub *ep_max;
762 struct usb_hw_ep_scratch_sub *ep_end;
763 struct usb_descriptor *desc;
764 struct usb_interface_descriptor *id;
765 struct usb_endpoint_descriptor *ed;
766 enum usb_dev_speed speed;
767 uint16_t wMaxPacketSize;
771 ep_iface = ues->ep_max;
772 ep_curr = ues->ep_max;
773 ep_end = ues->ep + USB_EP_MAX;
774 ep_max = ues->ep_max;
776 speed = usbd_get_speed(ues->udev);
780 while ((desc = usb_desc_foreach(ues->cd, desc))) {
781 if ((desc->bDescriptorType == UDESC_INTERFACE) &&
782 (desc->bLength >= sizeof(*id))) {
785 if (id->bAlternateSetting == 0) {
793 if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
794 (desc->bLength >= sizeof(*ed))) {
797 goto handle_endpoint_desc;
800 ues->ep_max = ep_max;
803 handle_endpoint_desc:
804 temp = (ed->bmAttributes & UE_XFERTYPE);
806 if (temp == ep_type) {
807 if (ep_curr == ep_end) {
808 /* too many endpoints */
809 return (1); /* failure */
811 wMaxPacketSize = UGETW(ed->wMaxPacketSize);
812 if ((wMaxPacketSize & 0xF800) &&
813 (speed == USB_SPEED_HIGH)) {
814 /* handle packet multiplier */
815 temp = (wMaxPacketSize >> 11) & 3;
816 wMaxPacketSize &= 0x7FF;
824 * Check if we have a fixed endpoint number, else the
825 * endpoint number is allocated dynamically:
827 ep_no = (ed->bEndpointAddress & UE_ADDR);
829 /* get HW endpoint profile */
830 (ues->methods->get_hw_ep_profile)
831 (ues->udev, &pf, ep_no);
833 /* HW profile does not exist - failure */
834 DPRINTFN(0, "Endpoint profile %u "
835 "does not exist\n", ep_no);
838 /* reserve fixed endpoint number */
839 if (ep_type == UE_CONTROL) {
840 ues->bmInAlloc[ep_no / 8] |=
842 ues->bmOutAlloc[ep_no / 8] |=
844 if ((pf->max_in_frame_size < wMaxPacketSize) ||
845 (pf->max_out_frame_size < wMaxPacketSize)) {
846 DPRINTFN(0, "Endpoint profile %u "
847 "has too small buffer\n", ep_no);
850 } else if (ed->bEndpointAddress & UE_DIR_IN) {
851 ues->bmInAlloc[ep_no / 8] |=
853 if (pf->max_in_frame_size < wMaxPacketSize) {
854 DPRINTFN(0, "Endpoint profile %u "
855 "has too small buffer\n", ep_no);
859 ues->bmOutAlloc[ep_no / 8] |=
861 if (pf->max_out_frame_size < wMaxPacketSize) {
862 DPRINTFN(0, "Endpoint profile %u "
863 "has too small buffer\n", ep_no);
867 } else if (is_complete) {
868 /* check if we have enough buffer space */
870 ep_curr->max_frame_size) {
871 return (1); /* failure */
873 if (ed->bEndpointAddress & UE_DIR_IN) {
874 ed->bEndpointAddress =
875 ep_curr->hw_endpoint_in;
877 ed->bEndpointAddress =
878 ep_curr->hw_endpoint_out;
882 /* compute the maximum frame size */
883 if (ep_curr->max_frame_size < wMaxPacketSize) {
884 ep_curr->max_frame_size = wMaxPacketSize;
886 if (temp == UE_CONTROL) {
887 ep_curr->needs_in = 1;
888 ep_curr->needs_out = 1;
890 if (ed->bEndpointAddress & UE_DIR_IN) {
891 ep_curr->needs_in = 1;
893 ep_curr->needs_out = 1;
896 ep_curr->needs_ep_type = ep_type;
900 if (ep_max < ep_curr) {
907 /*------------------------------------------------------------------------*
910 * This function will try to resolve endpoint requirements by the
911 * given endpoint profiles that the USB hardware reports.
916 *------------------------------------------------------------------------*/
918 usb_hw_ep_resolve(struct usb_device *udev,
919 struct usb_descriptor *desc)
921 struct usb_hw_ep_scratch *ues;
922 struct usb_hw_ep_scratch_sub *ep;
923 const struct usb_hw_ep_profile *pf;
924 const struct usb_bus_methods *methods;
925 struct usb_device_descriptor *dd;
929 return (USB_ERR_INVAL);
931 /* get bus methods */
932 methods = udev->bus->methods;
934 if (methods->get_hw_ep_profile == NULL)
935 return (USB_ERR_INVAL);
937 if (desc->bDescriptorType == UDESC_DEVICE) {
938 if (desc->bLength < sizeof(*dd))
939 return (USB_ERR_INVAL);
943 /* get HW control endpoint 0 profile */
944 (methods->get_hw_ep_profile) (udev, &pf, 0);
946 return (USB_ERR_INVAL);
948 if (!usb_hw_ep_match(pf, UE_CONTROL, 0)) {
949 DPRINTFN(0, "Endpoint 0 does not "
950 "support control\n");
951 return (USB_ERR_INVAL);
953 mps = dd->bMaxPacketSize;
955 if (udev->speed == USB_SPEED_FULL) {
957 * We can optionally choose another packet size !
960 /* check if "mps" is ok */
961 if (pf->max_in_frame_size >= mps) {
964 /* reduce maximum packet size */
967 /* check if "mps" is too small */
969 return (USB_ERR_INVAL);
973 dd->bMaxPacketSize = mps;
976 /* We only have one choice */
980 /* Check if we support the specified wMaxPacketSize */
981 if (pf->max_in_frame_size < mps) {
982 return (USB_ERR_INVAL);
985 return (0); /* success */
987 if (desc->bDescriptorType != UDESC_CONFIG)
988 return (USB_ERR_INVAL);
989 if (desc->bLength < sizeof(*(ues->cd)))
990 return (USB_ERR_INVAL);
992 ues = udev->scratch.hw_ep_scratch;
994 memset(ues, 0, sizeof(*ues));
996 ues->ep_max = ues->ep;
997 ues->cd = (void *)desc;
998 ues->methods = methods;
1001 /* Get all the endpoints we need */
1003 if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 0) ||
1004 usb_hw_ep_get_needs(ues, UE_INTERRUPT, 0) ||
1005 usb_hw_ep_get_needs(ues, UE_CONTROL, 0) ||
1006 usb_hw_ep_get_needs(ues, UE_BULK, 0)) {
1007 DPRINTFN(0, "Could not get needs\n");
1008 return (USB_ERR_INVAL);
1010 for (ep = ues->ep; ep != ues->ep_max; ep++) {
1011 while (ep->needs_in || ep->needs_out) {
1013 * First try to use a simplex endpoint.
1014 * Then try to use a duplex endpoint.
1016 if (usb_hw_ep_find_match(ues, ep, 1) &&
1017 usb_hw_ep_find_match(ues, ep, 0)) {
1018 DPRINTFN(0, "Could not find match\n");
1019 return (USB_ERR_INVAL);
1024 ues->ep_max = ues->ep;
1026 /* Update all endpoint addresses */
1028 if (usb_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 1) ||
1029 usb_hw_ep_get_needs(ues, UE_INTERRUPT, 1) ||
1030 usb_hw_ep_get_needs(ues, UE_CONTROL, 1) ||
1031 usb_hw_ep_get_needs(ues, UE_BULK, 1)) {
1032 DPRINTFN(0, "Could not update endpoint address\n");
1033 return (USB_ERR_INVAL);
1035 return (0); /* success */
1038 /*------------------------------------------------------------------------*
1042 * NULL: No USB template device descriptor found.
1043 * Else: Pointer to the USB template device descriptor.
1044 *------------------------------------------------------------------------*/
1045 static const struct usb_temp_device_desc *
1046 usb_temp_get_tdd(struct usb_device *udev)
1048 if (udev->usb_template_ptr == NULL) {
1051 return (udev->usb_template_ptr->tdd);
1054 /*------------------------------------------------------------------------*
1055 * usb_temp_get_device_desc
1058 * NULL: No USB device descriptor found.
1059 * Else: Pointer to USB device descriptor.
1060 *------------------------------------------------------------------------*/
1062 usb_temp_get_device_desc(struct usb_device *udev)
1064 struct usb_device_descriptor *dd;
1066 if (udev->usb_template_ptr == NULL) {
1069 dd = &udev->usb_template_ptr->udd;
1070 if (dd->bDescriptorType != UDESC_DEVICE) {
1071 /* sanity check failed */
1077 /*------------------------------------------------------------------------*
1078 * usb_temp_get_qualifier_desc
1081 * NULL: No USB device_qualifier descriptor found.
1082 * Else: Pointer to USB device_qualifier descriptor.
1083 *------------------------------------------------------------------------*/
1085 usb_temp_get_qualifier_desc(struct usb_device *udev)
1087 struct usb_device_qualifier *dq;
1089 if (udev->usb_template_ptr == NULL) {
1092 dq = &udev->usb_template_ptr->udq;
1093 if (dq->bDescriptorType != UDESC_DEVICE_QUALIFIER) {
1094 /* sanity check failed */
1100 /*------------------------------------------------------------------------*
1101 * usb_temp_get_config_desc
1104 * NULL: No USB config descriptor found.
1105 * Else: Pointer to USB config descriptor having index "index".
1106 *------------------------------------------------------------------------*/
1108 usb_temp_get_config_desc(struct usb_device *udev,
1109 uint16_t *pLength, uint8_t index)
1111 struct usb_device_descriptor *dd;
1112 struct usb_config_descriptor *cd;
1115 if (udev->usb_template_ptr == NULL) {
1118 dd = &udev->usb_template_ptr->udd;
1119 cd = (void *)(udev->usb_template_ptr + 1);
1121 if (index >= dd->bNumConfigurations) {
1126 if (cd->bDescriptorType != UDESC_CONFIG) {
1127 /* sanity check failed */
1130 temp = UGETW(cd->wTotalLength);
1131 cd = USB_ADD_BYTES(cd, temp);
1135 *pLength = UGETW(cd->wTotalLength);
1140 /*------------------------------------------------------------------------*
1141 * usb_temp_get_vendor_desc
1144 * NULL: No vendor descriptor found.
1145 * Else: Pointer to a vendor descriptor.
1146 *------------------------------------------------------------------------*/
1148 usb_temp_get_vendor_desc(struct usb_device *udev,
1149 const struct usb_device_request *req, uint16_t *plen)
1151 const struct usb_temp_device_desc *tdd;
1153 tdd = usb_temp_get_tdd(udev);
1157 if (tdd->getVendorDesc == NULL) {
1160 return ((tdd->getVendorDesc) (req, plen));
1163 /*------------------------------------------------------------------------*
1164 * usb_temp_get_string_desc
1167 * NULL: No string descriptor found.
1168 * Else: Pointer to a string descriptor.
1169 *------------------------------------------------------------------------*/
1171 usb_temp_get_string_desc(struct usb_device *udev,
1172 uint16_t lang_id, uint8_t string_index)
1174 const struct usb_temp_device_desc *tdd;
1176 tdd = usb_temp_get_tdd(udev);
1180 if (tdd->getStringDesc == NULL) {
1183 return ((tdd->getStringDesc) (lang_id, string_index));
1186 /*------------------------------------------------------------------------*
1187 * usb_temp_get_hub_desc
1190 * NULL: No USB HUB descriptor found.
1191 * Else: Pointer to a USB HUB descriptor.
1192 *------------------------------------------------------------------------*/
1194 usb_temp_get_hub_desc(struct usb_device *udev)
1196 return (NULL); /* needs to be implemented */
1199 /*------------------------------------------------------------------------*
1202 * This function is a demultiplexer for local USB device side control
1203 * endpoint requests.
1204 *------------------------------------------------------------------------*/
1206 usb_temp_get_desc(struct usb_device *udev, struct usb_device_request *req,
1207 const void **pPtr, uint16_t *pLength)
1215 switch (req->bmRequestType) {
1216 case UT_READ_DEVICE:
1217 switch (req->bRequest) {
1218 case UR_GET_DESCRIPTOR:
1219 goto tr_handle_get_descriptor;
1223 case UT_READ_CLASS_DEVICE:
1224 switch (req->bRequest) {
1225 case UR_GET_DESCRIPTOR:
1226 goto tr_handle_get_class_descriptor;
1234 tr_handle_get_descriptor:
1235 switch (req->wValue[1]) {
1237 if (req->wValue[0]) {
1240 buf = usb_temp_get_device_desc(udev);
1242 case UDESC_DEVICE_QUALIFIER:
1243 if (udev->speed != USB_SPEED_HIGH) {
1246 if (req->wValue[0]) {
1249 buf = usb_temp_get_qualifier_desc(udev);
1251 case UDESC_OTHER_SPEED_CONFIGURATION:
1252 if (udev->speed != USB_SPEED_HIGH) {
1256 buf = usb_temp_get_config_desc(udev,
1257 &len, req->wValue[0]);
1260 buf = usb_temp_get_string_desc(udev,
1261 UGETW(req->wIndex), req->wValue[0]);
1267 tr_handle_get_class_descriptor:
1268 if (req->wValue[0]) {
1271 buf = usb_temp_get_hub_desc(udev);
1281 return (0); /* success */
1284 /* try to get a vendor specific descriptor */
1286 buf = usb_temp_get_vendor_desc(udev, req, &len);
1291 return (0); /* we ignore failures */
1294 /*------------------------------------------------------------------------*
1297 * This function generates USB descriptors according to the given USB
1298 * template device descriptor. It will also try to figure out the best
1299 * matching endpoint addresses using the hardware endpoint profiles.
1304 *------------------------------------------------------------------------*/
1306 usb_temp_setup(struct usb_device *udev,
1307 const struct usb_temp_device_desc *tdd)
1309 struct usb_temp_setup *uts;
1319 /* Protect scratch area */
1320 do_unlock = usbd_ctrl_lock(udev);
1322 uts = udev->scratch.temp_setup;
1324 memset(uts, 0, sizeof(*uts));
1326 uts->usb_speed = udev->speed;
1327 uts->self_powered = udev->flags.self_powered;
1331 usb_make_device_desc(uts, tdd);
1334 /* some error happened */
1338 if (uts->size == 0) {
1339 uts->err = USB_ERR_INVAL;
1342 /* allocate zeroed memory */
1343 uts->buf = usbd_alloc_config_desc(udev, uts->size);
1345 * Allow malloc() to return NULL regardless of M_WAITOK flag.
1346 * This helps when porting the software to non-FreeBSD
1349 if (uts->buf == NULL) {
1350 /* could not allocate memory */
1351 uts->err = USB_ERR_NOMEM;
1358 usb_make_device_desc(uts, tdd);
1361 * Store a pointer to our descriptors:
1363 udev->usb_template_ptr = uts->buf;
1366 /* some error happened during second pass */
1370 * Resolve all endpoint addresses !
1372 buf = usb_temp_get_device_desc(udev);
1373 uts->err = usb_hw_ep_resolve(udev, buf);
1375 DPRINTFN(0, "Could not resolve endpoints for "
1376 "Device Descriptor, error = %s\n",
1377 usbd_errstr(uts->err));
1381 buf = usb_temp_get_config_desc(udev, NULL, n);
1385 uts->err = usb_hw_ep_resolve(udev, buf);
1387 DPRINTFN(0, "Could not resolve endpoints for "
1388 "Config Descriptor %u, error = %s\n", n,
1389 usbd_errstr(uts->err));
1396 usb_temp_unsetup(udev);
1398 usbd_ctrl_unlock(udev);
1402 /*------------------------------------------------------------------------*
1405 * This function frees any memory associated with the currently
1406 * setup template, if any.
1407 *------------------------------------------------------------------------*/
1409 usb_temp_unsetup(struct usb_device *udev)
1411 usbd_free_config_desc(udev, udev->usb_template_ptr);
1412 udev->usb_template_ptr = NULL;
1416 usb_temp_setup_by_index(struct usb_device *udev, uint16_t index)
1422 err = usb_temp_setup(udev, &usb_template_msc);
1425 err = usb_temp_setup(udev, &usb_template_cdce);
1428 err = usb_temp_setup(udev, &usb_template_mtp);
1430 case USB_TEMP_MODEM:
1431 err = usb_temp_setup(udev, &usb_template_modem);
1433 case USB_TEMP_AUDIO:
1434 err = usb_temp_setup(udev, &usb_template_audio);
1437 err = usb_temp_setup(udev, &usb_template_kbd);
1439 case USB_TEMP_MOUSE:
1440 err = usb_temp_setup(udev, &usb_template_mouse);
1442 case USB_TEMP_PHONE:
1443 err = usb_temp_setup(udev, &usb_template_phone);
1445 case USB_TEMP_SERIALNET:
1446 err = usb_temp_setup(udev, &usb_template_serialnet);
1449 err = usb_temp_setup(udev, &usb_template_midi);
1451 case USB_TEMP_MULTI:
1452 err = usb_temp_setup(udev, &usb_template_multi);
1454 case USB_TEMP_CDCEEM:
1455 err = usb_temp_setup(udev, &usb_template_cdceem);
1458 return (USB_ERR_INVAL);
1465 usb_temp_init(void *arg)
1467 /* register our functions */
1468 usb_temp_get_desc_p = &usb_temp_get_desc;
1469 usb_temp_setup_by_index_p = &usb_temp_setup_by_index;
1470 usb_temp_unsetup_p = &usb_temp_unsetup;
1473 SYSINIT(usb_temp_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_temp_init, NULL);
1474 SYSUNINIT(usb_temp_unload, SI_SUB_LOCK, SI_ORDER_ANY, usb_temp_unload, NULL);