1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008-2009 Hans Petter Selasky. 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 <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <poll.h> 31 #include <ctype.h> 32 #include <sys/queue.h> 33 34 #include "libusb20.h" 35 #include "libusb20_desc.h" 36 #include "libusb20_int.h" 37 38 static int 39 dummy_int(void) 40 { 41 return (LIBUSB20_ERROR_NOT_SUPPORTED); 42 } 43 44 static void 45 dummy_void(void) 46 { 47 return; 48 } 49 50 static void 51 dummy_callback(struct libusb20_transfer *xfer) 52 { 53 ; /* style fix */ 54 switch (libusb20_tr_get_status(xfer)) { 55 case LIBUSB20_TRANSFER_START: 56 libusb20_tr_submit(xfer); 57 break; 58 default: 59 /* complete or error */ 60 break; 61 } 62 return; 63 } 64 65 #define dummy_get_config_desc_full (void *)dummy_int 66 #define dummy_get_config_index (void *)dummy_int 67 #define dummy_set_config_index (void *)dummy_int 68 #define dummy_set_alt_index (void *)dummy_int 69 #define dummy_reset_device (void *)dummy_int 70 #define dummy_set_power_mode (void *)dummy_int 71 #define dummy_get_power_mode (void *)dummy_int 72 #define dummy_kernel_driver_active (void *)dummy_int 73 #define dummy_detach_kernel_driver (void *)dummy_int 74 #define dummy_do_request_sync (void *)dummy_int 75 #define dummy_tr_open (void *)dummy_int 76 #define dummy_tr_close (void *)dummy_int 77 #define dummy_tr_clear_stall_sync (void *)dummy_int 78 #define dummy_process (void *)dummy_int 79 #define dummy_dev_info (void *)dummy_int 80 #define dummy_dev_get_iface_driver (void *)dummy_int 81 82 #define dummy_tr_submit (void *)dummy_void 83 #define dummy_tr_cancel_async (void *)dummy_void 84 85 static const struct libusb20_device_methods libusb20_dummy_methods = { 86 LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 87 }; 88 89 void 90 libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 91 { 92 ; /* style fix */ 93 94 repeat: 95 96 if (!xfer->is_pending) { 97 xfer->status = LIBUSB20_TRANSFER_START; 98 } else { 99 xfer->is_pending = 0; 100 } 101 102 xfer->callback(xfer); 103 104 if (xfer->is_restart) { 105 xfer->is_restart = 0; 106 goto repeat; 107 } 108 if (xfer->is_draining && 109 (!xfer->is_pending)) { 110 xfer->is_draining = 0; 111 xfer->status = LIBUSB20_TRANSFER_DRAINED; 112 xfer->callback(xfer); 113 } 114 return; 115 } 116 117 int 118 libusb20_tr_close(struct libusb20_transfer *xfer) 119 { 120 int error; 121 122 if (!xfer->is_opened) { 123 return (LIBUSB20_ERROR_OTHER); 124 } 125 error = xfer->pdev->methods->tr_close(xfer); 126 127 if (xfer->pLength) { 128 free(xfer->pLength); 129 } 130 if (xfer->ppBuffer) { 131 free(xfer->ppBuffer); 132 } 133 /* reset variable fields in case the transfer is opened again */ 134 xfer->priv_sc0 = 0; 135 xfer->priv_sc1 = 0; 136 xfer->is_opened = 0; 137 xfer->is_pending = 0; 138 xfer->is_cancel = 0; 139 xfer->is_draining = 0; 140 xfer->is_restart = 0; 141 xfer->status = 0; 142 xfer->flags = 0; 143 xfer->nFrames = 0; 144 xfer->aFrames = 0; 145 xfer->timeout = 0; 146 xfer->maxFrames = 0; 147 xfer->maxTotalLength = 0; 148 xfer->maxPacketLen = 0; 149 return (error); 150 } 151 152 int 153 libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 154 uint32_t MaxFrameCount, uint8_t ep_no) 155 { 156 uint32_t size; 157 int error; 158 159 if (xfer->is_opened) { 160 return (LIBUSB20_ERROR_BUSY); 161 } 162 if (MaxFrameCount == 0) { 163 return (LIBUSB20_ERROR_INVALID_PARAM); 164 } 165 xfer->maxFrames = MaxFrameCount; 166 167 size = MaxFrameCount * sizeof(xfer->pLength[0]); 168 xfer->pLength = malloc(size); 169 if (xfer->pLength == NULL) { 170 return (LIBUSB20_ERROR_NO_MEM); 171 } 172 memset(xfer->pLength, 0, size); 173 174 size = MaxFrameCount * sizeof(xfer->ppBuffer[0]); 175 xfer->ppBuffer = malloc(size); 176 if (xfer->ppBuffer == NULL) { 177 free(xfer->pLength); 178 return (LIBUSB20_ERROR_NO_MEM); 179 } 180 memset(xfer->ppBuffer, 0, size); 181 182 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 183 MaxFrameCount, ep_no); 184 185 if (error) { 186 free(xfer->ppBuffer); 187 free(xfer->pLength); 188 } else { 189 xfer->is_opened = 1; 190 } 191 return (error); 192 } 193 194 struct libusb20_transfer * 195 libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex) 196 { 197 if (trIndex >= pdev->nTransfer) { 198 return (NULL); 199 } 200 return (pdev->pTransfer + trIndex); 201 } 202 203 uint32_t 204 libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 205 { 206 return (xfer->aFrames); 207 } 208 209 uint16_t 210 libusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 211 { 212 return (xfer->timeComplete); 213 } 214 215 uint32_t 216 libusb20_tr_get_actual_length(struct libusb20_transfer *xfer) 217 { 218 uint32_t x; 219 uint32_t actlen = 0; 220 221 for (x = 0; x != xfer->aFrames; x++) { 222 actlen += xfer->pLength[x]; 223 } 224 return (actlen); 225 } 226 227 uint32_t 228 libusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 229 { 230 return (xfer->maxFrames); 231 } 232 233 uint32_t 234 libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer) 235 { 236 /* 237 * Special Case NOTE: If the packet multiplier is non-zero for 238 * High Speed USB, the value returned is equal to 239 * "wMaxPacketSize * multiplier" ! 240 */ 241 return (xfer->maxPacketLen); 242 } 243 244 uint32_t 245 libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 246 { 247 return (xfer->maxTotalLength); 248 } 249 250 uint8_t 251 libusb20_tr_get_status(struct libusb20_transfer *xfer) 252 { 253 return (xfer->status); 254 } 255 256 uint8_t 257 libusb20_tr_pending(struct libusb20_transfer *xfer) 258 { 259 return (xfer->is_pending); 260 } 261 262 void * 263 libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 264 { 265 return (xfer->priv_sc0); 266 } 267 268 void * 269 libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 270 { 271 return (xfer->priv_sc1); 272 } 273 274 void 275 libusb20_tr_stop(struct libusb20_transfer *xfer) 276 { 277 if (!xfer->is_opened) { 278 /* transfer is not opened */ 279 return; 280 } 281 if (!xfer->is_pending) { 282 /* transfer not pending */ 283 return; 284 } 285 if (xfer->is_cancel) { 286 /* already cancelling */ 287 return; 288 } 289 xfer->is_cancel = 1; /* we are cancelling */ 290 291 xfer->pdev->methods->tr_cancel_async(xfer); 292 return; 293 } 294 295 void 296 libusb20_tr_drain(struct libusb20_transfer *xfer) 297 { 298 if (!xfer->is_opened) { 299 /* transfer is not opened */ 300 return; 301 } 302 /* make sure that we are cancelling */ 303 libusb20_tr_stop(xfer); 304 305 if (xfer->is_pending) { 306 xfer->is_draining = 1; 307 } 308 return; 309 } 310 311 void 312 libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 313 { 314 xfer->pdev->methods->tr_clear_stall_sync(xfer); 315 return; 316 } 317 318 void 319 libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 320 { 321 xfer->ppBuffer[frIndex] = buffer; 322 return; 323 } 324 325 void 326 libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 327 { 328 xfer->callback = cb; 329 return; 330 } 331 332 void 333 libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 334 { 335 xfer->flags = flags; 336 return; 337 } 338 339 uint32_t 340 libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex) 341 { 342 return (xfer->pLength[frIndex]); 343 } 344 345 void 346 libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 347 { 348 xfer->pLength[frIndex] = length; 349 return; 350 } 351 352 void 353 libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 354 { 355 xfer->priv_sc0 = sc0; 356 return; 357 } 358 359 void 360 libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 361 { 362 xfer->priv_sc1 = sc1; 363 return; 364 } 365 366 void 367 libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 368 { 369 xfer->timeout = timeout; 370 return; 371 } 372 373 void 374 libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames) 375 { 376 if (nFrames > xfer->maxFrames) { 377 /* should not happen */ 378 nFrames = xfer->maxFrames; 379 } 380 xfer->nFrames = nFrames; 381 return; 382 } 383 384 void 385 libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 386 { 387 xfer->ppBuffer[0] = pBuf; 388 xfer->pLength[0] = length; 389 xfer->timeout = timeout; 390 xfer->nFrames = 1; 391 return; 392 } 393 394 void 395 libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout) 396 { 397 uint16_t len; 398 399 xfer->ppBuffer[0] = psetup; 400 xfer->pLength[0] = 8; /* fixed */ 401 xfer->timeout = timeout; 402 403 len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8); 404 405 if (len != 0) { 406 xfer->nFrames = 2; 407 xfer->ppBuffer[1] = pBuf; 408 xfer->pLength[1] = len; 409 } else { 410 xfer->nFrames = 1; 411 } 412 return; 413 } 414 415 void 416 libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 417 { 418 xfer->ppBuffer[0] = pBuf; 419 xfer->pLength[0] = length; 420 xfer->timeout = timeout; 421 xfer->nFrames = 1; 422 return; 423 } 424 425 void 426 libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex) 427 { 428 if (frIndex >= xfer->maxFrames) { 429 /* should not happen */ 430 return; 431 } 432 xfer->ppBuffer[frIndex] = pBuf; 433 xfer->pLength[frIndex] = length; 434 return; 435 } 436 437 uint8_t 438 libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer, 439 void *pbuf, uint32_t length, uint32_t *pactlen, 440 uint32_t timeout) 441 { 442 struct libusb20_device *pdev = xfer->pdev; 443 uint32_t transfer_max; 444 uint32_t transfer_act; 445 uint8_t retval; 446 447 /* set some sensible default value */ 448 if (pactlen != NULL) 449 *pactlen = 0; 450 451 /* check for error condition */ 452 if (libusb20_tr_pending(xfer)) 453 return (LIBUSB20_ERROR_OTHER); 454 455 do { 456 /* compute maximum transfer length */ 457 transfer_max = 458 libusb20_tr_get_max_total_length(xfer); 459 460 if (transfer_max > length) 461 transfer_max = length; 462 463 /* setup bulk or interrupt transfer */ 464 libusb20_tr_setup_bulk(xfer, pbuf, 465 transfer_max, timeout); 466 467 /* start the transfer */ 468 libusb20_tr_start(xfer); 469 470 /* wait for transfer completion */ 471 while (libusb20_dev_process(pdev) == 0) { 472 473 if (libusb20_tr_pending(xfer) == 0) 474 break; 475 476 libusb20_dev_wait_process(pdev, -1); 477 } 478 479 transfer_act = libusb20_tr_get_actual_length(xfer); 480 481 /* update actual length, if any */ 482 if (pactlen != NULL) 483 pactlen[0] += transfer_act; 484 485 /* check transfer status */ 486 retval = libusb20_tr_get_status(xfer); 487 if (retval) 488 break; 489 490 /* check for short transfer */ 491 if (transfer_act != transfer_max) 492 break; 493 494 /* update buffer pointer and length */ 495 pbuf = ((uint8_t *)pbuf) + transfer_max; 496 length = length - transfer_max; 497 498 } while (length != 0); 499 500 return (retval); 501 } 502 503 void 504 libusb20_tr_submit(struct libusb20_transfer *xfer) 505 { 506 if (!xfer->is_opened) { 507 /* transfer is not opened */ 508 return; 509 } 510 if (xfer->is_pending) { 511 /* should not happen */ 512 return; 513 } 514 xfer->is_pending = 1; /* we are pending */ 515 xfer->is_cancel = 0; /* not cancelling */ 516 xfer->is_restart = 0; /* not restarting */ 517 518 xfer->pdev->methods->tr_submit(xfer); 519 return; 520 } 521 522 void 523 libusb20_tr_start(struct libusb20_transfer *xfer) 524 { 525 if (!xfer->is_opened) { 526 /* transfer is not opened */ 527 return; 528 } 529 if (xfer->is_pending) { 530 if (xfer->is_cancel) { 531 /* cancelling - restart */ 532 xfer->is_restart = 1; 533 } 534 /* transfer not pending */ 535 return; 536 } 537 /* get into the callback */ 538 libusb20_tr_callback_wrapper(xfer); 539 return; 540 } 541 542 /* USB device operations */ 543 544 int 545 libusb20_dev_close(struct libusb20_device *pdev) 546 { 547 struct libusb20_transfer *xfer; 548 uint16_t x; 549 int error = 0; 550 551 if (!pdev->is_opened) { 552 return (LIBUSB20_ERROR_OTHER); 553 } 554 for (x = 0; x != pdev->nTransfer; x++) { 555 xfer = pdev->pTransfer + x; 556 557 if (!xfer->is_opened) { 558 /* transfer is not opened */ 559 continue; 560 } 561 562 libusb20_tr_drain(xfer); 563 564 libusb20_tr_close(xfer); 565 } 566 567 if (pdev->pTransfer != NULL) { 568 free(pdev->pTransfer); 569 pdev->pTransfer = NULL; 570 } 571 error = pdev->beMethods->close_device(pdev); 572 573 pdev->methods = &libusb20_dummy_methods; 574 575 pdev->is_opened = 0; 576 577 /* 578 * The following variable is only used by the libusb v0.1 579 * compat layer: 580 */ 581 pdev->claimed_interface = 0; 582 583 return (error); 584 } 585 586 int 587 libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex) 588 { 589 int error; 590 591 error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex); 592 return (error); 593 } 594 595 struct LIBUSB20_DEVICE_DESC_DECODED * 596 libusb20_dev_get_device_desc(struct libusb20_device *pdev) 597 { 598 return (&(pdev->ddesc)); 599 } 600 601 int 602 libusb20_dev_get_fd(struct libusb20_device *pdev) 603 { 604 return (pdev->file); 605 } 606 607 int 608 libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex) 609 { 610 int error; 611 612 error = pdev->methods->kernel_driver_active(pdev, ifaceIndex); 613 return (error); 614 } 615 616 int 617 libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax) 618 { 619 struct libusb20_transfer *xfer; 620 uint32_t size; 621 uint16_t x; 622 int error; 623 624 if (pdev->is_opened) { 625 return (LIBUSB20_ERROR_BUSY); 626 } 627 if (nTransferMax >= 256) { 628 return (LIBUSB20_ERROR_INVALID_PARAM); 629 } else if (nTransferMax != 0) { 630 size = sizeof(pdev->pTransfer[0]) * nTransferMax; 631 pdev->pTransfer = malloc(size); 632 if (pdev->pTransfer == NULL) { 633 return (LIBUSB20_ERROR_NO_MEM); 634 } 635 memset(pdev->pTransfer, 0, size); 636 } 637 /* initialise all transfers */ 638 for (x = 0; x != nTransferMax; x++) { 639 640 xfer = pdev->pTransfer + x; 641 642 xfer->pdev = pdev; 643 xfer->trIndex = x; 644 xfer->callback = &dummy_callback; 645 } 646 647 /* set "nTransfer" early */ 648 pdev->nTransfer = nTransferMax; 649 650 error = pdev->beMethods->open_device(pdev, nTransferMax); 651 652 if (error) { 653 if (pdev->pTransfer != NULL) { 654 free(pdev->pTransfer); 655 pdev->pTransfer = NULL; 656 } 657 pdev->file = -1; 658 pdev->file_ctrl = -1; 659 pdev->nTransfer = 0; 660 } else { 661 pdev->is_opened = 1; 662 } 663 return (error); 664 } 665 666 int 667 libusb20_dev_reset(struct libusb20_device *pdev) 668 { 669 int error; 670 671 error = pdev->methods->reset_device(pdev); 672 return (error); 673 } 674 675 int 676 libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 677 { 678 int error; 679 680 error = pdev->methods->set_power_mode(pdev, power_mode); 681 return (error); 682 } 683 684 uint8_t 685 libusb20_dev_get_power_mode(struct libusb20_device *pdev) 686 { 687 int error; 688 uint8_t power_mode; 689 690 error = pdev->methods->get_power_mode(pdev, &power_mode); 691 if (error) 692 power_mode = LIBUSB20_POWER_ON; /* fake power mode */ 693 return (power_mode); 694 } 695 696 int 697 libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) 698 { 699 int error; 700 701 error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex); 702 return (error); 703 } 704 705 int 706 libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex) 707 { 708 int error; 709 710 error = pdev->methods->set_config_index(pdev, configIndex); 711 return (error); 712 } 713 714 int 715 libusb20_dev_request_sync(struct libusb20_device *pdev, 716 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data, 717 uint16_t *pactlen, uint32_t timeout, uint8_t flags) 718 { 719 int error; 720 721 error = pdev->methods->do_request_sync(pdev, 722 setup, data, pactlen, timeout, flags); 723 return (error); 724 } 725 726 int 727 libusb20_dev_req_string_sync(struct libusb20_device *pdev, 728 uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) 729 { 730 struct LIBUSB20_CONTROL_SETUP_DECODED req; 731 int error; 732 733 /* make sure memory is initialised */ 734 memset(ptr, 0, len); 735 736 if (len < 4) { 737 /* invalid length */ 738 return (LIBUSB20_ERROR_INVALID_PARAM); 739 } 740 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 741 742 /* 743 * We need to read the USB string in two steps else some USB 744 * devices will complain. 745 */ 746 req.bmRequestType = 747 LIBUSB20_REQUEST_TYPE_STANDARD | 748 LIBUSB20_RECIPIENT_DEVICE | 749 LIBUSB20_ENDPOINT_IN; 750 req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; 751 req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; 752 req.wIndex = langid; 753 req.wLength = 4; /* bytes */ 754 755 error = libusb20_dev_request_sync(pdev, &req, 756 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 757 if (error) { 758 return (error); 759 } 760 req.wLength = *(uint8_t *)ptr; /* bytes */ 761 if (req.wLength > len) { 762 /* partial string read */ 763 req.wLength = len; 764 } 765 error = libusb20_dev_request_sync(pdev, &req, 766 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 767 768 if (error) { 769 return (error); 770 } 771 if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) { 772 return (LIBUSB20_ERROR_OTHER); 773 } 774 return (0); /* success */ 775 } 776 777 int 778 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev, 779 uint8_t str_index, void *ptr, uint16_t len) 780 { 781 char *buf; 782 int error; 783 uint16_t langid; 784 uint16_t n; 785 uint16_t i; 786 uint16_t c; 787 uint8_t temp[255]; 788 uint8_t swap; 789 790 /* the following code derives from the FreeBSD USB kernel */ 791 792 if ((len < 1) || (ptr == NULL)) { 793 /* too short buffer */ 794 return (LIBUSB20_ERROR_INVALID_PARAM); 795 } 796 error = libusb20_dev_req_string_sync(pdev, 797 0, 0, temp, sizeof(temp)); 798 if (error < 0) { 799 *(uint8_t *)ptr = 0; /* zero terminate */ 800 return (error); 801 } 802 langid = temp[2] | (temp[3] << 8); 803 804 error = libusb20_dev_req_string_sync(pdev, str_index, 805 langid, temp, sizeof(temp)); 806 if (error < 0) { 807 *(uint8_t *)ptr = 0; /* zero terminate */ 808 return (error); 809 } 810 if (temp[0] < 2) { 811 /* string length is too short */ 812 *(uint8_t *)ptr = 0; /* zero terminate */ 813 return (LIBUSB20_ERROR_OTHER); 814 } 815 /* reserve one byte for terminating zero */ 816 len--; 817 818 /* find maximum length */ 819 n = (temp[0] / 2) - 1; 820 if (n > len) { 821 n = len; 822 } 823 /* reset swap state */ 824 swap = 3; 825 826 /* setup output buffer pointer */ 827 buf = ptr; 828 829 /* convert and filter */ 830 for (i = 0; (i != n); i++) { 831 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8); 832 833 /* convert from Unicode, handle buggy strings */ 834 if (((c & 0xff00) == 0) && (swap & 1)) { 835 /* Little Endian, default */ 836 *buf = c; 837 swap = 1; 838 } else if (((c & 0x00ff) == 0) && (swap & 2)) { 839 /* Big Endian */ 840 *buf = c >> 8; 841 swap = 2; 842 } else { 843 /* skip invalid character */ 844 continue; 845 } 846 /* 847 * Filter by default - we don't allow greater and less than 848 * signs because they might confuse the dmesg printouts! 849 */ 850 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) { 851 /* skip invalid character */ 852 continue; 853 } 854 buf++; 855 } 856 *buf = 0; /* zero terminate string */ 857 858 return (0); 859 } 860 861 struct libusb20_config * 862 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) 863 { 864 struct libusb20_config *retval = NULL; 865 uint8_t *ptr; 866 uint16_t len; 867 uint8_t do_close; 868 int error; 869 870 if (!pdev->is_opened) { 871 error = libusb20_dev_open(pdev, 0); 872 if (error) { 873 return (NULL); 874 } 875 do_close = 1; 876 } else { 877 do_close = 0; 878 } 879 error = pdev->methods->get_config_desc_full(pdev, 880 &ptr, &len, configIndex); 881 882 if (error) { 883 goto done; 884 } 885 /* parse new config descriptor */ 886 retval = libusb20_parse_config_desc(ptr); 887 888 /* free config descriptor */ 889 free(ptr); 890 891 done: 892 if (do_close) { 893 error = libusb20_dev_close(pdev); 894 } 895 return (retval); 896 } 897 898 struct libusb20_device * 899 libusb20_dev_alloc(void) 900 { 901 struct libusb20_device *pdev; 902 903 pdev = malloc(sizeof(*pdev)); 904 if (pdev == NULL) { 905 return (NULL); 906 } 907 memset(pdev, 0, sizeof(*pdev)); 908 909 pdev->file = -1; 910 pdev->file_ctrl = -1; 911 pdev->methods = &libusb20_dummy_methods; 912 return (pdev); 913 } 914 915 uint8_t 916 libusb20_dev_get_config_index(struct libusb20_device *pdev) 917 { 918 int error; 919 uint8_t cfg_index; 920 uint8_t do_close; 921 922 if (!pdev->is_opened) { 923 error = libusb20_dev_open(pdev, 0); 924 if (error == 0) { 925 do_close = 1; 926 } else { 927 do_close = 0; 928 } 929 } else { 930 do_close = 0; 931 } 932 933 error = pdev->methods->get_config_index(pdev, &cfg_index); 934 if (error) { 935 cfg_index = 0 - 1; /* current config index */ 936 } 937 if (do_close) { 938 if (libusb20_dev_close(pdev)) { 939 /* ignore */ 940 } 941 } 942 return (cfg_index); 943 } 944 945 uint8_t 946 libusb20_dev_get_mode(struct libusb20_device *pdev) 947 { 948 return (pdev->usb_mode); 949 } 950 951 uint8_t 952 libusb20_dev_get_speed(struct libusb20_device *pdev) 953 { 954 return (pdev->usb_speed); 955 } 956 957 /* if this function returns an error, the device is gone */ 958 int 959 libusb20_dev_process(struct libusb20_device *pdev) 960 { 961 int error; 962 963 error = pdev->methods->process(pdev); 964 return (error); 965 } 966 967 void 968 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout) 969 { 970 struct pollfd pfd[1]; 971 972 if (!pdev->is_opened) { 973 return; 974 } 975 pfd[0].fd = pdev->file; 976 pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 977 pfd[0].revents = 0; 978 979 if (poll(pfd, 1, timeout)) { 980 /* ignore any error */ 981 } 982 return; 983 } 984 985 void 986 libusb20_dev_free(struct libusb20_device *pdev) 987 { 988 if (pdev == NULL) { 989 /* be NULL safe */ 990 return; 991 } 992 if (pdev->is_opened) { 993 if (libusb20_dev_close(pdev)) { 994 /* ignore any errors */ 995 } 996 } 997 free(pdev); 998 return; 999 } 1000 1001 int 1002 libusb20_dev_get_info(struct libusb20_device *pdev, 1003 struct usb_device_info *pinfo) 1004 { 1005 if (pinfo == NULL) 1006 return (LIBUSB20_ERROR_INVALID_PARAM); 1007 1008 return (pdev->beMethods->dev_get_info(pdev, pinfo)); 1009 } 1010 1011 const char * 1012 libusb20_dev_get_backend_name(struct libusb20_device *pdev) 1013 { 1014 return (pdev->beMethods->get_backend_name()); 1015 } 1016 1017 const char * 1018 libusb20_dev_get_desc(struct libusb20_device *pdev) 1019 { 1020 return (pdev->usb_desc); 1021 } 1022 1023 void 1024 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 1025 { 1026 pdev->debug = debug; 1027 return; 1028 } 1029 1030 int 1031 libusb20_dev_get_debug(struct libusb20_device *pdev) 1032 { 1033 return (pdev->debug); 1034 } 1035 1036 uint8_t 1037 libusb20_dev_get_address(struct libusb20_device *pdev) 1038 { 1039 return (pdev->device_address); 1040 } 1041 1042 uint8_t 1043 libusb20_dev_get_bus_number(struct libusb20_device *pdev) 1044 { 1045 return (pdev->bus_number); 1046 } 1047 1048 int 1049 libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1050 uint8_t iface_index, char *buf, uint8_t len) 1051 { 1052 if ((buf == NULL) || (len == 0)) 1053 return (LIBUSB20_ERROR_INVALID_PARAM); 1054 1055 return (pdev->beMethods->dev_get_iface_desc( 1056 pdev, iface_index, buf, len)); 1057 } 1058 1059 /* USB backend operations */ 1060 1061 int 1062 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1063 uint16_t quirk_index, struct libusb20_quirk *pq) 1064 { 1065 return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1066 } 1067 1068 int 1069 libusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1070 uint16_t quirk_index, struct libusb20_quirk *pq) 1071 { 1072 return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1073 } 1074 1075 int 1076 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1077 struct libusb20_quirk *pq) 1078 { 1079 return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1080 } 1081 1082 int 1083 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1084 struct libusb20_quirk *pq) 1085 { 1086 return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1087 } 1088 1089 int 1090 libusb20_be_set_template(struct libusb20_backend *pbe, int temp) 1091 { 1092 return (pbe->methods->root_set_template(pbe, temp)); 1093 } 1094 1095 int 1096 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp) 1097 { 1098 int temp; 1099 1100 if (ptemp == NULL) 1101 ptemp = &temp; 1102 1103 return (pbe->methods->root_get_template(pbe, ptemp)); 1104 } 1105 1106 struct libusb20_device * 1107 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1108 { 1109 if (pbe == NULL) { 1110 pdev = NULL; 1111 } else if (pdev == NULL) { 1112 pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1113 } else { 1114 pdev = TAILQ_NEXT(pdev, dev_entry); 1115 } 1116 return (pdev); 1117 } 1118 1119 struct libusb20_backend * 1120 libusb20_be_alloc(const struct libusb20_backend_methods *methods) 1121 { 1122 struct libusb20_backend *pbe; 1123 1124 pbe = malloc(sizeof(*pbe)); 1125 if (pbe == NULL) { 1126 return (NULL); 1127 } 1128 memset(pbe, 0, sizeof(*pbe)); 1129 1130 TAILQ_INIT(&(pbe->usb_devs)); 1131 1132 pbe->methods = methods; /* set backend methods */ 1133 1134 /* do the initial device scan */ 1135 if (pbe->methods->init_backend) { 1136 pbe->methods->init_backend(pbe); 1137 } 1138 return (pbe); 1139 } 1140 1141 struct libusb20_backend * 1142 libusb20_be_alloc_linux(void) 1143 { 1144 struct libusb20_backend *pbe; 1145 1146 #ifdef __linux__ 1147 pbe = libusb20_be_alloc(&libusb20_linux_backend); 1148 #else 1149 pbe = NULL; 1150 #endif 1151 return (pbe); 1152 } 1153 1154 struct libusb20_backend * 1155 libusb20_be_alloc_ugen20(void) 1156 { 1157 struct libusb20_backend *pbe; 1158 1159 #ifdef __FreeBSD__ 1160 pbe = libusb20_be_alloc(&libusb20_ugen20_backend); 1161 #else 1162 pbe = NULL; 1163 #endif 1164 return (pbe); 1165 } 1166 1167 struct libusb20_backend * 1168 libusb20_be_alloc_default(void) 1169 { 1170 struct libusb20_backend *pbe; 1171 1172 pbe = libusb20_be_alloc_linux(); 1173 if (pbe) { 1174 return (pbe); 1175 } 1176 pbe = libusb20_be_alloc_ugen20(); 1177 if (pbe) { 1178 return (pbe); 1179 } 1180 return (NULL); /* no backend found */ 1181 } 1182 1183 void 1184 libusb20_be_free(struct libusb20_backend *pbe) 1185 { 1186 struct libusb20_device *pdev; 1187 1188 if (pbe == NULL) { 1189 /* be NULL safe */ 1190 return; 1191 } 1192 while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1193 libusb20_be_dequeue_device(pbe, pdev); 1194 libusb20_dev_free(pdev); 1195 } 1196 if (pbe->methods->exit_backend) { 1197 pbe->methods->exit_backend(pbe); 1198 } 1199 /* free backend */ 1200 free(pbe); 1201 } 1202 1203 void 1204 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1205 { 1206 pdev->beMethods = pbe->methods; /* copy backend methods */ 1207 TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1208 } 1209 1210 void 1211 libusb20_be_dequeue_device(struct libusb20_backend *pbe, 1212 struct libusb20_device *pdev) 1213 { 1214 TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1215 } 1216