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 #include <sys/queue.h> 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 32 #define libusb_device_handle libusb20_device 33 34 #include "libusb20.h" 35 #include "libusb20_desc.h" 36 #include "libusb20_int.h" 37 #include "libusb.h" 38 #include "libusb10.h" 39 40 #define N_ALIGN(n) (-((-(n)) & (-8UL))) 41 42 /* USB descriptors */ 43 44 int 45 libusb_get_device_descriptor(libusb_device *dev, 46 struct libusb_device_descriptor *desc) 47 { 48 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 49 struct libusb20_device *pdev; 50 51 if ((dev == NULL) || (desc == NULL)) 52 return (LIBUSB_ERROR_INVALID_PARAM); 53 54 pdev = dev->os_priv; 55 pdesc = libusb20_dev_get_device_desc(pdev); 56 57 desc->bLength = pdesc->bLength; 58 desc->bDescriptorType = pdesc->bDescriptorType; 59 desc->bcdUSB = pdesc->bcdUSB; 60 desc->bDeviceClass = pdesc->bDeviceClass; 61 desc->bDeviceSubClass = pdesc->bDeviceSubClass; 62 desc->bDeviceProtocol = pdesc->bDeviceProtocol; 63 desc->bMaxPacketSize0 = pdesc->bMaxPacketSize0; 64 desc->idVendor = pdesc->idVendor; 65 desc->idProduct = pdesc->idProduct; 66 desc->bcdDevice = pdesc->bcdDevice; 67 desc->iManufacturer = pdesc->iManufacturer; 68 desc->iProduct = pdesc->iProduct; 69 desc->iSerialNumber = pdesc->iSerialNumber; 70 desc->bNumConfigurations = pdesc->bNumConfigurations; 71 72 return (0); 73 } 74 75 int 76 libusb_get_active_config_descriptor(libusb_device *dev, 77 struct libusb_config_descriptor **config) 78 { 79 struct libusb20_device *pdev; 80 uint8_t config_index; 81 82 pdev = dev->os_priv; 83 config_index = libusb20_dev_get_config_index(pdev); 84 85 return (libusb_get_config_descriptor(dev, config_index, config)); 86 } 87 88 int 89 libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, 90 struct libusb_config_descriptor **config) 91 { 92 struct libusb20_device *pdev; 93 struct libusb20_config *pconf; 94 struct libusb20_interface *pinf; 95 struct libusb20_endpoint *pend; 96 struct libusb_config_descriptor *pconfd; 97 struct libusb_interface_descriptor *ifd; 98 struct libusb_endpoint_descriptor *endd; 99 uint8_t *pextra; 100 uint16_t nextra; 101 uint8_t nif; 102 uint8_t nep; 103 uint8_t nalt; 104 uint8_t i; 105 uint8_t j; 106 uint8_t k; 107 108 if (dev == NULL || config == NULL) 109 return (LIBUSB_ERROR_INVALID_PARAM); 110 111 *config = NULL; 112 113 pdev = dev->os_priv; 114 pconf = libusb20_dev_alloc_config(pdev, config_index); 115 116 if (pconf == NULL) 117 return (LIBUSB_ERROR_NOT_FOUND); 118 119 nalt = nif = pconf->num_interface; 120 nep = 0; 121 nextra = N_ALIGN(pconf->extra.len); 122 123 for (i = 0; i < nif; i++) { 124 125 pinf = pconf->interface + i; 126 nextra += N_ALIGN(pinf->extra.len); 127 nep += pinf->num_endpoints; 128 k = pinf->num_endpoints; 129 pend = pinf->endpoints; 130 while (k--) { 131 nextra += N_ALIGN(pend->extra.len); 132 pend++; 133 } 134 135 j = pinf->num_altsetting; 136 nalt += pinf->num_altsetting; 137 pinf = pinf->altsetting; 138 while (j--) { 139 nextra += N_ALIGN(pinf->extra.len); 140 nep += pinf->num_endpoints; 141 k = pinf->num_endpoints; 142 pend = pinf->endpoints; 143 while (k--) { 144 nextra += N_ALIGN(pend->extra.len); 145 pend++; 146 } 147 pinf++; 148 } 149 } 150 151 nextra = nextra + 152 (1 * sizeof(libusb_config_descriptor)) + 153 (nif * sizeof(libusb_interface)) + 154 (nalt * sizeof(libusb_interface_descriptor)) + 155 (nep * sizeof(libusb_endpoint_descriptor)); 156 157 nextra = N_ALIGN(nextra); 158 159 pconfd = malloc(nextra); 160 161 if (pconfd == NULL) { 162 free(pconf); 163 return (LIBUSB_ERROR_NO_MEM); 164 } 165 /* make sure memory is initialised */ 166 memset(pconfd, 0, nextra); 167 168 pconfd->interface = (libusb_interface *) (pconfd + 1); 169 170 ifd = (libusb_interface_descriptor *) (pconfd->interface + nif); 171 endd = (libusb_endpoint_descriptor *) (ifd + nalt); 172 pextra = (uint8_t *)(endd + nep); 173 174 /* fill in config descriptor */ 175 176 pconfd->bLength = pconf->desc.bLength; 177 pconfd->bDescriptorType = pconf->desc.bDescriptorType; 178 pconfd->wTotalLength = pconf->desc.wTotalLength; 179 pconfd->bNumInterfaces = pconf->desc.bNumInterfaces; 180 pconfd->bConfigurationValue = pconf->desc.bConfigurationValue; 181 pconfd->iConfiguration = pconf->desc.iConfiguration; 182 pconfd->bmAttributes = pconf->desc.bmAttributes; 183 pconfd->MaxPower = pconf->desc.bMaxPower; 184 185 if (pconf->extra.len != 0) { 186 pconfd->extra_length = pconf->extra.len; 187 pconfd->extra = pextra; 188 memcpy(pextra, pconf->extra.ptr, pconfd->extra_length); 189 pextra += N_ALIGN(pconfd->extra_length); 190 } 191 /* setup all interface and endpoint pointers */ 192 193 for (i = 0; i < nif; i++) { 194 195 pconfd->interface[i].altsetting = ifd; 196 ifd->endpoint = endd; 197 endd += pconf->interface[i].num_endpoints; 198 ifd++; 199 200 for (j = 0; j < pconf->interface[i].num_altsetting; j++) { 201 ifd->endpoint = endd; 202 endd += pconf->interface[i].altsetting[j].num_endpoints; 203 ifd++; 204 } 205 } 206 207 /* fill in all interface and endpoint data */ 208 209 for (i = 0; i < nif; i++) { 210 pinf = &pconf->interface[i]; 211 pconfd->interface[i].num_altsetting = pinf->num_altsetting + 1; 212 for (j = 0; j < pconfd->interface[i].num_altsetting; j++) { 213 if (j != 0) 214 pinf = &pconf->interface[i].altsetting[j - 1]; 215 ifd = &pconfd->interface[i].altsetting[j]; 216 ifd->bLength = pinf->desc.bLength; 217 ifd->bDescriptorType = pinf->desc.bDescriptorType; 218 ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber; 219 ifd->bAlternateSetting = pinf->desc.bAlternateSetting; 220 ifd->bNumEndpoints = pinf->desc.bNumEndpoints; 221 ifd->bInterfaceClass = pinf->desc.bInterfaceClass; 222 ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass; 223 ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol; 224 ifd->iInterface = pinf->desc.iInterface; 225 if (pinf->extra.len != 0) { 226 ifd->extra_length = pinf->extra.len; 227 ifd->extra = pextra; 228 memcpy(pextra, pinf->extra.ptr, pinf->extra.len); 229 pextra += N_ALIGN(pinf->extra.len); 230 } 231 for (k = 0; k < pinf->num_endpoints; k++) { 232 pend = &pinf->endpoints[k]; 233 endd = &ifd->endpoint[k]; 234 endd->bLength = pend->desc.bLength; 235 endd->bDescriptorType = pend->desc.bDescriptorType; 236 endd->bEndpointAddress = pend->desc.bEndpointAddress; 237 endd->bmAttributes = pend->desc.bmAttributes; 238 endd->wMaxPacketSize = pend->desc.wMaxPacketSize; 239 endd->bInterval = pend->desc.bInterval; 240 endd->bRefresh = pend->desc.bRefresh; 241 endd->bSynchAddress = pend->desc.bSynchAddress; 242 if (pend->extra.len != 0) { 243 endd->extra_length = pend->extra.len; 244 endd->extra = pextra; 245 memcpy(pextra, pend->extra.ptr, pend->extra.len); 246 pextra += N_ALIGN(pend->extra.len); 247 } 248 } 249 } 250 } 251 252 free(pconf); 253 254 *config = pconfd; 255 256 return (0); /* success */ 257 } 258 259 int 260 libusb_get_config_descriptor_by_value(libusb_device *dev, 261 uint8_t bConfigurationValue, struct libusb_config_descriptor **config) 262 { 263 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 264 struct libusb20_device *pdev; 265 int i; 266 int err; 267 268 if (dev == NULL || config == NULL) 269 return (LIBUSB_ERROR_INVALID_PARAM); 270 271 pdev = dev->os_priv; 272 pdesc = libusb20_dev_get_device_desc(pdev); 273 274 for (i = 0; i < pdesc->bNumConfigurations; i++) { 275 err = libusb_get_config_descriptor(dev, i, config); 276 if (err) 277 return (err); 278 279 if ((*config)->bConfigurationValue == bConfigurationValue) 280 return (0); /* success */ 281 282 libusb_free_config_descriptor(*config); 283 } 284 285 *config = NULL; 286 287 return (LIBUSB_ERROR_NOT_FOUND); 288 } 289 290 void 291 libusb_free_config_descriptor(struct libusb_config_descriptor *config) 292 { 293 free(config); 294 } 295 296 int 297 libusb_get_string_descriptor(libusb_device_handle *pdev, 298 uint8_t desc_index, uint16_t langid, unsigned char *data, 299 int length) 300 { 301 if (pdev == NULL || data == NULL || length < 1) 302 return (LIBUSB_ERROR_INVALID_PARAM); 303 304 if (length > 65535) 305 length = 65535; 306 307 /* put some default data into the destination buffer */ 308 data[0] = 0; 309 310 return (libusb_control_transfer(pdev, LIBUSB_ENDPOINT_IN, 311 LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, 312 langid, data, length, 1000)); 313 } 314 315 int 316 libusb_get_string_descriptor_ascii(libusb_device_handle *pdev, 317 uint8_t desc_index, unsigned char *data, int length) 318 { 319 if (pdev == NULL || data == NULL || length < 1) 320 return (LIBUSB_ERROR_INVALID_PARAM); 321 322 if (length > 65535) 323 length = 65535; 324 325 /* put some default data into the destination buffer */ 326 data[0] = 0; 327 328 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, 329 data, length) == 0) 330 return (strlen(data)); 331 332 return (LIBUSB_ERROR_OTHER); 333 } 334 335 int 336 libusb_get_descriptor(libusb_device_handle * devh, uint8_t desc_type, 337 uint8_t desc_index, uint8_t *data, int length) 338 { 339 if (devh == NULL || data == NULL || length < 1) 340 return (LIBUSB_ERROR_INVALID_PARAM); 341 342 if (length > 65535) 343 length = 65535; 344 345 return (libusb_control_transfer(devh, LIBUSB_ENDPOINT_IN, 346 LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, 347 length, 1000)); 348 } 349 350 int 351 libusb_parse_ss_endpoint_comp(const void *buf, int len, 352 struct libusb_ss_endpoint_companion_descriptor **ep_comp) 353 { 354 if (buf == NULL || ep_comp == NULL || len < 1) 355 return (LIBUSB_ERROR_INVALID_PARAM); 356 357 if (len > 65535) 358 len = 65535; 359 360 *ep_comp = NULL; 361 362 while (len != 0) { 363 uint8_t dlen; 364 uint8_t dtype; 365 366 dlen = ((const uint8_t *)buf)[0]; 367 dtype = ((const uint8_t *)buf)[1]; 368 369 if (dlen < 2 || dlen > len) 370 break; 371 372 if (dlen >= LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE && 373 dtype == LIBUSB_DT_SS_ENDPOINT_COMPANION) { 374 struct libusb_ss_endpoint_companion_descriptor *ptr; 375 376 ptr = malloc(sizeof(*ptr)); 377 if (ptr == NULL) 378 return (LIBUSB_ERROR_NO_MEM); 379 380 ptr->bLength = LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE; 381 ptr->bDescriptorType = dtype; 382 ptr->bMaxBurst = ((const uint8_t *)buf)[2]; 383 ptr->bmAttributes = ((const uint8_t *)buf)[3]; 384 ptr->wBytesPerInterval = ((const uint8_t *)buf)[4] | 385 (((const uint8_t *)buf)[5] << 8); 386 387 *ep_comp = ptr; 388 389 return (0); /* success */ 390 } 391 392 buf = ((const uint8_t *)buf) + dlen; 393 len -= dlen; 394 } 395 return (LIBUSB_ERROR_IO); 396 } 397 398 void 399 libusb_free_ss_endpoint_comp(struct libusb_ss_endpoint_companion_descriptor *ep_comp) 400 { 401 if (ep_comp == NULL) 402 return; 403 404 free(ep_comp); 405 } 406 407 int 408 libusb_parse_bos_descriptor(const void *buf, int len, 409 struct libusb_bos_descriptor **bos) 410 { 411 struct libusb_bos_descriptor *ptr; 412 struct libusb_usb_2_0_device_capability_descriptor *dcap_20 = NULL; 413 struct libusb_ss_usb_device_capability_descriptor *ss_cap = NULL; 414 415 if (buf == NULL || bos == NULL || len < 1) 416 return (LIBUSB_ERROR_INVALID_PARAM); 417 418 if (len > 65535) 419 len = 65535; 420 421 *bos = ptr = NULL; 422 423 while (len != 0) { 424 uint8_t dlen; 425 uint8_t dtype; 426 427 dlen = ((const uint8_t *)buf)[0]; 428 dtype = ((const uint8_t *)buf)[1]; 429 430 if (dlen < 2 || dlen > len) 431 break; 432 433 if (dlen >= LIBUSB_DT_BOS_SIZE && 434 dtype == LIBUSB_DT_BOS) { 435 436 ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + 437 sizeof(*ss_cap)); 438 439 if (ptr == NULL) 440 return (LIBUSB_ERROR_NO_MEM); 441 442 *bos = ptr; 443 444 ptr->bLength = LIBUSB_DT_BOS_SIZE; 445 ptr->bDescriptorType = dtype; 446 ptr->wTotalLength = ((const uint8_t *)buf)[2] | 447 (((const uint8_t *)buf)[3] << 8); 448 ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; 449 ptr->usb_2_0_ext_cap = NULL; 450 ptr->ss_usb_cap = NULL; 451 452 dcap_20 = (void *)(ptr + 1); 453 ss_cap = (void *)(dcap_20 + 1); 454 } 455 if (dlen >= 3 && 456 ptr != NULL && 457 dtype == LIBUSB_DT_DEVICE_CAPABILITY) { 458 switch (((const uint8_t *)buf)[2]) { 459 case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: 460 if (ptr->usb_2_0_ext_cap != NULL || dcap_20 == NULL) 461 break; 462 if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) 463 break; 464 465 ptr->usb_2_0_ext_cap = dcap_20; 466 467 dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; 468 dcap_20->bDescriptorType = dtype; 469 dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; 470 dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | 471 (((const uint8_t *)buf)[4] << 8) | 472 (((const uint8_t *)buf)[5] << 16) | 473 (((const uint8_t *)buf)[6] << 24); 474 break; 475 476 case LIBUSB_SS_USB_DEVICE_CAPABILITY: 477 if (ptr->ss_usb_cap != NULL || ss_cap == NULL) 478 break; 479 if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) 480 break; 481 482 ptr->ss_usb_cap = ss_cap; 483 484 ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; 485 ss_cap->bDescriptorType = dtype; 486 ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; 487 ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; 488 ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | 489 (((const uint8_t *)buf)[5] << 8); 490 ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; 491 ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; 492 ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | 493 (((const uint8_t *)buf)[9] << 8); 494 break; 495 496 default: 497 break; 498 } 499 } 500 501 buf = ((const uint8_t *)buf) + dlen; 502 len -= dlen; 503 } 504 if (ptr != NULL) 505 return (0); /* success */ 506 507 return (LIBUSB_ERROR_IO); 508 } 509 510 void 511 libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) 512 { 513 if (bos == NULL) 514 return; 515 516 free(bos); 517 } 518