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