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