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_ascii(libusb_device_handle *pdev, 298 uint8_t desc_index, unsigned char *data, int length) 299 { 300 if (pdev == NULL || data == NULL || length < 1) 301 return (LIBUSB_ERROR_INVALID_PARAM); 302 303 if (length > 65535) 304 length = 65535; 305 306 /* put some default data into the destination buffer */ 307 data[0] = 0; 308 309 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, 310 data, length) == 0) 311 return (strlen(data)); 312 313 return (LIBUSB_ERROR_OTHER); 314 } 315 316 int 317 libusb_get_descriptor(libusb_device_handle * devh, uint8_t desc_type, 318 uint8_t desc_index, uint8_t *data, int length) 319 { 320 if (devh == NULL || data == NULL || length < 1) 321 return (LIBUSB_ERROR_INVALID_PARAM); 322 323 if (length > 65535) 324 length = 65535; 325 326 return (libusb_control_transfer(devh, LIBUSB_ENDPOINT_IN, 327 LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, 328 length, 1000)); 329 } 330 331 int 332 libusb_parse_ss_endpoint_comp(const void *buf, int len, 333 struct libusb_ss_endpoint_companion_descriptor **ep_comp) 334 { 335 if (buf == NULL || ep_comp == NULL || len < 1) 336 return (LIBUSB_ERROR_INVALID_PARAM); 337 338 if (len > 65535) 339 len = 65535; 340 341 *ep_comp = NULL; 342 343 while (len != 0) { 344 uint8_t dlen; 345 uint8_t dtype; 346 347 dlen = ((const uint8_t *)buf)[0]; 348 dtype = ((const uint8_t *)buf)[1]; 349 350 if (dlen < 2 || dlen > len) 351 break; 352 353 if (dlen >= LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE && 354 dtype == LIBUSB_DT_SS_ENDPOINT_COMPANION) { 355 struct libusb_ss_endpoint_companion_descriptor *ptr; 356 357 ptr = malloc(sizeof(*ptr)); 358 if (ptr == NULL) 359 return (LIBUSB_ERROR_NO_MEM); 360 361 ptr->bLength = LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE; 362 ptr->bDescriptorType = dtype; 363 ptr->bMaxBurst = ((const uint8_t *)buf)[2]; 364 ptr->bmAttributes = ((const uint8_t *)buf)[3]; 365 ptr->wBytesPerInterval = ((const uint8_t *)buf)[4] | 366 (((const uint8_t *)buf)[5] << 8); 367 368 *ep_comp = ptr; 369 370 return (0); /* success */ 371 } 372 373 buf = ((const uint8_t *)buf) + dlen; 374 len -= dlen; 375 } 376 return (LIBUSB_ERROR_IO); 377 } 378 379 void 380 libusb_free_ss_endpoint_comp(struct libusb_ss_endpoint_companion_descriptor *ep_comp) 381 { 382 if (ep_comp == NULL) 383 return; 384 385 free(ep_comp); 386 } 387 388 int 389 libusb_parse_bos_descriptor(const void *buf, int len, 390 struct libusb_bos_descriptor **bos) 391 { 392 struct libusb_bos_descriptor *ptr; 393 struct libusb_usb_2_0_device_capability_descriptor *dcap_20; 394 struct libusb_ss_usb_device_capability_descriptor *ss_cap; 395 396 if (buf == NULL || bos == NULL || len < 1) 397 return (LIBUSB_ERROR_INVALID_PARAM); 398 399 if (len > 65535) 400 len = 65535; 401 402 *bos = ptr = NULL; 403 404 while (len != 0) { 405 uint8_t dlen; 406 uint8_t dtype; 407 408 dlen = ((const uint8_t *)buf)[0]; 409 dtype = ((const uint8_t *)buf)[1]; 410 411 if (dlen < 2 || dlen > len) 412 break; 413 414 if (dlen >= LIBUSB_DT_BOS_SIZE && 415 dtype == LIBUSB_DT_BOS) { 416 417 ptr = malloc(sizeof(*ptr) + sizeof(*dcap_20) + 418 sizeof(*ss_cap)); 419 420 if (ptr == NULL) 421 return (LIBUSB_ERROR_NO_MEM); 422 423 *bos = ptr; 424 425 ptr->bLength = LIBUSB_DT_BOS_SIZE; 426 ptr->bDescriptorType = dtype; 427 ptr->wTotalLength = ((const uint8_t *)buf)[2] | 428 (((const uint8_t *)buf)[3] << 8); 429 ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; 430 ptr->usb_2_0_ext_cap = NULL; 431 ptr->ss_usb_cap = NULL; 432 433 dcap_20 = (void *)(ptr + 1); 434 ss_cap = (void *)(dcap_20 + 1); 435 } 436 if (dlen >= 3 && 437 ptr != NULL && 438 dtype == LIBUSB_DT_DEVICE_CAPABILITY) { 439 switch (((const uint8_t *)buf)[2]) { 440 case LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY: 441 if (ptr->usb_2_0_ext_cap != NULL) 442 break; 443 if (dlen < LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE) 444 break; 445 446 ptr->usb_2_0_ext_cap = dcap_20; 447 448 dcap_20->bLength = LIBUSB_USB_2_0_EXTENSION_DEVICE_CAPABILITY_SIZE; 449 dcap_20->bDescriptorType = dtype; 450 dcap_20->bDevCapabilityType = ((const uint8_t *)buf)[2]; 451 dcap_20->bmAttributes = ((const uint8_t *)buf)[3] | 452 (((const uint8_t *)buf)[4] << 8) | 453 (((const uint8_t *)buf)[5] << 16) | 454 (((const uint8_t *)buf)[6] << 24); 455 break; 456 457 case LIBUSB_SS_USB_DEVICE_CAPABILITY: 458 if (ptr->ss_usb_cap != NULL) 459 break; 460 if (dlen < LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE) 461 break; 462 463 ptr->ss_usb_cap = ss_cap; 464 465 ss_cap->bLength = LIBUSB_SS_USB_DEVICE_CAPABILITY_SIZE; 466 ss_cap->bDescriptorType = dtype; 467 ss_cap->bDevCapabilityType = ((const uint8_t *)buf)[2]; 468 ss_cap->bmAttributes = ((const uint8_t *)buf)[3]; 469 ss_cap->wSpeedSupported = ((const uint8_t *)buf)[4] | 470 (((const uint8_t *)buf)[5] << 8); 471 ss_cap->bFunctionalitySupport = ((const uint8_t *)buf)[6]; 472 ss_cap->bU1DevExitLat = ((const uint8_t *)buf)[7]; 473 ss_cap->wU2DevExitLat = ((const uint8_t *)buf)[8] | 474 (((const uint8_t *)buf)[9] << 8); 475 break; 476 477 default: 478 break; 479 } 480 } 481 482 buf = ((const uint8_t *)buf) + dlen; 483 len -= dlen; 484 } 485 if (ptr != NULL) 486 return (0); /* success */ 487 488 return (LIBUSB_ERROR_IO); 489 } 490 491 void 492 libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) 493 { 494 if (bos == NULL) 495 return; 496 497 free(bos); 498 } 499