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->bNumDeviceCaps = ((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->bNumDeviceCaps, 477 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->bNumDeviceCaps) { 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->bNumDeviceCaps = 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->bNumDeviceCaps; 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 free(container_id); 715 } 716 717 int 718 libusb_get_platform_descriptor(libusb_context *ctx, 719 struct libusb_bos_dev_capability_descriptor *bos_cap, 720 struct libusb_platform_descriptor **pd) 721 { 722 struct libusb_platform_descriptor *desc; 723 uint8_t *cap_data; 724 725 if (bos_cap == NULL || 726 bos_cap->bDescriptorType != LIBUSB_BT_PLATFORM_DESCRIPTOR || 727 pd == NULL) 728 return (LIBUSB_ERROR_INVALID_PARAM); 729 730 if (bos_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) 731 return (LIBUSB_ERROR_IO); 732 733 cap_data = bos_cap->dev_capability_data; 734 desc = calloc(1, bos_cap->bLength); 735 if (desc == NULL) 736 return (LIBUSB_ERROR_NO_MEM); 737 738 desc->bLength = bos_cap->bLength; 739 desc->bDescriptorType = LIBUSB_BT_PLATFORM_DESCRIPTOR; 740 desc->bDevCapabilityType = bos_cap->bDevCapabilityType; 741 desc->bReserved = cap_data[0]; 742 memcpy(desc->PlatformCapabilityUUID, cap_data + 1, 743 sizeof(desc->PlatformCapabilityUUID)); 744 745 /* 746 * UUID (16 bytes) + bReserved 747 */ 748 cap_data += sizeof(desc->PlatformCapabilityUUID) + 1; 749 /* 750 * UUID (16 bytes) + bReserved + bLength + bDescriptortype + 751 * bDevCapabilitytype 752 */ 753 memcpy(desc->CapabilityData, cap_data, 754 bos_cap->bLength - (sizeof(desc->PlatformCapabilityUUID) + 4)); 755 *pd = desc; 756 757 return (LIBUSB_SUCCESS); 758 } 759 760 void 761 libusb_free_platform_descriptor( 762 struct libusb_platform_descriptor *platform_descriptor) 763 { 764 free(platform_descriptor); 765 } 766