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 437 if (buf == NULL || bos == NULL || len < 1) 438 return (LIBUSB_ERROR_INVALID_PARAM); 439 440 if (len > 65535) 441 len = 65535; 442 443 *bos = ptr = NULL; 444 445 while (len != 0) { 446 uint8_t dlen; 447 uint8_t dtype; 448 449 dlen = ((const uint8_t *)buf)[0]; 450 dtype = ((const uint8_t *)buf)[1]; 451 452 if (dlen < 2 || dlen > len) 453 break; 454 455 if (dlen >= LIBUSB_DT_BOS_SIZE && 456 dtype == LIBUSB_DT_BOS) { 457 458 ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + 459 sizeof(*ss_cap)); 460 461 if (ptr == NULL) 462 return (LIBUSB_ERROR_NO_MEM); 463 464 *bos = ptr; 465 466 ptr->bLength = LIBUSB_DT_BOS_SIZE; 467 ptr->bDescriptorType = dtype; 468 ptr->wTotalLength = ((const uint8_t *)buf)[2] | 469 (((const uint8_t *)buf)[3] << 8); 470 ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; 471 ptr->usb_2_0_ext_cap = NULL; 472 ptr->ss_usb_cap = NULL; 473 474 dcap_20 = (void *)(ptr + 1); 475 ss_cap = (void *)(dcap_20 + 1); 476 } 477 if (dlen >= 3 && 478 ptr != NULL && 479 dtype == LIBUSB_DT_DEVICE_CAPABILITY) { 480 switch (((const uint8_t *)buf)[2]) { 481 case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: 482 if (ptr->usb_2_0_ext_cap != NULL || dcap_20 == NULL) 483 break; 484 if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) 485 break; 486 487 ptr->usb_2_0_ext_cap = dcap_20; 488 489 dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; 490 dcap_20->bDescriptorType = dtype; 491 dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; 492 dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | 493 (((const uint8_t *)buf)[4] << 8) | 494 (((const uint8_t *)buf)[5] << 16) | 495 (((const uint8_t *)buf)[6] << 24); 496 break; 497 498 case LIBUSB_SS_USB_DEVICE_CAPABILITY: 499 if (ptr->ss_usb_cap != NULL || ss_cap == NULL) 500 break; 501 if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) 502 break; 503 504 ptr->ss_usb_cap = ss_cap; 505 506 ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; 507 ss_cap->bDescriptorType = dtype; 508 ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; 509 ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; 510 ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | 511 (((const uint8_t *)buf)[5] << 8); 512 ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; 513 ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; 514 ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | 515 (((const uint8_t *)buf)[9] << 8); 516 break; 517 518 default: 519 break; 520 } 521 } 522 523 buf = ((const uint8_t *)buf) + dlen; 524 len -= dlen; 525 } 526 if (ptr != NULL) 527 return (0); /* success */ 528 529 return (LIBUSB_ERROR_IO); 530 } 531 532 void 533 libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) 534 { 535 if (bos == NULL) 536 return; 537 538 free(bos); 539 } 540 541 int 542 libusb_get_bos_descriptor(libusb_device_handle *handle, 543 struct libusb_bos_descriptor **bos) 544 { 545 uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0}; 546 uint16_t wTotalLength; 547 uint8_t *bos_data; 548 int err; 549 550 err = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, 551 bos_header, sizeof(bos_header)); 552 if (err < 0) 553 return (err); 554 555 wTotalLength = bos_header[2] | (bos_header[3] << 8); 556 if (wTotalLength < LIBUSB_DT_BOS_SIZE) 557 return (LIBUSB_ERROR_INVALID_PARAM); 558 559 bos_data = calloc(wTotalLength, 1); 560 if (bos_data == NULL) 561 return (LIBUSB_ERROR_NO_MEM); 562 563 err = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, 564 bos_data, wTotalLength); 565 if (err < 0) 566 goto done; 567 568 /* avoid descriptor length mismatches */ 569 bos_data[2] = (wTotalLength & 0xFF); 570 bos_data[3] = (wTotalLength >> 8); 571 572 err = libusb_parse_bos_descriptor(bos_data, wTotalLength, bos); 573 done: 574 free(bos_data); 575 return (err); 576 } 577 578 int 579 libusb_get_usb_2_0_extension_descriptor(struct libusb_context *ctx, 580 struct libusb_bos_dev_capability_descriptor *dev_cap, 581 struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) 582 { 583 struct libusb_usb_2_0_extension_descriptor *desc; 584 585 if (dev_cap == NULL || usb_2_0_extension == NULL || 586 dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) 587 return (LIBUSB_ERROR_INVALID_PARAM); 588 if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) 589 return (LIBUSB_ERROR_IO); 590 591 desc = malloc(sizeof(*desc)); 592 if (desc == NULL) 593 return (LIBUSB_ERROR_NO_MEM); 594 595 desc->bLength = LIBUSB_BT_USB_2_0_EXTENSION_SIZE; 596 desc->bDescriptorType = dev_cap->bDescriptorType; 597 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 598 desc->bmAttributes = 599 (dev_cap->dev_capability_data[0]) | 600 (dev_cap->dev_capability_data[1] << 8) | 601 (dev_cap->dev_capability_data[2] << 16) | 602 (dev_cap->dev_capability_data[3] << 24); 603 604 *usb_2_0_extension = desc; 605 return (0); 606 } 607 608 void 609 libusb_free_usb_2_0_extension_descriptor( 610 struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) 611 { 612 613 free(usb_2_0_extension); 614 } 615 616 int 617 libusb_get_ss_usb_device_capability_descriptor(struct libusb_context *ctx, 618 struct libusb_bos_dev_capability_descriptor *dev_cap, 619 struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_capability) 620 { 621 struct libusb_ss_usb_device_capability_descriptor *desc; 622 623 if (dev_cap == NULL || ss_usb_device_capability == NULL || 624 dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) 625 return (LIBUSB_ERROR_INVALID_PARAM); 626 if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) 627 return (LIBUSB_ERROR_IO); 628 629 desc = malloc(sizeof(*desc)); 630 if (desc == NULL) 631 return (LIBUSB_ERROR_NO_MEM); 632 633 desc->bLength = LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE; 634 desc->bDescriptorType = dev_cap->bDescriptorType; 635 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 636 desc->bmAttributes = dev_cap->dev_capability_data[0]; 637 desc->wSpeedSupported = dev_cap->dev_capability_data[1] | 638 (dev_cap->dev_capability_data[2] << 8); 639 desc->bFunctionalitySupport = dev_cap->dev_capability_data[3]; 640 desc->bU1DevExitLat = dev_cap->dev_capability_data[4]; 641 desc->wU2DevExitLat = dev_cap->dev_capability_data[5] | 642 (dev_cap->dev_capability_data[6] << 8); 643 644 *ss_usb_device_capability = desc; 645 return (0); 646 } 647 648 void 649 libusb_free_ss_usb_device_capability_descriptor( 650 struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability) 651 { 652 653 free(ss_usb_device_capability); 654 } 655 656 int 657 libusb_get_container_id_descriptor(struct libusb_context *ctx, 658 struct libusb_bos_dev_capability_descriptor *dev_cap, 659 struct libusb_container_id_descriptor **container_id) 660 { 661 struct libusb_container_id_descriptor *desc; 662 663 if (dev_cap == NULL || container_id == NULL || 664 dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) 665 return (LIBUSB_ERROR_INVALID_PARAM); 666 if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) 667 return (LIBUSB_ERROR_IO); 668 669 desc = malloc(sizeof(*desc)); 670 if (desc == NULL) 671 return (LIBUSB_ERROR_NO_MEM); 672 673 desc->bLength = LIBUSB_BT_CONTAINER_ID_SIZE; 674 desc->bDescriptorType = dev_cap->bDescriptorType; 675 desc->bDevCapabilityType = dev_cap->bDevCapabilityType; 676 desc->bReserved = dev_cap->dev_capability_data[0]; 677 memcpy(desc->ContainerID, dev_cap->dev_capability_data + 1, 678 sizeof(desc->ContainerID)); 679 680 *container_id = desc; 681 return (0); 682 } 683 684 void 685 libusb_free_container_id_descriptor( 686 struct libusb_container_id_descriptor *container_id) 687 { 688 689 free(container_id); 690 } 691