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