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 * usb_make_raw_desc 195 * 196 * This function will insert a raw USB descriptor into the generated 197 * USB configuration. 198 *------------------------------------------------------------------------*/ 199 static void 200 usb_make_raw_desc(struct usb_temp_setup *temp, 201 const uint8_t *raw) 202 { 203 void *dst; 204 uint8_t len; 205 206 /* 207 * The first byte of any USB descriptor gives the length. 208 */ 209 if (raw) { 210 len = raw[0]; 211 if (temp->buf) { 212 dst = USB_ADD_BYTES(temp->buf, temp->size); 213 memcpy(dst, raw, len); 214 215 /* check if we have got a CDC union descriptor */ 216 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; 221 222 /* update the interface numbers */ 223 224 ud->bMasterInterface += 225 temp->bInterfaceNumber; 226 ud->bSlaveInterface[0] += 227 temp->bInterfaceNumber; 228 } 229 230 /* check if we have got an interface association descriptor */ 231 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; 235 236 /* update the interface number */ 237 238 iad->bFirstInterface += 239 temp->bInterfaceNumber; 240 } 241 242 /* check if we have got a call management descriptor */ 243 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; 248 249 /* update the interface number */ 250 251 ccd->bDataInterface += 252 temp->bInterfaceNumber; 253 } 254 } 255 temp->size += len; 256 } 257 } 258 259 /*------------------------------------------------------------------------* 260 * usb_make_endpoint_desc 261 * 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 *------------------------------------------------------------------------*/ 266 static void 267 usb_make_endpoint_desc(struct usb_temp_setup *temp, 268 const struct usb_temp_endpoint_desc *ted) 269 { 270 struct usb_endpoint_descriptor *ed; 271 const void **rd; 272 uint16_t old_size; 273 uint16_t mps; 274 uint8_t ea; /* Endpoint Address */ 275 uint8_t et; /* Endpiont Type */ 276 277 /* Reserve memory */ 278 old_size = temp->size; 279 280 ea = (ted->bEndpointAddress & (UE_ADDR | UE_DIR_IN | UE_DIR_OUT)); 281 et = (ted->bmAttributes & UE_XFERTYPE); 282 283 if (et == UE_ISOCHRONOUS) { 284 /* account for extra byte fields */ 285 temp->size += sizeof(*ed) + 2; 286 } else { 287 temp->size += sizeof(*ed); 288 } 289 290 /* Scan all Raw Descriptors first */ 291 rd = ted->ppRawDesc; 292 if (rd) { 293 while (*rd) { 294 usb_make_raw_desc(temp, *rd); 295 rd++; 296 } 297 } 298 if (ted->pPacketSize == NULL) { 299 /* not initialized */ 300 temp->err = USB_ERR_INVAL; 301 return; 302 } 303 mps = ted->pPacketSize->mps[temp->usb_speed]; 304 if (mps == 0) { 305 /* not initialized */ 306 temp->err = USB_ERR_INVAL; 307 return; 308 } else if (mps == UE_ZERO_MPS) { 309 /* escape for Zero Max Packet Size */ 310 mps = 0; 311 } 312 313 /* 314 * Fill out the real USB endpoint descriptor 315 * in case there is a buffer present: 316 */ 317 if (temp->buf) { 318 ed = USB_ADD_BYTES(temp->buf, old_size); 319 if (et == UE_ISOCHRONOUS) 320 ed->bLength = sizeof(*ed) + 2; 321 else 322 ed->bLength = sizeof(*ed); 323 ed->bDescriptorType = UDESC_ENDPOINT; 324 ed->bEndpointAddress = ea; 325 ed->bmAttributes = ted->bmAttributes; 326 USETW(ed->wMaxPacketSize, mps); 327 328 /* setup bInterval parameter */ 329 330 if (ted->pIntervals && 331 ted->pIntervals->bInterval[temp->usb_speed]) { 332 ed->bInterval = 333 ted->pIntervals->bInterval[temp->usb_speed]; 334 } else { 335 switch (et) { 336 case UE_BULK: 337 case UE_CONTROL: 338 ed->bInterval = 0; /* not used */ 339 break; 340 case UE_INTERRUPT: 341 switch (temp->usb_speed) { 342 case USB_SPEED_LOW: 343 case USB_SPEED_FULL: 344 ed->bInterval = 1; /* 1 ms */ 345 break; 346 default: 347 ed->bInterval = 4; /* 1 ms */ 348 break; 349 } 350 break; 351 default: /* UE_ISOCHRONOUS */ 352 switch (temp->usb_speed) { 353 case USB_SPEED_LOW: 354 case USB_SPEED_FULL: 355 ed->bInterval = 1; /* 1 ms */ 356 break; 357 default: 358 ed->bInterval = 1; /* 125 us */ 359 break; 360 } 361 break; 362 } 363 } 364 } 365 temp->bNumEndpoints++; 366 } 367 368 /*------------------------------------------------------------------------* 369 * usb_make_interface_desc 370 * 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 *------------------------------------------------------------------------*/ 375 static void 376 usb_make_interface_desc(struct usb_temp_setup *temp, 377 const struct usb_temp_interface_desc *tid) 378 { 379 struct usb_interface_descriptor *id; 380 const struct usb_temp_endpoint_desc **ted; 381 const void **rd; 382 uint16_t old_size; 383 384 /* Reserve memory */ 385 386 old_size = temp->size; 387 temp->size += sizeof(*id); 388 389 /* Update interface and alternate interface numbers */ 390 391 if (tid->isAltInterface == 0) { 392 temp->bAlternateSetting = 0; 393 temp->bInterfaceNumber++; 394 } else { 395 temp->bAlternateSetting++; 396 } 397 398 /* Scan all Raw Descriptors first */ 399 400 rd = tid->ppRawDesc; 401 402 if (rd) { 403 while (*rd) { 404 usb_make_raw_desc(temp, *rd); 405 rd++; 406 } 407 } 408 /* Reset some counters */ 409 410 temp->bNumEndpoints = 0; 411 412 /* Scan all Endpoint Descriptors second */ 413 414 ted = tid->ppEndpoints; 415 if (ted) { 416 while (*ted) { 417 usb_make_endpoint_desc(temp, *ted); 418 ted++; 419 } 420 } 421 /* 422 * Fill out the real USB interface descriptor 423 * in case there is a buffer present: 424 */ 425 if (temp->buf) { 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; 436 } 437 } 438 439 /*------------------------------------------------------------------------* 440 * usb_make_config_desc 441 * 442 * This function will generate an USB config descriptor from the given 443 * USB template config descriptor, which will be inserted into the USB 444 * configuration. 445 *------------------------------------------------------------------------*/ 446 static void 447 usb_make_config_desc(struct usb_temp_setup *temp, 448 const struct usb_temp_config_desc *tcd) 449 { 450 struct usb_config_descriptor *cd; 451 const struct usb_temp_interface_desc **tid; 452 uint16_t old_size; 453 int power; 454 455 /* Reserve memory */ 456 457 old_size = temp->size; 458 temp->size += sizeof(*cd); 459 460 /* Reset some counters */ 461 462 temp->bInterfaceNumber = 0xFF; 463 temp->bAlternateSetting = 0; 464 465 /* Scan all the USB interfaces */ 466 467 tid = tcd->ppIfaceDesc; 468 if (tid) { 469 while (*tid) { 470 usb_make_interface_desc(temp, *tid); 471 tid++; 472 } 473 } 474 /* 475 * Fill out the real USB config descriptor 476 * in case there is a buffer present: 477 */ 478 if (temp->buf) { 479 cd = USB_ADD_BYTES(temp->buf, old_size); 480 481 /* compute total size */ 482 old_size = temp->size - old_size; 483 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; 491 492 power = usb_template_power; 493 cd->bMaxPower = power / 2; /* 2 mA units */ 494 cd->bmAttributes |= UC_REMOTE_WAKEUP; 495 if (power > 0) { 496 cd->bmAttributes |= UC_BUS_POWERED; 497 cd->bmAttributes &= ~UC_SELF_POWERED; 498 } else { 499 cd->bmAttributes &= ~UC_BUS_POWERED; 500 cd->bmAttributes |= UC_SELF_POWERED; 501 } 502 } 503 } 504 505 /*------------------------------------------------------------------------* 506 * usb_make_device_desc 507 * 508 * This function will generate an USB device descriptor from the 509 * given USB template device descriptor. 510 *------------------------------------------------------------------------*/ 511 static void 512 usb_make_device_desc(struct usb_temp_setup *temp, 513 const struct usb_temp_device_desc *tdd) 514 { 515 struct usb_temp_data *utd; 516 const struct usb_temp_config_desc **tcd; 517 uint16_t old_size; 518 519 /* Reserve memory */ 520 521 old_size = temp->size; 522 temp->size += sizeof(*utd); 523 524 /* Scan all the USB configs */ 525 526 temp->bConfigurationValue = 1; 527 tcd = tdd->ppConfigDesc; 528 if (tcd) { 529 while (*tcd) { 530 usb_make_config_desc(temp, *tcd); 531 temp->bConfigurationValue++; 532 tcd++; 533 } 534 } 535 /* 536 * Fill out the real USB device descriptor 537 * in case there is a buffer present: 538 */ 539 540 if (temp->buf) { 541 utd = USB_ADD_BYTES(temp->buf, old_size); 542 543 /* Store a pointer to our template device descriptor */ 544 utd->tdd = tdd; 545 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; 559 560 /* 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 565 * descriptors. 566 */ 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; 575 576 switch (temp->usb_speed) { 577 case USB_SPEED_LOW: 578 USETW(utd->udd.bcdUSB, 0x0110); 579 utd->udd.bMaxPacketSize = 8; 580 break; 581 case USB_SPEED_FULL: 582 USETW(utd->udd.bcdUSB, 0x0110); 583 utd->udd.bMaxPacketSize = 32; 584 break; 585 case USB_SPEED_HIGH: 586 USETW(utd->udd.bcdUSB, 0x0200); 587 utd->udd.bMaxPacketSize = 64; 588 break; 589 case USB_SPEED_VARIABLE: 590 USETW(utd->udd.bcdUSB, 0x0250); 591 utd->udd.bMaxPacketSize = 255; /* 512 bytes */ 592 break; 593 case USB_SPEED_SUPER: 594 USETW(utd->udd.bcdUSB, 0x0300); 595 utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */ 596 break; 597 default: 598 temp->err = USB_ERR_INVAL; 599 break; 600 } 601 } 602 } 603 604 /*------------------------------------------------------------------------* 605 * usb_hw_ep_match 606 * 607 * Return values: 608 * 0: The endpoint profile does not match the criteria 609 * Else: The endpoint profile matches the criteria 610 *------------------------------------------------------------------------*/ 611 static uint8_t 612 usb_hw_ep_match(const struct usb_hw_ep_profile *pf, 613 uint8_t ep_type, uint8_t ep_dir_in) 614 { 615 if (ep_type == UE_CONTROL) { 616 /* special */ 617 return (pf->support_control); 618 } 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))) { 624 return (1); 625 } 626 } 627 return (0); 628 } 629 630 /*------------------------------------------------------------------------* 631 * usb_hw_ep_find_match 632 * 633 * This function is used to find the best matching endpoint profile 634 * for and endpoint belonging to an USB descriptor. 635 * 636 * Return values: 637 * 0: Success. Got a match. 638 * Else: Failure. No match. 639 *------------------------------------------------------------------------*/ 640 static uint8_t 641 usb_hw_ep_find_match(struct usb_hw_ep_scratch *ues, 642 struct usb_hw_ep_scratch_sub *ep, uint8_t is_simplex) 643 { 644 const struct usb_hw_ep_profile *pf; 645 uint16_t distance; 646 uint16_t temp; 647 uint16_t max_frame_size; 648 uint8_t n; 649 uint8_t best_n; 650 uint8_t dir_in; 651 uint8_t dir_out; 652 653 distance = 0xFFFF; 654 best_n = 0; 655 656 if ((!ep->needs_in) && (!ep->needs_out)) { 657 return (0); /* we are done */ 658 } 659 if (ep->needs_ep_type == UE_CONTROL) { 660 dir_in = 1; 661 dir_out = 1; 662 } else { 663 if (ep->needs_in) { 664 dir_in = 1; 665 dir_out = 0; 666 } else { 667 dir_in = 0; 668 dir_out = 1; 669 } 670 } 671 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); 675 if (pf == NULL) { 676 /* end of profiles */ 677 break; 678 } 679 /* check if IN-endpoint is reserved */ 680 if (dir_in || pf->is_simplex) { 681 if (ues->bmInAlloc[n / 8] & (1 << (n % 8))) { 682 /* mismatch */ 683 continue; 684 } 685 } 686 /* check if OUT-endpoint is reserved */ 687 if (dir_out || pf->is_simplex) { 688 if (ues->bmOutAlloc[n / 8] & (1 << (n % 8))) { 689 /* mismatch */ 690 continue; 691 } 692 } 693 /* check simplex */ 694 if (pf->is_simplex == is_simplex) { 695 /* mismatch */ 696 continue; 697 } 698 /* check if HW endpoint matches */ 699 if (!usb_hw_ep_match(pf, ep->needs_ep_type, dir_in)) { 700 /* mismatch */ 701 continue; 702 } 703 /* get maximum frame size */ 704 if (dir_in) 705 max_frame_size = pf->max_in_frame_size; 706 else 707 max_frame_size = pf->max_out_frame_size; 708 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) { 713 distance = temp; 714 best_n = n; 715 ep->pf = pf; 716 } 717 } 718 } 719 720 /* see if we got a match */ 721 if (best_n != 0) { 722 /* get the correct profile */ 723 pf = ep->pf; 724 725 /* reserve IN-endpoint */ 726 if (dir_in) { 727 ues->bmInAlloc[best_n / 8] |= 728 (1 << (best_n % 8)); 729 ep->hw_endpoint_in = best_n | UE_DIR_IN; 730 ep->needs_in = 0; 731 } 732 /* reserve OUT-endpoint */ 733 if (dir_out) { 734 ues->bmOutAlloc[best_n / 8] |= 735 (1 << (best_n % 8)); 736 ep->hw_endpoint_out = best_n | UE_DIR_OUT; 737 ep->needs_out = 0; 738 } 739 return (0); /* got a match */ 740 } 741 return (1); /* failure */ 742 } 743 744 /*------------------------------------------------------------------------* 745 * usb_hw_ep_get_needs 746 * 747 * This function will figure out the type and number of endpoints 748 * which are needed for an USB configuration. 749 * 750 * Return values: 751 * 0: Success. 752 * Else: Failure. 753 *------------------------------------------------------------------------*/ 754 static uint8_t 755 usb_hw_ep_get_needs(struct usb_hw_ep_scratch *ues, 756 uint8_t ep_type, uint8_t is_complete) 757 { 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; 768 uint16_t temp; 769 uint8_t ep_no; 770 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; 775 desc = NULL; 776 speed = usbd_get_speed(ues->udev); 777 778 repeat: 779 780 while ((desc = usb_desc_foreach(ues->cd, desc))) { 781 if ((desc->bDescriptorType == UDESC_INTERFACE) && 782 (desc->bLength >= sizeof(*id))) { 783 id = (void *)desc; 784 785 if (id->bAlternateSetting == 0) { 786 /* going forward */ 787 ep_iface = ep_max; 788 } else { 789 /* reset */ 790 ep_curr = ep_iface; 791 } 792 } 793 if ((desc->bDescriptorType == UDESC_ENDPOINT) && 794 (desc->bLength >= sizeof(*ed))) { 795 ed = (void *)desc; 796 797 goto handle_endpoint_desc; 798 } 799 } 800 ues->ep_max = ep_max; 801 return (0); 802 803 handle_endpoint_desc: 804 temp = (ed->bmAttributes & UE_XFERTYPE); 805 806 if (temp == ep_type) { 807 if (ep_curr == ep_end) { 808 /* too many endpoints */ 809 return (1); /* failure */ 810 } 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; 817 if (temp == 1) { 818 wMaxPacketSize *= 2; 819 } else { 820 wMaxPacketSize *= 3; 821 } 822 } 823 /* 824 * Check if we have a fixed endpoint number, else the 825 * endpoint number is allocated dynamically: 826 */ 827 ep_no = (ed->bEndpointAddress & UE_ADDR); 828 if (ep_no != 0) { 829 /* get HW endpoint profile */ 830 (ues->methods->get_hw_ep_profile) 831 (ues->udev, &pf, ep_no); 832 if (pf == NULL) { 833 /* HW profile does not exist - failure */ 834 DPRINTFN(0, "Endpoint profile %u " 835 "does not exist\n", ep_no); 836 return (1); 837 } 838 /* reserve fixed endpoint number */ 839 if (ep_type == UE_CONTROL) { 840 ues->bmInAlloc[ep_no / 8] |= 841 (1 << (ep_no % 8)); 842 ues->bmOutAlloc[ep_no / 8] |= 843 (1 << (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); 848 return (1); 849 } 850 } else if (ed->bEndpointAddress & UE_DIR_IN) { 851 ues->bmInAlloc[ep_no / 8] |= 852 (1 << (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); 856 return (1); 857 } 858 } else { 859 ues->bmOutAlloc[ep_no / 8] |= 860 (1 << (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); 864 return (1); 865 } 866 } 867 } else if (is_complete) { 868 /* check if we have enough buffer space */ 869 if (wMaxPacketSize > 870 ep_curr->max_frame_size) { 871 return (1); /* failure */ 872 } 873 if (ed->bEndpointAddress & UE_DIR_IN) { 874 ed->bEndpointAddress = 875 ep_curr->hw_endpoint_in; 876 } else { 877 ed->bEndpointAddress = 878 ep_curr->hw_endpoint_out; 879 } 880 881 } else { 882 /* compute the maximum frame size */ 883 if (ep_curr->max_frame_size < wMaxPacketSize) { 884 ep_curr->max_frame_size = wMaxPacketSize; 885 } 886 if (temp == UE_CONTROL) { 887 ep_curr->needs_in = 1; 888 ep_curr->needs_out = 1; 889 } else { 890 if (ed->bEndpointAddress & UE_DIR_IN) { 891 ep_curr->needs_in = 1; 892 } else { 893 ep_curr->needs_out = 1; 894 } 895 } 896 ep_curr->needs_ep_type = ep_type; 897 } 898 899 ep_curr++; 900 if (ep_max < ep_curr) { 901 ep_max = ep_curr; 902 } 903 } 904 goto repeat; 905 } 906 907 /*------------------------------------------------------------------------* 908 * usb_hw_ep_resolve 909 * 910 * This function will try to resolve endpoint requirements by the 911 * given endpoint profiles that the USB hardware reports. 912 * 913 * Return values: 914 * 0: Success 915 * Else: Failure 916 *------------------------------------------------------------------------*/ 917 static usb_error_t 918 usb_hw_ep_resolve(struct usb_device *udev, 919 struct usb_descriptor *desc) 920 { 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; 926 uint16_t mps; 927 928 if (desc == NULL) 929 return (USB_ERR_INVAL); 930 931 /* get bus methods */ 932 methods = udev->bus->methods; 933 934 if (methods->get_hw_ep_profile == NULL) 935 return (USB_ERR_INVAL); 936 937 if (desc->bDescriptorType == UDESC_DEVICE) { 938 if (desc->bLength < sizeof(*dd)) 939 return (USB_ERR_INVAL); 940 941 dd = (void *)desc; 942 943 /* get HW control endpoint 0 profile */ 944 (methods->get_hw_ep_profile) (udev, &pf, 0); 945 if (pf == NULL) { 946 return (USB_ERR_INVAL); 947 } 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); 952 } 953 mps = dd->bMaxPacketSize; 954 955 if (udev->speed == USB_SPEED_FULL) { 956 /* 957 * We can optionally choose another packet size ! 958 */ 959 while (1) { 960 /* check if "mps" is ok */ 961 if (pf->max_in_frame_size >= mps) { 962 break; 963 } 964 /* reduce maximum packet size */ 965 mps /= 2; 966 967 /* check if "mps" is too small */ 968 if (mps < 8) { 969 return (USB_ERR_INVAL); 970 } 971 } 972 973 dd->bMaxPacketSize = mps; 974 975 } else { 976 /* We only have one choice */ 977 if (mps == 255) { 978 mps = 512; 979 } 980 /* Check if we support the specified wMaxPacketSize */ 981 if (pf->max_in_frame_size < mps) { 982 return (USB_ERR_INVAL); 983 } 984 } 985 return (0); /* success */ 986 } 987 if (desc->bDescriptorType != UDESC_CONFIG) 988 return (USB_ERR_INVAL); 989 if (desc->bLength < sizeof(*(ues->cd))) 990 return (USB_ERR_INVAL); 991 992 ues = udev->scratch.hw_ep_scratch; 993 994 memset(ues, 0, sizeof(*ues)); 995 996 ues->ep_max = ues->ep; 997 ues->cd = (void *)desc; 998 ues->methods = methods; 999 ues->udev = udev; 1000 1001 /* Get all the endpoints we need */ 1002 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); 1009 } 1010 for (ep = ues->ep; ep != ues->ep_max; ep++) { 1011 while (ep->needs_in || ep->needs_out) { 1012 /* 1013 * First try to use a simplex endpoint. 1014 * Then try to use a duplex endpoint. 1015 */ 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); 1020 } 1021 } 1022 } 1023 1024 ues->ep_max = ues->ep; 1025 1026 /* Update all endpoint addresses */ 1027 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); 1034 } 1035 return (0); /* success */ 1036 } 1037 1038 /*------------------------------------------------------------------------* 1039 * usb_temp_get_tdd 1040 * 1041 * Returns: 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) 1047 { 1048 if (udev->usb_template_ptr == NULL) { 1049 return (NULL); 1050 } 1051 return (udev->usb_template_ptr->tdd); 1052 } 1053 1054 /*------------------------------------------------------------------------* 1055 * usb_temp_get_device_desc 1056 * 1057 * Returns: 1058 * NULL: No USB device descriptor found. 1059 * Else: Pointer to USB device descriptor. 1060 *------------------------------------------------------------------------*/ 1061 static void * 1062 usb_temp_get_device_desc(struct usb_device *udev) 1063 { 1064 struct usb_device_descriptor *dd; 1065 1066 if (udev->usb_template_ptr == NULL) { 1067 return (NULL); 1068 } 1069 dd = &udev->usb_template_ptr->udd; 1070 if (dd->bDescriptorType != UDESC_DEVICE) { 1071 /* sanity check failed */ 1072 return (NULL); 1073 } 1074 return (dd); 1075 } 1076 1077 /*------------------------------------------------------------------------* 1078 * usb_temp_get_qualifier_desc 1079 * 1080 * Returns: 1081 * NULL: No USB device_qualifier descriptor found. 1082 * Else: Pointer to USB device_qualifier descriptor. 1083 *------------------------------------------------------------------------*/ 1084 static void * 1085 usb_temp_get_qualifier_desc(struct usb_device *udev) 1086 { 1087 struct usb_device_qualifier *dq; 1088 1089 if (udev->usb_template_ptr == NULL) { 1090 return (NULL); 1091 } 1092 dq = &udev->usb_template_ptr->udq; 1093 if (dq->bDescriptorType != UDESC_DEVICE_QUALIFIER) { 1094 /* sanity check failed */ 1095 return (NULL); 1096 } 1097 return (dq); 1098 } 1099 1100 /*------------------------------------------------------------------------* 1101 * usb_temp_get_config_desc 1102 * 1103 * Returns: 1104 * NULL: No USB config descriptor found. 1105 * Else: Pointer to USB config descriptor having index "index". 1106 *------------------------------------------------------------------------*/ 1107 static void * 1108 usb_temp_get_config_desc(struct usb_device *udev, 1109 uint16_t *pLength, uint8_t index) 1110 { 1111 struct usb_device_descriptor *dd; 1112 struct usb_config_descriptor *cd; 1113 uint16_t temp; 1114 1115 if (udev->usb_template_ptr == NULL) { 1116 return (NULL); 1117 } 1118 dd = &udev->usb_template_ptr->udd; 1119 cd = (void *)(udev->usb_template_ptr + 1); 1120 1121 if (index >= dd->bNumConfigurations) { 1122 /* out of range */ 1123 return (NULL); 1124 } 1125 while (index--) { 1126 if (cd->bDescriptorType != UDESC_CONFIG) { 1127 /* sanity check failed */ 1128 return (NULL); 1129 } 1130 temp = UGETW(cd->wTotalLength); 1131 cd = USB_ADD_BYTES(cd, temp); 1132 } 1133 1134 if (pLength) { 1135 *pLength = UGETW(cd->wTotalLength); 1136 } 1137 return (cd); 1138 } 1139 1140 /*------------------------------------------------------------------------* 1141 * usb_temp_get_vendor_desc 1142 * 1143 * Returns: 1144 * NULL: No vendor descriptor found. 1145 * Else: Pointer to a vendor descriptor. 1146 *------------------------------------------------------------------------*/ 1147 static const void * 1148 usb_temp_get_vendor_desc(struct usb_device *udev, 1149 const struct usb_device_request *req, uint16_t *plen) 1150 { 1151 const struct usb_temp_device_desc *tdd; 1152 1153 tdd = usb_temp_get_tdd(udev); 1154 if (tdd == NULL) { 1155 return (NULL); 1156 } 1157 if (tdd->getVendorDesc == NULL) { 1158 return (NULL); 1159 } 1160 return ((tdd->getVendorDesc) (req, plen)); 1161 } 1162 1163 /*------------------------------------------------------------------------* 1164 * usb_temp_get_string_desc 1165 * 1166 * Returns: 1167 * NULL: No string descriptor found. 1168 * Else: Pointer to a string descriptor. 1169 *------------------------------------------------------------------------*/ 1170 static const void * 1171 usb_temp_get_string_desc(struct usb_device *udev, 1172 uint16_t lang_id, uint8_t string_index) 1173 { 1174 const struct usb_temp_device_desc *tdd; 1175 1176 tdd = usb_temp_get_tdd(udev); 1177 if (tdd == NULL) { 1178 return (NULL); 1179 } 1180 if (tdd->getStringDesc == NULL) { 1181 return (NULL); 1182 } 1183 return ((tdd->getStringDesc) (lang_id, string_index)); 1184 } 1185 1186 /*------------------------------------------------------------------------* 1187 * usb_temp_get_hub_desc 1188 * 1189 * Returns: 1190 * NULL: No USB HUB descriptor found. 1191 * Else: Pointer to a USB HUB descriptor. 1192 *------------------------------------------------------------------------*/ 1193 static const void * 1194 usb_temp_get_hub_desc(struct usb_device *udev) 1195 { 1196 return (NULL); /* needs to be implemented */ 1197 } 1198 1199 /*------------------------------------------------------------------------* 1200 * usb_temp_get_desc 1201 * 1202 * This function is a demultiplexer for local USB device side control 1203 * endpoint requests. 1204 *------------------------------------------------------------------------*/ 1205 static usb_error_t 1206 usb_temp_get_desc(struct usb_device *udev, struct usb_device_request *req, 1207 const void **pPtr, uint16_t *pLength) 1208 { 1209 const uint8_t *buf; 1210 uint16_t len; 1211 1212 buf = NULL; 1213 len = 0; 1214 1215 switch (req->bmRequestType) { 1216 case UT_READ_DEVICE: 1217 switch (req->bRequest) { 1218 case UR_GET_DESCRIPTOR: 1219 goto tr_handle_get_descriptor; 1220 default: 1221 goto tr_stalled; 1222 } 1223 case UT_READ_CLASS_DEVICE: 1224 switch (req->bRequest) { 1225 case UR_GET_DESCRIPTOR: 1226 goto tr_handle_get_class_descriptor; 1227 default: 1228 goto tr_stalled; 1229 } 1230 default: 1231 goto tr_stalled; 1232 } 1233 1234 tr_handle_get_descriptor: 1235 switch (req->wValue[1]) { 1236 case UDESC_DEVICE: 1237 if (req->wValue[0]) { 1238 goto tr_stalled; 1239 } 1240 buf = usb_temp_get_device_desc(udev); 1241 goto tr_valid; 1242 case UDESC_DEVICE_QUALIFIER: 1243 if (udev->speed != USB_SPEED_HIGH) { 1244 goto tr_stalled; 1245 } 1246 if (req->wValue[0]) { 1247 goto tr_stalled; 1248 } 1249 buf = usb_temp_get_qualifier_desc(udev); 1250 goto tr_valid; 1251 case UDESC_OTHER_SPEED_CONFIGURATION: 1252 if (udev->speed != USB_SPEED_HIGH) { 1253 goto tr_stalled; 1254 } 1255 case UDESC_CONFIG: 1256 buf = usb_temp_get_config_desc(udev, 1257 &len, req->wValue[0]); 1258 goto tr_valid; 1259 case UDESC_STRING: 1260 buf = usb_temp_get_string_desc(udev, 1261 UGETW(req->wIndex), req->wValue[0]); 1262 goto tr_valid; 1263 default: 1264 goto tr_stalled; 1265 } 1266 1267 tr_handle_get_class_descriptor: 1268 if (req->wValue[0]) { 1269 goto tr_stalled; 1270 } 1271 buf = usb_temp_get_hub_desc(udev); 1272 goto tr_valid; 1273 1274 tr_valid: 1275 if (buf == NULL) 1276 goto tr_stalled; 1277 if (len == 0) 1278 len = buf[0]; 1279 *pPtr = buf; 1280 *pLength = len; 1281 return (0); /* success */ 1282 1283 tr_stalled: 1284 /* try to get a vendor specific descriptor */ 1285 len = 0; 1286 buf = usb_temp_get_vendor_desc(udev, req, &len); 1287 if (buf != NULL) 1288 goto tr_valid; 1289 *pPtr = NULL; 1290 *pLength = 0; 1291 return (0); /* we ignore failures */ 1292 } 1293 1294 /*------------------------------------------------------------------------* 1295 * usb_temp_setup 1296 * 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. 1300 * 1301 * Returns: 1302 * 0: Success 1303 * Else: Failure 1304 *------------------------------------------------------------------------*/ 1305 usb_error_t 1306 usb_temp_setup(struct usb_device *udev, 1307 const struct usb_temp_device_desc *tdd) 1308 { 1309 struct usb_temp_setup *uts; 1310 void *buf; 1311 usb_error_t error; 1312 uint8_t n; 1313 uint8_t do_unlock; 1314 1315 /* be NULL safe */ 1316 if (tdd == NULL) 1317 return (0); 1318 1319 /* Protect scratch area */ 1320 do_unlock = usbd_ctrl_lock(udev); 1321 1322 uts = udev->scratch.temp_setup; 1323 1324 memset(uts, 0, sizeof(*uts)); 1325 1326 uts->usb_speed = udev->speed; 1327 uts->self_powered = udev->flags.self_powered; 1328 1329 /* first pass */ 1330 1331 usb_make_device_desc(uts, tdd); 1332 1333 if (uts->err) { 1334 /* some error happened */ 1335 goto done; 1336 } 1337 /* sanity check */ 1338 if (uts->size == 0) { 1339 uts->err = USB_ERR_INVAL; 1340 goto done; 1341 } 1342 /* allocate zeroed memory */ 1343 uts->buf = usbd_alloc_config_desc(udev, uts->size); 1344 /* 1345 * Allow malloc() to return NULL regardless of M_WAITOK flag. 1346 * This helps when porting the software to non-FreeBSD 1347 * systems. 1348 */ 1349 if (uts->buf == NULL) { 1350 /* could not allocate memory */ 1351 uts->err = USB_ERR_NOMEM; 1352 goto done; 1353 } 1354 /* second pass */ 1355 1356 uts->size = 0; 1357 1358 usb_make_device_desc(uts, tdd); 1359 1360 /* 1361 * Store a pointer to our descriptors: 1362 */ 1363 udev->usb_template_ptr = uts->buf; 1364 1365 if (uts->err) { 1366 /* some error happened during second pass */ 1367 goto done; 1368 } 1369 /* 1370 * Resolve all endpoint addresses ! 1371 */ 1372 buf = usb_temp_get_device_desc(udev); 1373 uts->err = usb_hw_ep_resolve(udev, buf); 1374 if (uts->err) { 1375 DPRINTFN(0, "Could not resolve endpoints for " 1376 "Device Descriptor, error = %s\n", 1377 usbd_errstr(uts->err)); 1378 goto done; 1379 } 1380 for (n = 0;; n++) { 1381 buf = usb_temp_get_config_desc(udev, NULL, n); 1382 if (buf == NULL) { 1383 break; 1384 } 1385 uts->err = usb_hw_ep_resolve(udev, buf); 1386 if (uts->err) { 1387 DPRINTFN(0, "Could not resolve endpoints for " 1388 "Config Descriptor %u, error = %s\n", n, 1389 usbd_errstr(uts->err)); 1390 goto done; 1391 } 1392 } 1393 done: 1394 error = uts->err; 1395 if (error) 1396 usb_temp_unsetup(udev); 1397 if (do_unlock) 1398 usbd_ctrl_unlock(udev); 1399 return (error); 1400 } 1401 1402 /*------------------------------------------------------------------------* 1403 * usb_temp_unsetup 1404 * 1405 * This function frees any memory associated with the currently 1406 * setup template, if any. 1407 *------------------------------------------------------------------------*/ 1408 void 1409 usb_temp_unsetup(struct usb_device *udev) 1410 { 1411 usbd_free_config_desc(udev, udev->usb_template_ptr); 1412 udev->usb_template_ptr = NULL; 1413 } 1414 1415 static usb_error_t 1416 usb_temp_setup_by_index(struct usb_device *udev, uint16_t index) 1417 { 1418 usb_error_t err; 1419 1420 switch (index) { 1421 case USB_TEMP_MSC: 1422 err = usb_temp_setup(udev, &usb_template_msc); 1423 break; 1424 case USB_TEMP_CDCE: 1425 err = usb_temp_setup(udev, &usb_template_cdce); 1426 break; 1427 case USB_TEMP_MTP: 1428 err = usb_temp_setup(udev, &usb_template_mtp); 1429 break; 1430 case USB_TEMP_MODEM: 1431 err = usb_temp_setup(udev, &usb_template_modem); 1432 break; 1433 case USB_TEMP_AUDIO: 1434 err = usb_temp_setup(udev, &usb_template_audio); 1435 break; 1436 case USB_TEMP_KBD: 1437 err = usb_temp_setup(udev, &usb_template_kbd); 1438 break; 1439 case USB_TEMP_MOUSE: 1440 err = usb_temp_setup(udev, &usb_template_mouse); 1441 break; 1442 case USB_TEMP_PHONE: 1443 err = usb_temp_setup(udev, &usb_template_phone); 1444 break; 1445 case USB_TEMP_SERIALNET: 1446 err = usb_temp_setup(udev, &usb_template_serialnet); 1447 break; 1448 case USB_TEMP_MIDI: 1449 err = usb_temp_setup(udev, &usb_template_midi); 1450 break; 1451 case USB_TEMP_MULTI: 1452 err = usb_temp_setup(udev, &usb_template_multi); 1453 break; 1454 case USB_TEMP_CDCEEM: 1455 err = usb_temp_setup(udev, &usb_template_cdceem); 1456 break; 1457 default: 1458 return (USB_ERR_INVAL); 1459 } 1460 1461 return (err); 1462 } 1463 1464 static void 1465 usb_temp_init(void *arg) 1466 { 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; 1471 } 1472 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); 1475