1 /* $FreeBSD$ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * 5 * Copyright (c) 2009 Sylvestre Gallon. 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 #ifdef LIBUSB_GLOBAL_INCLUDE_FILE 30 #include LIBUSB_GLOBAL_INCLUDE_FILE 31 #else 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include <sys/queue.h> 37 #endif 38 39 #define libusb_device_handle libusb20_device 40 41 #include "libusb20.h" 42 #include "libusb20_desc.h" 43 #include "libusb20_int.h" 44 #include "libusb.h" 45 #include "libusb10.h" 46 47 #define N_ALIGN(n) (-((-(n)) & (-8UL))) 48 49 /* USB descriptors */ 50 51 int 52 libusb_get_device_descriptor(libusb_device *dev, 53 struct libusb_device_descriptor *desc) 54 { 55 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 56 struct libusb20_device *pdev; 57 58 if ((dev == NULL) || (desc == NULL)) 59 return (LIBUSB_ERROR_INVALID_PARAM); 60 61 pdev = dev->os_priv; 62 pdesc = libusb20_dev_get_device_desc(pdev); 63 64 desc->bLength = pdesc->bLength; 65 desc->bDescriptorType = pdesc->bDescriptorType; 66 desc->bcdUSB = pdesc->bcdUSB; 67 desc->bDeviceClass = pdesc->bDeviceClass; 68 desc->bDeviceSubClass = pdesc->bDeviceSubClass; 69 desc->bDeviceProtocol = pdesc->bDeviceProtocol; 70 desc->bMaxPacketSize0 = pdesc->bMaxPacketSize0; 71 desc->idVendor = pdesc->idVendor; 72 desc->idProduct = pdesc->idProduct; 73 desc->bcdDevice = pdesc->bcdDevice; 74 desc->iManufacturer = pdesc->iManufacturer; 75 desc->iProduct = pdesc->iProduct; 76 desc->iSerialNumber = pdesc->iSerialNumber; 77 desc->bNumConfigurations = pdesc->bNumConfigurations; 78 79 return (0); 80 } 81 82 int 83 libusb_get_active_config_descriptor(libusb_device *dev, 84 struct libusb_config_descriptor **config) 85 { 86 struct libusb20_device *pdev; 87 uint8_t config_index; 88 89 pdev = dev->os_priv; 90 config_index = libusb20_dev_get_config_index(pdev); 91 92 return (libusb_get_config_descriptor(dev, config_index, config)); 93 } 94 95 int 96 libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, 97 struct libusb_config_descriptor **config) 98 { 99 struct libusb20_device *pdev; 100 struct libusb20_config *pconf; 101 struct libusb20_interface *pinf; 102 struct libusb20_endpoint *pend; 103 struct libusb_config_descriptor *pconfd; 104 struct libusb_interface_descriptor *ifd; 105 struct libusb_endpoint_descriptor *endd; 106 uint8_t *pextra; 107 uint16_t nextra; 108 uint8_t nif; 109 uint8_t nep; 110 uint8_t nalt; 111 uint8_t i; 112 uint8_t j; 113 uint8_t k; 114 115 if (dev == NULL || config == NULL) 116 return (LIBUSB_ERROR_INVALID_PARAM); 117 118 *config = NULL; 119 120 pdev = dev->os_priv; 121 pconf = libusb20_dev_alloc_config(pdev, config_index); 122 123 if (pconf == NULL) 124 return (LIBUSB_ERROR_NOT_FOUND); 125 126 nalt = nif = pconf->num_interface; 127 nep = 0; 128 nextra = N_ALIGN(pconf->extra.len); 129 130 for (i = 0; i < nif; i++) { 131 132 pinf = pconf->interface + i; 133 nextra += N_ALIGN(pinf->extra.len); 134 nep += pinf->num_endpoints; 135 k = pinf->num_endpoints; 136 pend = pinf->endpoints; 137 while (k--) { 138 nextra += N_ALIGN(pend->extra.len); 139 pend++; 140 } 141 142 j = pinf->num_altsetting; 143 nalt += pinf->num_altsetting; 144 pinf = pinf->altsetting; 145 while (j--) { 146 nextra += N_ALIGN(pinf->extra.len); 147 nep += pinf->num_endpoints; 148 k = pinf->num_endpoints; 149 pend = pinf->endpoints; 150 while (k--) { 151 nextra += N_ALIGN(pend->extra.len); 152 pend++; 153 } 154 pinf++; 155 } 156 } 157 158 nextra = nextra + 159 (1 * sizeof(libusb_config_descriptor)) + 160 (nif * sizeof(libusb_interface)) + 161 (nalt * sizeof(libusb_interface_descriptor)) + 162 (nep * sizeof(libusb_endpoint_descriptor)); 163 164 nextra = N_ALIGN(nextra); 165 166 pconfd = malloc(nextra); 167 168 if (pconfd == NULL) { 169 free(pconf); 170 return (LIBUSB_ERROR_NO_MEM); 171 } 172 /* make sure memory is initialised */ 173 memset(pconfd, 0, nextra); 174 175 pconfd->interface = (libusb_interface *) (pconfd + 1); 176 177 ifd = (libusb_interface_descriptor *) (pconfd->interface + nif); 178 endd = (libusb_endpoint_descriptor *) (ifd + nalt); 179 pextra = (uint8_t *)(endd + nep); 180 181 /* fill in config descriptor */ 182 183 pconfd->bLength = pconf->desc.bLength; 184 pconfd->bDescriptorType = pconf->desc.bDescriptorType; 185 pconfd->wTotalLength = pconf->desc.wTotalLength; 186 pconfd->bNumInterfaces = pconf->desc.bNumInterfaces; 187 pconfd->bConfigurationValue = pconf->desc.bConfigurationValue; 188 pconfd->iConfiguration = pconf->desc.iConfiguration; 189 pconfd->bmAttributes = pconf->desc.bmAttributes; 190 pconfd->MaxPower = pconf->desc.bMaxPower; 191 192 if (pconf->extra.len != 0) { 193 pconfd->extra_length = pconf->extra.len; 194 pconfd->extra = pextra; 195 memcpy(pextra, pconf->extra.ptr, pconfd->extra_length); 196 pextra += N_ALIGN(pconfd->extra_length); 197 } 198 /* setup all interface and endpoint pointers */ 199 200 for (i = 0; i < nif; i++) { 201 202 pconfd->interface[i].altsetting = ifd; 203 ifd->endpoint = endd; 204 endd += pconf->interface[i].num_endpoints; 205 ifd++; 206 207 for (j = 0; j < pconf->interface[i].num_altsetting; j++) { 208 ifd->endpoint = endd; 209 endd += pconf->interface[i].altsetting[j].num_endpoints; 210 ifd++; 211 } 212 } 213 214 /* fill in all interface and endpoint data */ 215 216 for (i = 0; i < nif; i++) { 217 pinf = &pconf->interface[i]; 218 pconfd->interface[i].num_altsetting = pinf->num_altsetting + 1; 219 for (j = 0; j < pconfd->interface[i].num_altsetting; j++) { 220 if (j != 0) 221 pinf = &pconf->interface[i].altsetting[j - 1]; 222 ifd = &pconfd->interface[i].altsetting[j]; 223 ifd->bLength = pinf->desc.bLength; 224 ifd->bDescriptorType = pinf->desc.bDescriptorType; 225 ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber; 226 ifd->bAlternateSetting = pinf->desc.bAlternateSetting; 227 ifd->bNumEndpoints = pinf->desc.bNumEndpoints; 228 ifd->bInterfaceClass = pinf->desc.bInterfaceClass; 229 ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass; 230 ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol; 231 ifd->iInterface = pinf->desc.iInterface; 232 if (pinf->extra.len != 0) { 233 ifd->extra_length = pinf->extra.len; 234 ifd->extra = pextra; 235 memcpy(pextra, pinf->extra.ptr, pinf->extra.len); 236 pextra += N_ALIGN(pinf->extra.len); 237 } 238 for (k = 0; k < pinf->num_endpoints; k++) { 239 pend = &pinf->endpoints[k]; 240 endd = &ifd->endpoint[k]; 241 endd->bLength = pend->desc.bLength; 242 endd->bDescriptorType = pend->desc.bDescriptorType; 243 endd->bEndpointAddress = pend->desc.bEndpointAddress; 244 endd->bmAttributes = pend->desc.bmAttributes; 245 endd->wMaxPacketSize = pend->desc.wMaxPacketSize; 246 endd->bInterval = pend->desc.bInterval; 247 endd->bRefresh = pend->desc.bRefresh; 248 endd->bSynchAddress = pend->desc.bSynchAddress; 249 if (pend->extra.len != 0) { 250 endd->extra_length = pend->extra.len; 251 endd->extra = pextra; 252 memcpy(pextra, pend->extra.ptr, pend->extra.len); 253 pextra += N_ALIGN(pend->extra.len); 254 } 255 } 256 } 257 } 258 259 free(pconf); 260 261 *config = pconfd; 262 263 return (0); /* success */ 264 } 265 266 int 267 libusb_get_config_descriptor_by_value(libusb_device *dev, 268 uint8_t bConfigurationValue, struct libusb_config_descriptor **config) 269 { 270 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 271 struct libusb20_device *pdev; 272 int i; 273 int err; 274 275 if (dev == NULL || config == NULL) 276 return (LIBUSB_ERROR_INVALID_PARAM); 277 278 pdev = dev->os_priv; 279 pdesc = libusb20_dev_get_device_desc(pdev); 280 281 for (i = 0; i < pdesc->bNumConfigurations; i++) { 282 err = libusb_get_config_descriptor(dev, i, config); 283 if (err) 284 return (err); 285 286 if ((*config)->bConfigurationValue == bConfigurationValue) 287 return (0); /* success */ 288 289 libusb_free_config_descriptor(*config); 290 } 291 292 *config = NULL; 293 294 return (LIBUSB_ERROR_NOT_FOUND); 295 } 296 297 void 298 libusb_free_config_descriptor(struct libusb_config_descriptor *config) 299 { 300 free(config); 301 } 302 303 int 304 libusb_get_string_descriptor(libusb_device_handle *pdev, 305 uint8_t desc_index, uint16_t langid, unsigned char *data, 306 int length) 307 { 308 if (pdev == NULL || data == NULL || length < 1) 309 return (LIBUSB_ERROR_INVALID_PARAM); 310 311 if (length > 65535) 312 length = 65535; 313 314 /* put some default data into the destination buffer */ 315 data[0] = 0; 316 317 return (libusb_control_transfer(pdev, LIBUSB_ENDPOINT_IN, 318 LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, 319 langid, data, length, 1000)); 320 } 321 322 int 323 libusb_get_string_descriptor_ascii(libusb_device_handle *pdev, 324 uint8_t desc_index, unsigned char *data, int length) 325 { 326 if (pdev == NULL || data == NULL || length < 1) 327 return (LIBUSB_ERROR_INVALID_PARAM); 328 329 if (length > 65535) 330 length = 65535; 331 332 /* put some default data into the destination buffer */ 333 data[0] = 0; 334 335 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, 336 data, length) == 0) 337 return (strlen((char *)data)); 338 339 return (LIBUSB_ERROR_OTHER); 340 } 341 342 int 343 libusb_get_descriptor(libusb_device_handle * devh, uint8_t desc_type, 344 uint8_t desc_index, uint8_t *data, int length) 345 { 346 if (devh == NULL || data == NULL || length < 1) 347 return (LIBUSB_ERROR_INVALID_PARAM); 348 349 if (length > 65535) 350 length = 65535; 351 352 return (libusb_control_transfer(devh, LIBUSB_ENDPOINT_IN, 353 LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, 354 length, 1000)); 355 } 356 357 int 358 libusb_parse_ss_endpoint_comp(const void *buf, int len, 359 struct libusb_ss_endpoint_companion_descriptor **ep_comp) 360 { 361 if (buf == NULL || ep_comp == NULL || len < 1) 362 return (LIBUSB_ERROR_INVALID_PARAM); 363 364 if (len > 65535) 365 len = 65535; 366 367 *ep_comp = NULL; 368 369 while (len != 0) { 370 uint8_t dlen; 371 uint8_t dtype; 372 373 dlen = ((const uint8_t *)buf)[0]; 374 dtype = ((const uint8_t *)buf)[1]; 375 376 if (dlen < 2 || dlen > len) 377 break; 378 379 if (dlen >= LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE && 380 dtype == LIBUSB_DT_SS_ENDPOINT_COMPANION) { 381 struct libusb_ss_endpoint_companion_descriptor *ptr; 382 383 ptr = malloc(sizeof(*ptr)); 384 if (ptr == NULL) 385 return (LIBUSB_ERROR_NO_MEM); 386 387 ptr->bLength = LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE; 388 ptr->bDescriptorType = dtype; 389 ptr->bMaxBurst = ((const uint8_t *)buf)[2]; 390 ptr->bmAttributes = ((const uint8_t *)buf)[3]; 391 ptr->wBytesPerInterval = ((const uint8_t *)buf)[4] | 392 (((const uint8_t *)buf)[5] << 8); 393 394 *ep_comp = ptr; 395 396 return (0); /* success */ 397 } 398 399 buf = ((const uint8_t *)buf) + dlen; 400 len -= dlen; 401 } 402 return (LIBUSB_ERROR_IO); 403 } 404 405 void 406 libusb_free_ss_endpoint_comp(struct libusb_ss_endpoint_companion_descriptor *ep_comp) 407 { 408 if (ep_comp == NULL) 409 return; 410 411 free(ep_comp); 412 } 413 414 int 415 libusb_get_ss_endpoint_companion_descriptor(struct libusb_context *ctx, 416 const struct libusb_endpoint_descriptor *endpoint, 417 struct libusb_ss_endpoint_companion_descriptor **ep_comp) 418 { 419 if (endpoint == NULL) 420 return (LIBUSB_ERROR_INVALID_PARAM); 421 return (libusb_parse_ss_endpoint_comp(endpoint->extra, endpoint->extra_length, ep_comp)); 422 } 423 424 void 425 libusb_free_ss_endpoint_companion_descriptor(struct libusb_ss_endpoint_companion_descriptor *ep_comp) 426 { 427 428 libusb_free_ss_endpoint_comp(ep_comp); 429 } 430 431 int 432 libusb_parse_bos_descriptor(const void *buf, int len, 433 struct libusb_bos_descriptor **bos) 434 { 435 struct libusb_bos_descriptor *ptr; 436 struct libusb_usb_2_0_device_capability_descriptor *dcap_20 = NULL; 437 struct libusb_ss_usb_device_capability_descriptor *ss_cap = NULL; 438 uint8_t index = 0; 439 440 if (buf == NULL || bos == NULL || len < 1) 441 return (LIBUSB_ERROR_INVALID_PARAM); 442 443 if (len > 65535) 444 len = 65535; 445 446 *bos = ptr = NULL; 447 448 while (len != 0) { 449 uint8_t dlen; 450 uint8_t dtype; 451 452 dlen = ((const uint8_t *)buf)[0]; 453 dtype = ((const uint8_t *)buf)[1]; 454 455 if (dlen < 2 || dlen > len) 456 break; 457 458 if (dlen >= LIBUSB_DT_BOS_SIZE && 459 dtype == LIBUSB_DT_BOS && 460 ptr == NULL) { 461 462 ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + 463 sizeof(*ss_cap)); 464 465 if (ptr == NULL) 466 return (LIBUSB_ERROR_NO_MEM); 467 468 *bos = ptr; 469 470 ptr->bLength = LIBUSB_DT_BOS_SIZE; 471 ptr->bDescriptorType = dtype; 472 ptr->wTotalLength = ((const uint8_t *)buf)[2] | 473 (((const uint8_t *)buf)[3] << 8); 474 ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; 475 ptr->usb_2_0_ext_cap = NULL; 476 ptr->ss_usb_cap = NULL; 477 ptr->dev_capability = calloc(ptr->bNumDeviceCapabilities, sizeof(void *)); 478 if (ptr->dev_capability == NULL) { 479 free(ptr); 480 return (LIBUSB_ERROR_NO_MEM); 481 } 482 483 dcap_20 = (void *)(ptr + 1); 484 ss_cap = (void *)(dcap_20 + 1); 485 } 486 if (dlen >= 3 && 487 ptr != NULL && 488 dtype == LIBUSB_DT_DEVICE_CAPABILITY) { 489 if (index != ptr->bNumDeviceCapabilities) { 490 ptr->dev_capability[index] = malloc(dlen); 491 if (ptr->dev_capability[index] == NULL) { 492 libusb_free_bos_descriptor(ptr); 493 return LIBUSB_ERROR_NO_MEM; 494 } 495 memcpy(ptr->dev_capability[index], buf, dlen); 496 index++; 497 } 498 switch (((const uint8_t *)buf)[2]) { 499 case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: 500 if (ptr->usb_2_0_ext_cap != NULL || dcap_20 == NULL) 501 break; 502 if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) 503 break; 504 505 ptr->usb_2_0_ext_cap = dcap_20; 506 507 dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; 508 dcap_20->bDescriptorType = dtype; 509 dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; 510 dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | 511 (((const uint8_t *)buf)[4] << 8) | 512 (((const uint8_t *)buf)[5] << 16) | 513 (((const uint8_t *)buf)[6] << 24); 514 break; 515 516 case LIBUSB_SS_USB_DEVICE_CAPABILITY: 517 if (ptr->ss_usb_cap != NULL || ss_cap == NULL) 518 break; 519 if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) 520 break; 521 522 ptr->ss_usb_cap = ss_cap; 523 524 ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; 525 ss_cap->bDescriptorType = dtype; 526 ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; 527 ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; 528 ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | 529 (((const uint8_t *)buf)[5] << 8); 530 ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; 531 ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; 532 ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | 533 (((const uint8_t *)buf)[9] << 8); 534 break; 535 536 default: 537 break; 538 } 539 } 540 541 buf = ((const uint8_t *)buf) + dlen; 542 len -= dlen; 543 } 544 545 if (ptr != NULL) { 546 ptr->bNumDeviceCapabilities = index; 547 return (0); /* success */ 548 } 549 550 return (LIBUSB_ERROR_IO); 551 } 552 553 void 554 libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) 555 { 556 uint8_t i; 557 558 if (bos == NULL) 559 return; 560 561 for (i = 0; i != bos->bNumDeviceCapabilities; i++) 562 free(bos->dev_capability[i]); 563 free(bos->dev_capability); 564 free(bos); 565 } 566 567 int 568 libusb_get_bos_descriptor(libusb_device_handle *handle, 569 struct libusb_bos_descriptor **bos) 570 { 571 uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0}; 572 uint16_t wTotalLength; 573 uint8_t *bos_data; 574 int err; 575 576 err = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, 577 bos_header, sizeof(bos_header)); 578 if (err < 0) 579 return (err); 580 581 wTotalLength = bos_header[2] | (bos_header[3] << 8); 582 if (wTotalLength < LIBUSB_DT_BOS_SIZE) 583 return (LIBUSB_ERROR_INVALID_PARAM); 584 585 bos_data = calloc(wTotalLength, 1); 586 if (bos_data == NULL) 587 return (LIBUSB_ERROR_NO_MEM); 588 589 err = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, 590 bos_data, wTotalLength); 591 if (err < 0) 592 goto done; 593 594 /* avoid descriptor length mismatches */ 595 bos_data[2] = (wTotalLength & 0xFF); 596 bos_data[3] = (wTotalLength >> 8); 597 598 err = libusb_parse_bos_descriptor(bos_data, wTotalLength, bos); 599 done: 600 free(bos_data); 601 return (err); 602 } 603 604 int 605 libusb_get_usb_2_0_extension_descriptor(struct libusb_context *ctx, 606 struct libusb_bos_dev_capability_descriptor *dev_cap, 607 struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) 608 { 609 struct libusb_usb_2_0_extension_descriptor *desc; 610 611 if (dev_cap == NULL || usb_2_0_extension == NULL || 612 dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) 613 return (LIBUSB_ERROR_INVALID_PARAM); 614 if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) 615 return (LIBUSB_ERROR_IO); 616 617 desc = malloc(sizeof(*desc)); 618 if (desc == NULL) 619 return (LIBUSB_ERROR_NO_MEM); 620 621 desc->bLength = LIBUSB_BT_USB_2_0_EXTENSION_SIZE; 622 desc->bDescriptorType = dev_cap->bDescriptorType; 623 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 624 desc->bmAttributes = 625 (dev_cap->dev_capability_data[0]) | 626 (dev_cap->dev_capability_data[1] << 8) | 627 (dev_cap->dev_capability_data[2] << 16) | 628 (dev_cap->dev_capability_data[3] << 24); 629 630 *usb_2_0_extension = desc; 631 return (0); 632 } 633 634 void 635 libusb_free_usb_2_0_extension_descriptor( 636 struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) 637 { 638 639 free(usb_2_0_extension); 640 } 641 642 int 643 libusb_get_ss_usb_device_capability_descriptor(struct libusb_context *ctx, 644 struct libusb_bos_dev_capability_descriptor *dev_cap, 645 struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_capability) 646 { 647 struct libusb_ss_usb_device_capability_descriptor *desc; 648 649 if (dev_cap == NULL || ss_usb_device_capability == NULL || 650 dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) 651 return (LIBUSB_ERROR_INVALID_PARAM); 652 if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) 653 return (LIBUSB_ERROR_IO); 654 655 desc = malloc(sizeof(*desc)); 656 if (desc == NULL) 657 return (LIBUSB_ERROR_NO_MEM); 658 659 desc->bLength = LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE; 660 desc->bDescriptorType = dev_cap->bDescriptorType; 661 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 662 desc->bmAttributes = dev_cap->dev_capability_data[0]; 663 desc->wSpeedSupported = dev_cap->dev_capability_data[1] | 664 (dev_cap->dev_capability_data[2] << 8); 665 desc->bFunctionalitySupport = dev_cap->dev_capability_data[3]; 666 desc->bU1DevExitLat = dev_cap->dev_capability_data[4]; 667 desc->wU2DevExitLat = dev_cap->dev_capability_data[5] | 668 (dev_cap->dev_capability_data[6] << 8); 669 670 *ss_usb_device_capability = desc; 671 return (0); 672 } 673 674 void 675 libusb_free_ss_usb_device_capability_descriptor( 676 struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability) 677 { 678 679 free(ss_usb_device_capability); 680 } 681 682 int 683 libusb_get_container_id_descriptor(struct libusb_context *ctx, 684 struct libusb_bos_dev_capability_descriptor *dev_cap, 685 struct libusb_container_id_descriptor **container_id) 686 { 687 struct libusb_container_id_descriptor *desc; 688 689 if (dev_cap == NULL || container_id == NULL || 690 dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) 691 return (LIBUSB_ERROR_INVALID_PARAM); 692 if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) 693 return (LIBUSB_ERROR_IO); 694 695 desc = malloc(sizeof(*desc)); 696 if (desc == NULL) 697 return (LIBUSB_ERROR_NO_MEM); 698 699 desc->bLength = LIBUSB_BT_CONTAINER_ID_SIZE; 700 desc->bDescriptorType = dev_cap->bDescriptorType; 701 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 702 desc->bReserved = dev_cap->dev_capability_data[0]; 703 memcpy(desc->ContainerID, dev_cap->dev_capability_data + 1, 704 sizeof(desc->ContainerID)); 705 706 *container_id = desc; 707 return (0); 708 } 709 710 void 711 libusb_free_container_id_descriptor( 712 struct libusb_container_id_descriptor *container_id) 713 { 714 715 free(container_id); 716 } 717