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(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_parse_bos_descriptor(const void *buf, int len, 414 struct libusb_bos_descriptor **bos) 415 { 416 struct libusb_bos_descriptor *ptr; 417 struct libusb_usb_2_0_device_capability_descriptor *dcap_20 = NULL; 418 struct libusb_ss_usb_device_capability_descriptor *ss_cap = NULL; 419 420 if (buf == NULL || bos == NULL || len < 1) 421 return (LIBUSB_ERROR_INVALID_PARAM); 422 423 if (len > 65535) 424 len = 65535; 425 426 *bos = ptr = NULL; 427 428 while (len != 0) { 429 uint8_t dlen; 430 uint8_t dtype; 431 432 dlen = ((const uint8_t *)buf)[0]; 433 dtype = ((const uint8_t *)buf)[1]; 434 435 if (dlen < 2 || dlen > len) 436 break; 437 438 if (dlen >= LIBUSB_DT_BOS_SIZE && 439 dtype == LIBUSB_DT_BOS) { 440 441 ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + 442 sizeof(*ss_cap)); 443 444 if (ptr == NULL) 445 return (LIBUSB_ERROR_NO_MEM); 446 447 *bos = ptr; 448 449 ptr->bLength = LIBUSB_DT_BOS_SIZE; 450 ptr->bDescriptorType = dtype; 451 ptr->wTotalLength = ((const uint8_t *)buf)[2] | 452 (((const uint8_t *)buf)[3] << 8); 453 ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; 454 ptr->usb_2_0_ext_cap = NULL; 455 ptr->ss_usb_cap = NULL; 456 457 dcap_20 = (void *)(ptr + 1); 458 ss_cap = (void *)(dcap_20 + 1); 459 } 460 if (dlen >= 3 && 461 ptr != NULL && 462 dtype == LIBUSB_DT_DEVICE_CAPABILITY) { 463 switch (((const uint8_t *)buf)[2]) { 464 case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: 465 if (ptr->usb_2_0_ext_cap != NULL || dcap_20 == NULL) 466 break; 467 if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) 468 break; 469 470 ptr->usb_2_0_ext_cap = dcap_20; 471 472 dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; 473 dcap_20->bDescriptorType = dtype; 474 dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; 475 dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | 476 (((const uint8_t *)buf)[4] << 8) | 477 (((const uint8_t *)buf)[5] << 16) | 478 (((const uint8_t *)buf)[6] << 24); 479 break; 480 481 case LIBUSB_SS_USB_DEVICE_CAPABILITY: 482 if (ptr->ss_usb_cap != NULL || ss_cap == NULL) 483 break; 484 if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) 485 break; 486 487 ptr->ss_usb_cap = ss_cap; 488 489 ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; 490 ss_cap->bDescriptorType = dtype; 491 ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; 492 ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; 493 ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | 494 (((const uint8_t *)buf)[5] << 8); 495 ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; 496 ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; 497 ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | 498 (((const uint8_t *)buf)[9] << 8); 499 break; 500 501 default: 502 break; 503 } 504 } 505 506 buf = ((const uint8_t *)buf) + dlen; 507 len -= dlen; 508 } 509 if (ptr != NULL) 510 return (0); /* success */ 511 512 return (LIBUSB_ERROR_IO); 513 } 514 515 void 516 libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) 517 { 518 if (bos == NULL) 519 return; 520 521 free(bos); 522 } 523