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