1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #ifdef LIBUSB_GLOBAL_INCLUDE_FILE 29 #include LIBUSB_GLOBAL_INCLUDE_FILE 30 #else 31 #include <ctype.h> 32 #include <poll.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <time.h> 37 #include <sys/queue.h> 38 #endif 39 40 #include "libusb20.h" 41 #include "libusb20_desc.h" 42 #include "libusb20_int.h" 43 44 static int 45 dummy_int(void) 46 { 47 return (LIBUSB20_ERROR_NOT_SUPPORTED); 48 } 49 50 static void 51 dummy_void(void) 52 { 53 return; 54 } 55 56 static void 57 dummy_callback(struct libusb20_transfer *xfer) 58 { 59 ; /* style fix */ 60 switch (libusb20_tr_get_status(xfer)) { 61 case LIBUSB20_TRANSFER_START: 62 libusb20_tr_submit(xfer); 63 break; 64 default: 65 /* complete or error */ 66 break; 67 } 68 return; 69 } 70 71 #define dummy_get_config_desc_full (void *)dummy_int 72 #define dummy_get_config_index (void *)dummy_int 73 #define dummy_set_config_index (void *)dummy_int 74 #define dummy_set_alt_index (void *)dummy_int 75 #define dummy_reset_device (void *)dummy_int 76 #define dummy_check_connected (void *)dummy_int 77 #define dummy_set_power_mode (void *)dummy_int 78 #define dummy_get_power_mode (void *)dummy_int 79 #define dummy_get_power_usage (void *)dummy_int 80 #define dummy_get_stats (void *)dummy_int 81 #define dummy_kernel_driver_active (void *)dummy_int 82 #define dummy_detach_kernel_driver (void *)dummy_int 83 #define dummy_attach_kernel_driver (void *)dummy_int 84 #define dummy_do_request_sync (void *)dummy_int 85 #define dummy_tr_open (void *)dummy_int 86 #define dummy_tr_close (void *)dummy_int 87 #define dummy_tr_clear_stall_sync (void *)dummy_int 88 #define dummy_process (void *)dummy_int 89 #define dummy_dev_info (void *)dummy_int 90 #define dummy_dev_get_iface_driver (void *)dummy_int 91 92 #define dummy_tr_submit (void *)dummy_void 93 #define dummy_tr_cancel_async (void *)dummy_void 94 95 static const struct libusb20_device_methods libusb20_dummy_methods = { 96 LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 97 }; 98 99 void 100 libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 101 { 102 ; /* style fix */ 103 104 repeat: 105 106 if (!xfer->is_pending) { 107 xfer->status = LIBUSB20_TRANSFER_START; 108 } else { 109 xfer->is_pending = 0; 110 } 111 112 xfer->callback(xfer); 113 114 if (xfer->is_restart) { 115 xfer->is_restart = 0; 116 goto repeat; 117 } 118 if (xfer->is_draining && 119 (!xfer->is_pending)) { 120 xfer->is_draining = 0; 121 xfer->status = LIBUSB20_TRANSFER_DRAINED; 122 xfer->callback(xfer); 123 } 124 return; 125 } 126 127 int 128 libusb20_tr_close(struct libusb20_transfer *xfer) 129 { 130 int error; 131 132 if (!xfer->is_opened) { 133 return (LIBUSB20_ERROR_OTHER); 134 } 135 error = xfer->pdev->methods->tr_close(xfer); 136 137 if (xfer->pLength) { 138 free(xfer->pLength); 139 } 140 if (xfer->ppBuffer) { 141 free(xfer->ppBuffer); 142 } 143 /* reset variable fields in case the transfer is opened again */ 144 xfer->priv_sc0 = NULL; 145 xfer->priv_sc1 = NULL; 146 xfer->is_opened = 0; 147 xfer->is_pending = 0; 148 xfer->is_cancel = 0; 149 xfer->is_draining = 0; 150 xfer->is_restart = 0; 151 xfer->status = 0; 152 xfer->flags = 0; 153 xfer->nFrames = 0; 154 xfer->aFrames = 0; 155 xfer->timeout = 0; 156 xfer->maxFrames = 0; 157 xfer->maxTotalLength = 0; 158 xfer->maxPacketLen = 0; 159 return (error); 160 } 161 162 int 163 libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 164 uint32_t MaxFrameCount, uint8_t ep_no) 165 { 166 return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0)); 167 } 168 169 int 170 libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 171 uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id) 172 { 173 uint32_t size; 174 uint8_t pre_scale; 175 int error; 176 177 if (xfer->is_opened) 178 return (LIBUSB20_ERROR_BUSY); 179 if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) { 180 MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE; 181 /* 182 * The kernel can setup 8 times more frames when 183 * pre-scaling ISOCHRONOUS transfers. Make sure the 184 * length and pointer buffers are big enough: 185 */ 186 MaxFrameCount *= 8; 187 pre_scale = 1; 188 } else { 189 pre_scale = 0; 190 } 191 if (MaxFrameCount == 0) 192 return (LIBUSB20_ERROR_INVALID_PARAM); 193 194 xfer->maxFrames = MaxFrameCount; 195 196 size = MaxFrameCount * sizeof(xfer->pLength[0]); 197 xfer->pLength = malloc(size); 198 if (xfer->pLength == NULL) { 199 return (LIBUSB20_ERROR_NO_MEM); 200 } 201 memset(xfer->pLength, 0, size); 202 203 size = MaxFrameCount * sizeof(xfer->ppBuffer[0]); 204 xfer->ppBuffer = malloc(size); 205 if (xfer->ppBuffer == NULL) { 206 free(xfer->pLength); 207 return (LIBUSB20_ERROR_NO_MEM); 208 } 209 memset(xfer->ppBuffer, 0, size); 210 211 if (pre_scale) { 212 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 213 MaxFrameCount / 8, ep_no, stream_id, 1); 214 } else { 215 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 216 MaxFrameCount, ep_no, stream_id, 0); 217 } 218 219 if (error) { 220 free(xfer->ppBuffer); 221 free(xfer->pLength); 222 } else { 223 xfer->is_opened = 1; 224 } 225 return (error); 226 } 227 228 struct libusb20_transfer * 229 libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex) 230 { 231 if (trIndex >= pdev->nTransfer) { 232 return (NULL); 233 } 234 return (pdev->pTransfer + trIndex); 235 } 236 237 uint32_t 238 libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 239 { 240 return (xfer->aFrames); 241 } 242 243 uint16_t 244 libusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 245 { 246 return (xfer->timeComplete); 247 } 248 249 uint32_t 250 libusb20_tr_get_actual_length(struct libusb20_transfer *xfer) 251 { 252 uint32_t x; 253 uint32_t actlen = 0; 254 255 for (x = 0; x != xfer->aFrames; x++) { 256 actlen += xfer->pLength[x]; 257 } 258 return (actlen); 259 } 260 261 uint32_t 262 libusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 263 { 264 return (xfer->maxFrames); 265 } 266 267 uint32_t 268 libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer) 269 { 270 /* 271 * Special Case NOTE: If the packet multiplier is non-zero for 272 * High Speed USB, the value returned is equal to 273 * "wMaxPacketSize * multiplier" ! 274 */ 275 return (xfer->maxPacketLen); 276 } 277 278 uint32_t 279 libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 280 { 281 return (xfer->maxTotalLength); 282 } 283 284 uint8_t 285 libusb20_tr_get_status(struct libusb20_transfer *xfer) 286 { 287 return (xfer->status); 288 } 289 290 uint8_t 291 libusb20_tr_pending(struct libusb20_transfer *xfer) 292 { 293 return (xfer->is_pending); 294 } 295 296 void * 297 libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 298 { 299 return (xfer->priv_sc0); 300 } 301 302 void * 303 libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 304 { 305 return (xfer->priv_sc1); 306 } 307 308 void 309 libusb20_tr_stop(struct libusb20_transfer *xfer) 310 { 311 if (!xfer->is_opened) { 312 /* transfer is not opened */ 313 return; 314 } 315 if (!xfer->is_pending) { 316 /* transfer not pending */ 317 return; 318 } 319 if (xfer->is_cancel) { 320 /* already cancelling */ 321 return; 322 } 323 xfer->is_cancel = 1; /* we are cancelling */ 324 325 xfer->pdev->methods->tr_cancel_async(xfer); 326 return; 327 } 328 329 void 330 libusb20_tr_drain(struct libusb20_transfer *xfer) 331 { 332 if (!xfer->is_opened) { 333 /* transfer is not opened */ 334 return; 335 } 336 /* make sure that we are cancelling */ 337 libusb20_tr_stop(xfer); 338 339 if (xfer->is_pending) { 340 xfer->is_draining = 1; 341 } 342 return; 343 } 344 345 void 346 libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 347 { 348 xfer->pdev->methods->tr_clear_stall_sync(xfer); 349 return; 350 } 351 352 void 353 libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 354 { 355 xfer->ppBuffer[frIndex] = buffer; 356 return; 357 } 358 359 void 360 libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 361 { 362 xfer->callback = cb; 363 return; 364 } 365 366 void 367 libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 368 { 369 xfer->flags = flags; 370 return; 371 } 372 373 uint32_t 374 libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex) 375 { 376 return (xfer->pLength[frIndex]); 377 } 378 379 void 380 libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 381 { 382 xfer->pLength[frIndex] = length; 383 return; 384 } 385 386 void 387 libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 388 { 389 xfer->priv_sc0 = sc0; 390 return; 391 } 392 393 void 394 libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 395 { 396 xfer->priv_sc1 = sc1; 397 return; 398 } 399 400 void 401 libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 402 { 403 xfer->timeout = timeout; 404 return; 405 } 406 407 void 408 libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames) 409 { 410 if (nFrames > xfer->maxFrames) { 411 /* should not happen */ 412 nFrames = xfer->maxFrames; 413 } 414 xfer->nFrames = nFrames; 415 return; 416 } 417 418 void 419 libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 420 { 421 xfer->ppBuffer[0] = pBuf; 422 xfer->pLength[0] = length; 423 xfer->timeout = timeout; 424 xfer->nFrames = 1; 425 return; 426 } 427 428 void 429 libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout) 430 { 431 uint16_t len; 432 433 xfer->ppBuffer[0] = psetup; 434 xfer->pLength[0] = 8; /* fixed */ 435 xfer->timeout = timeout; 436 437 len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8); 438 439 if (len != 0) { 440 xfer->nFrames = 2; 441 xfer->ppBuffer[1] = pBuf; 442 xfer->pLength[1] = len; 443 } else { 444 xfer->nFrames = 1; 445 } 446 return; 447 } 448 449 void 450 libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 451 { 452 xfer->ppBuffer[0] = pBuf; 453 xfer->pLength[0] = length; 454 xfer->timeout = timeout; 455 xfer->nFrames = 1; 456 return; 457 } 458 459 void 460 libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex) 461 { 462 if (frIndex >= xfer->maxFrames) { 463 /* should not happen */ 464 return; 465 } 466 xfer->ppBuffer[frIndex] = pBuf; 467 xfer->pLength[frIndex] = length; 468 return; 469 } 470 471 uint8_t 472 libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer, 473 void *pbuf, uint32_t length, uint32_t *pactlen, 474 uint32_t timeout) 475 { 476 struct libusb20_device *pdev = xfer->pdev; 477 uint32_t transfer_max; 478 uint32_t transfer_act; 479 uint8_t retval; 480 481 /* set some sensible default value */ 482 if (pactlen != NULL) 483 *pactlen = 0; 484 485 /* check for error condition */ 486 if (libusb20_tr_pending(xfer)) 487 return (LIBUSB20_ERROR_OTHER); 488 489 do { 490 /* compute maximum transfer length */ 491 transfer_max = 492 libusb20_tr_get_max_total_length(xfer); 493 494 if (transfer_max > length) 495 transfer_max = length; 496 497 /* setup bulk or interrupt transfer */ 498 libusb20_tr_setup_bulk(xfer, pbuf, 499 transfer_max, timeout); 500 501 /* start the transfer */ 502 libusb20_tr_start(xfer); 503 504 /* wait for transfer completion */ 505 while (libusb20_dev_process(pdev) == 0) { 506 507 if (libusb20_tr_pending(xfer) == 0) 508 break; 509 510 libusb20_dev_wait_process(pdev, -1); 511 } 512 513 transfer_act = libusb20_tr_get_actual_length(xfer); 514 515 /* update actual length, if any */ 516 if (pactlen != NULL) 517 pactlen[0] += transfer_act; 518 519 /* check transfer status */ 520 retval = libusb20_tr_get_status(xfer); 521 if (retval) 522 break; 523 524 /* check for short transfer */ 525 if (transfer_act != transfer_max) 526 break; 527 528 /* update buffer pointer and length */ 529 pbuf = ((uint8_t *)pbuf) + transfer_max; 530 length = length - transfer_max; 531 532 } while (length != 0); 533 534 return (retval); 535 } 536 537 void 538 libusb20_tr_submit(struct libusb20_transfer *xfer) 539 { 540 if (!xfer->is_opened) { 541 /* transfer is not opened */ 542 return; 543 } 544 if (xfer->is_pending) { 545 /* should not happen */ 546 return; 547 } 548 xfer->is_pending = 1; /* we are pending */ 549 xfer->is_cancel = 0; /* not cancelling */ 550 xfer->is_restart = 0; /* not restarting */ 551 552 xfer->pdev->methods->tr_submit(xfer); 553 return; 554 } 555 556 void 557 libusb20_tr_start(struct libusb20_transfer *xfer) 558 { 559 if (!xfer->is_opened) { 560 /* transfer is not opened */ 561 return; 562 } 563 if (xfer->is_pending) { 564 if (xfer->is_cancel) { 565 /* cancelling - restart */ 566 xfer->is_restart = 1; 567 } 568 /* transfer not pending */ 569 return; 570 } 571 /* get into the callback */ 572 libusb20_tr_callback_wrapper(xfer); 573 return; 574 } 575 576 /* USB device operations */ 577 578 int 579 libusb20_dev_close(struct libusb20_device *pdev) 580 { 581 struct libusb20_transfer *xfer; 582 uint16_t x; 583 int error = 0; 584 585 if (!pdev->is_opened) { 586 return (LIBUSB20_ERROR_OTHER); 587 } 588 for (x = 0; x != pdev->nTransfer; x++) { 589 xfer = pdev->pTransfer + x; 590 591 if (!xfer->is_opened) { 592 /* transfer is not opened */ 593 continue; 594 } 595 596 libusb20_tr_drain(xfer); 597 598 libusb20_tr_close(xfer); 599 } 600 601 if (pdev->pTransfer != NULL) { 602 free(pdev->pTransfer); 603 pdev->pTransfer = NULL; 604 } 605 error = pdev->beMethods->close_device(pdev); 606 607 pdev->methods = &libusb20_dummy_methods; 608 609 pdev->is_opened = 0; 610 611 /* 612 * Make sure libusb20_tr_get_pointer() fails: 613 */ 614 pdev->nTransfer = 0; 615 616 /* 617 * The following variable is only used by the libusb v0.1 618 * compat layer: 619 */ 620 pdev->claimed_interface = 0; 621 622 /* 623 * The following variable is only used by the libusb v1.0 624 * compat layer: 625 */ 626 pdev->auto_detach = 0; 627 628 return (error); 629 } 630 631 int 632 libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex) 633 { 634 int error; 635 636 error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex); 637 return (error); 638 } 639 640 int 641 libusb20_dev_attach_kernel_driver(struct libusb20_device *pdev, 642 uint8_t ifaceIndex) 643 { 644 int error; 645 646 error = pdev->methods->attach_kernel_driver(pdev, ifaceIndex); 647 return (error); 648 } 649 650 struct LIBUSB20_DEVICE_DESC_DECODED * 651 libusb20_dev_get_device_desc(struct libusb20_device *pdev) 652 { 653 return (&(pdev->ddesc)); 654 } 655 656 int 657 libusb20_dev_get_fd(struct libusb20_device *pdev) 658 { 659 return (pdev->file); 660 } 661 662 int 663 libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex) 664 { 665 int error; 666 667 error = pdev->methods->kernel_driver_active(pdev, ifaceIndex); 668 return (error); 669 } 670 671 int 672 libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax) 673 { 674 struct libusb20_transfer *xfer; 675 uint32_t size; 676 uint16_t x; 677 int error; 678 679 if (pdev->is_opened) { 680 return (LIBUSB20_ERROR_BUSY); 681 } 682 if (nTransferMax >= 256) { 683 return (LIBUSB20_ERROR_INVALID_PARAM); 684 } else if (nTransferMax != 0) { 685 size = sizeof(pdev->pTransfer[0]) * nTransferMax; 686 pdev->pTransfer = malloc(size); 687 if (pdev->pTransfer == NULL) { 688 return (LIBUSB20_ERROR_NO_MEM); 689 } 690 memset(pdev->pTransfer, 0, size); 691 } 692 /* initialise all transfers */ 693 for (x = 0; x != nTransferMax; x++) { 694 695 xfer = pdev->pTransfer + x; 696 697 xfer->pdev = pdev; 698 xfer->trIndex = x; 699 xfer->callback = &dummy_callback; 700 } 701 702 /* set "nTransfer" early */ 703 pdev->nTransfer = nTransferMax; 704 705 error = pdev->beMethods->open_device(pdev, nTransferMax); 706 707 if (error) { 708 if (pdev->pTransfer != NULL) { 709 free(pdev->pTransfer); 710 pdev->pTransfer = NULL; 711 } 712 pdev->file = -1; 713 pdev->file_ctrl = -1; 714 pdev->nTransfer = 0; 715 } else { 716 pdev->is_opened = 1; 717 } 718 return (error); 719 } 720 721 int 722 libusb20_dev_reset(struct libusb20_device *pdev) 723 { 724 int error; 725 726 error = pdev->methods->reset_device(pdev); 727 return (error); 728 } 729 730 int 731 libusb20_dev_check_connected(struct libusb20_device *pdev) 732 { 733 int error; 734 735 error = pdev->methods->check_connected(pdev); 736 return (error); 737 } 738 739 int 740 libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 741 { 742 int error; 743 744 error = pdev->methods->set_power_mode(pdev, power_mode); 745 return (error); 746 } 747 748 uint8_t 749 libusb20_dev_get_power_mode(struct libusb20_device *pdev) 750 { 751 int error; 752 uint8_t power_mode; 753 754 error = pdev->methods->get_power_mode(pdev, &power_mode); 755 if (error) 756 power_mode = LIBUSB20_POWER_ON; /* fake power mode */ 757 return (power_mode); 758 } 759 760 int 761 libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize) 762 { 763 764 if (pdev->port_level == 0) { 765 /* 766 * Fallback for backends without port path: 767 */ 768 if (bufsize < 2) 769 return (LIBUSB20_ERROR_OVERFLOW); 770 buf[0] = pdev->parent_address; 771 buf[1] = pdev->parent_port; 772 return (2); 773 } 774 775 /* check if client buffer is too small */ 776 if (pdev->port_level > bufsize) 777 return (LIBUSB20_ERROR_OVERFLOW); 778 779 /* copy port number information */ 780 memcpy(buf, pdev->port_path, pdev->port_level); 781 782 return (pdev->port_level); /* success */ 783 } 784 785 uint16_t 786 libusb20_dev_get_power_usage(struct libusb20_device *pdev) 787 { 788 int error; 789 uint16_t power_usage; 790 791 error = pdev->methods->get_power_usage(pdev, &power_usage); 792 if (error) 793 power_usage = 0; 794 return (power_usage); 795 } 796 797 int 798 libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) 799 { 800 int error; 801 802 error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex); 803 return (error); 804 } 805 806 int 807 libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex) 808 { 809 int error; 810 811 error = pdev->methods->set_config_index(pdev, configIndex); 812 return (error); 813 } 814 815 int 816 libusb20_dev_request_sync(struct libusb20_device *pdev, 817 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data, 818 uint16_t *pactlen, uint32_t timeout, uint8_t flags) 819 { 820 int error; 821 822 error = pdev->methods->do_request_sync(pdev, 823 setup, data, pactlen, timeout, flags); 824 return (error); 825 } 826 827 int 828 libusb20_dev_req_string_sync(struct libusb20_device *pdev, 829 uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) 830 { 831 struct LIBUSB20_CONTROL_SETUP_DECODED req; 832 int error; 833 int flags; 834 835 /* make sure memory is initialised */ 836 memset(ptr, 0, len); 837 838 if (len < 4) { 839 /* invalid length */ 840 return (LIBUSB20_ERROR_INVALID_PARAM); 841 } 842 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 843 844 /* 845 * We need to read the USB string in two steps else some USB 846 * devices will complain. 847 */ 848 req.bmRequestType = 849 LIBUSB20_REQUEST_TYPE_STANDARD | 850 LIBUSB20_RECIPIENT_DEVICE | 851 LIBUSB20_ENDPOINT_IN; 852 req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; 853 req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; 854 req.wIndex = langid; 855 req.wLength = 4; /* bytes */ 856 857 error = libusb20_dev_request_sync(pdev, &req, 858 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 859 if (error) { 860 /* try to request full string */ 861 req.wLength = 255; 862 flags = 0; 863 } else { 864 /* extract length and request full string */ 865 req.wLength = *(uint8_t *)ptr; 866 flags = LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK; 867 } 868 if (req.wLength > len) { 869 /* partial string read */ 870 req.wLength = len; 871 } 872 error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, flags); 873 if (error) 874 return (error); 875 876 if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) 877 return (LIBUSB20_ERROR_OTHER); 878 return (0); /* success */ 879 } 880 881 int 882 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev, 883 uint8_t str_index, void *ptr, uint16_t len) 884 { 885 char *buf; 886 int error; 887 uint16_t langid; 888 uint16_t n; 889 uint16_t i; 890 uint16_t c; 891 uint8_t temp[255]; 892 uint8_t swap; 893 894 /* the following code derives from the FreeBSD USB kernel */ 895 896 if ((len < 1) || (ptr == NULL)) { 897 /* too short buffer */ 898 return (LIBUSB20_ERROR_INVALID_PARAM); 899 } 900 error = libusb20_dev_req_string_sync(pdev, 901 0, 0, temp, sizeof(temp)); 902 if (error < 0) { 903 *(uint8_t *)ptr = 0; /* zero terminate */ 904 return (error); 905 } 906 langid = temp[2] | (temp[3] << 8); 907 908 error = libusb20_dev_req_string_sync(pdev, str_index, 909 langid, temp, sizeof(temp)); 910 if (error < 0) { 911 *(uint8_t *)ptr = 0; /* zero terminate */ 912 return (error); 913 } 914 if (temp[0] < 2) { 915 /* string length is too short */ 916 *(uint8_t *)ptr = 0; /* zero terminate */ 917 return (LIBUSB20_ERROR_OTHER); 918 } 919 /* reserve one byte for terminating zero */ 920 len--; 921 922 /* find maximum length */ 923 n = (temp[0] / 2) - 1; 924 if (n > len) { 925 n = len; 926 } 927 /* reset swap state */ 928 swap = 3; 929 930 /* setup output buffer pointer */ 931 buf = ptr; 932 933 /* convert and filter */ 934 for (i = 0; (i != n); i++) { 935 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8); 936 937 /* convert from Unicode, handle buggy strings */ 938 if (((c & 0xff00) == 0) && (swap & 1)) { 939 /* Little Endian, default */ 940 *buf = c; 941 swap = 1; 942 } else if (((c & 0x00ff) == 0) && (swap & 2)) { 943 /* Big Endian */ 944 *buf = c >> 8; 945 swap = 2; 946 } else { 947 /* skip invalid character */ 948 continue; 949 } 950 /* 951 * Filter by default - we don't allow greater and less than 952 * signs because they might confuse the dmesg printouts! 953 */ 954 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) { 955 /* skip invalid character */ 956 continue; 957 } 958 buf++; 959 } 960 *buf = 0; /* zero terminate string */ 961 962 return (0); 963 } 964 965 struct libusb20_config * 966 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) 967 { 968 struct libusb20_config *retval = NULL; 969 uint8_t *ptr; 970 uint16_t len; 971 uint8_t do_close; 972 int error; 973 974 /* 975 * Catch invalid configuration descriptor reads early on to 976 * avoid issues with devices that don't check for a valid USB 977 * configuration read request. 978 */ 979 if (configIndex >= pdev->ddesc.bNumConfigurations) 980 return (NULL); 981 982 if (!pdev->is_opened) { 983 error = libusb20_dev_open(pdev, 0); 984 if (error) { 985 return (NULL); 986 } 987 do_close = 1; 988 } else { 989 do_close = 0; 990 } 991 error = pdev->methods->get_config_desc_full(pdev, 992 &ptr, &len, configIndex); 993 994 if (error) { 995 goto done; 996 } 997 /* parse new config descriptor */ 998 retval = libusb20_parse_config_desc(ptr); 999 1000 /* free config descriptor */ 1001 free(ptr); 1002 1003 done: 1004 if (do_close) { 1005 error = libusb20_dev_close(pdev); 1006 } 1007 return (retval); 1008 } 1009 1010 struct libusb20_device * 1011 libusb20_dev_alloc(void) 1012 { 1013 struct libusb20_device *pdev; 1014 1015 pdev = malloc(sizeof(*pdev)); 1016 if (pdev == NULL) { 1017 return (NULL); 1018 } 1019 memset(pdev, 0, sizeof(*pdev)); 1020 1021 pdev->file = -1; 1022 pdev->file_ctrl = -1; 1023 pdev->methods = &libusb20_dummy_methods; 1024 return (pdev); 1025 } 1026 1027 uint8_t 1028 libusb20_dev_get_config_index(struct libusb20_device *pdev) 1029 { 1030 int error; 1031 uint8_t cfg_index; 1032 uint8_t do_close; 1033 1034 if (!pdev->is_opened) { 1035 error = libusb20_dev_open(pdev, 0); 1036 if (error == 0) { 1037 do_close = 1; 1038 } else { 1039 do_close = 0; 1040 } 1041 } else { 1042 do_close = 0; 1043 } 1044 1045 error = pdev->methods->get_config_index(pdev, &cfg_index); 1046 if (error) 1047 cfg_index = 0xFF; /* current config index */ 1048 if (do_close) { 1049 if (libusb20_dev_close(pdev)) { 1050 /* ignore */ 1051 } 1052 } 1053 return (cfg_index); 1054 } 1055 1056 uint8_t 1057 libusb20_dev_get_mode(struct libusb20_device *pdev) 1058 { 1059 return (pdev->usb_mode); 1060 } 1061 1062 uint8_t 1063 libusb20_dev_get_speed(struct libusb20_device *pdev) 1064 { 1065 return (pdev->usb_speed); 1066 } 1067 1068 int 1069 libusb20_dev_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstats) 1070 { 1071 uint8_t do_close; 1072 int error; 1073 1074 if (!pdev->is_opened) { 1075 error = libusb20_dev_open(pdev, 0); 1076 if (error == 0) { 1077 do_close = 1; 1078 } else { 1079 do_close = 0; 1080 } 1081 } else { 1082 do_close = 0; 1083 } 1084 1085 error = pdev->methods->get_stats(pdev, pstats); 1086 1087 if (do_close) 1088 (void) libusb20_dev_close(pdev); 1089 1090 return (error); 1091 } 1092 1093 /* if this function returns an error, the device is gone */ 1094 int 1095 libusb20_dev_process(struct libusb20_device *pdev) 1096 { 1097 int error; 1098 1099 error = pdev->methods->process(pdev); 1100 return (error); 1101 } 1102 1103 void 1104 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout) 1105 { 1106 struct pollfd pfd[1]; 1107 1108 if (!pdev->is_opened) { 1109 return; 1110 } 1111 pfd[0].fd = pdev->file; 1112 pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 1113 pfd[0].revents = 0; 1114 1115 if (poll(pfd, 1, timeout)) { 1116 /* ignore any error */ 1117 } 1118 return; 1119 } 1120 1121 void 1122 libusb20_dev_free(struct libusb20_device *pdev) 1123 { 1124 if (pdev == NULL) { 1125 /* be NULL safe */ 1126 return; 1127 } 1128 if (pdev->is_opened) { 1129 if (libusb20_dev_close(pdev)) { 1130 /* ignore any errors */ 1131 } 1132 } 1133 free(pdev); 1134 return; 1135 } 1136 1137 int 1138 libusb20_dev_get_info(struct libusb20_device *pdev, 1139 struct usb_device_info *pinfo) 1140 { 1141 if (pinfo == NULL) 1142 return (LIBUSB20_ERROR_INVALID_PARAM); 1143 1144 return (pdev->beMethods->dev_get_info(pdev, pinfo)); 1145 } 1146 1147 const char * 1148 libusb20_dev_get_backend_name(struct libusb20_device *pdev) 1149 { 1150 return (pdev->beMethods->get_backend_name()); 1151 } 1152 1153 const char * 1154 libusb20_dev_get_desc(struct libusb20_device *pdev) 1155 { 1156 return (pdev->usb_desc); 1157 } 1158 1159 void 1160 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 1161 { 1162 pdev->debug = debug; 1163 return; 1164 } 1165 1166 int 1167 libusb20_dev_get_debug(struct libusb20_device *pdev) 1168 { 1169 return (pdev->debug); 1170 } 1171 1172 uint8_t 1173 libusb20_dev_get_address(struct libusb20_device *pdev) 1174 { 1175 return (pdev->device_address); 1176 } 1177 1178 uint8_t 1179 libusb20_dev_get_parent_address(struct libusb20_device *pdev) 1180 { 1181 return (pdev->parent_address); 1182 } 1183 1184 uint8_t 1185 libusb20_dev_get_parent_port(struct libusb20_device *pdev) 1186 { 1187 return (pdev->parent_port); 1188 } 1189 1190 uint8_t 1191 libusb20_dev_get_bus_number(struct libusb20_device *pdev) 1192 { 1193 return (pdev->bus_number); 1194 } 1195 1196 int 1197 libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1198 uint8_t iface_index, char *buf, uint8_t len) 1199 { 1200 if ((buf == NULL) || (len == 0)) 1201 return (LIBUSB20_ERROR_INVALID_PARAM); 1202 1203 buf[0] = 0; /* set default string value */ 1204 1205 return (pdev->beMethods->dev_get_iface_desc( 1206 pdev, iface_index, buf, len)); 1207 } 1208 1209 /* USB backend operations */ 1210 1211 int 1212 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1213 uint16_t quirk_index, struct libusb20_quirk *pq) 1214 { 1215 return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1216 } 1217 1218 int 1219 libusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1220 uint16_t quirk_index, struct libusb20_quirk *pq) 1221 { 1222 return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1223 } 1224 1225 int 1226 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1227 struct libusb20_quirk *pq) 1228 { 1229 return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1230 } 1231 1232 int 1233 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1234 struct libusb20_quirk *pq) 1235 { 1236 return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1237 } 1238 1239 int 1240 libusb20_be_set_template(struct libusb20_backend *pbe, int temp) 1241 { 1242 return (pbe->methods->root_set_template(pbe, temp)); 1243 } 1244 1245 int 1246 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp) 1247 { 1248 int temp; 1249 1250 if (ptemp == NULL) 1251 ptemp = &temp; 1252 1253 return (pbe->methods->root_get_template(pbe, ptemp)); 1254 } 1255 1256 struct libusb20_device * 1257 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1258 { 1259 if (pbe == NULL) { 1260 pdev = NULL; 1261 } else if (pdev == NULL) { 1262 pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1263 } else { 1264 pdev = TAILQ_NEXT(pdev, dev_entry); 1265 } 1266 return (pdev); 1267 } 1268 1269 struct libusb20_backend * 1270 libusb20_be_alloc(const struct libusb20_backend_methods *methods) 1271 { 1272 struct libusb20_backend *pbe; 1273 1274 pbe = malloc(sizeof(*pbe)); 1275 if (pbe == NULL) { 1276 return (NULL); 1277 } 1278 memset(pbe, 0, sizeof(*pbe)); 1279 1280 TAILQ_INIT(&(pbe->usb_devs)); 1281 1282 pbe->methods = methods; /* set backend methods */ 1283 1284 /* do the initial device scan */ 1285 if (pbe->methods->init_backend) { 1286 pbe->methods->init_backend(pbe); 1287 } 1288 return (pbe); 1289 } 1290 1291 struct libusb20_backend * 1292 libusb20_be_alloc_linux(void) 1293 { 1294 return (NULL); 1295 } 1296 1297 struct libusb20_backend * 1298 libusb20_be_alloc_ugen20(void) 1299 { 1300 return (libusb20_be_alloc(&libusb20_ugen20_backend)); 1301 } 1302 1303 struct libusb20_backend * 1304 libusb20_be_alloc_default(void) 1305 { 1306 struct libusb20_backend *pbe; 1307 1308 #ifdef __linux__ 1309 pbe = libusb20_be_alloc_linux(); 1310 if (pbe) { 1311 return (pbe); 1312 } 1313 #endif 1314 pbe = libusb20_be_alloc_ugen20(); 1315 if (pbe) { 1316 return (pbe); 1317 } 1318 return (NULL); /* no backend found */ 1319 } 1320 1321 void 1322 libusb20_be_free(struct libusb20_backend *pbe) 1323 { 1324 struct libusb20_device *pdev; 1325 1326 if (pbe == NULL) { 1327 /* be NULL safe */ 1328 return; 1329 } 1330 while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1331 libusb20_be_dequeue_device(pbe, pdev); 1332 libusb20_dev_free(pdev); 1333 } 1334 if (pbe->methods->exit_backend) { 1335 pbe->methods->exit_backend(pbe); 1336 } 1337 /* free backend */ 1338 free(pbe); 1339 } 1340 1341 void 1342 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1343 { 1344 pdev->beMethods = pbe->methods; /* copy backend methods */ 1345 TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1346 } 1347 1348 void 1349 libusb20_be_dequeue_device(struct libusb20_backend *pbe, 1350 struct libusb20_device *pdev) 1351 { 1352 TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1353 } 1354 1355 const char * 1356 libusb20_strerror(int code) 1357 { 1358 switch (code) { 1359 case LIBUSB20_SUCCESS: 1360 return ("Success"); 1361 case LIBUSB20_ERROR_IO: 1362 return ("I/O error"); 1363 case LIBUSB20_ERROR_INVALID_PARAM: 1364 return ("Invalid parameter"); 1365 case LIBUSB20_ERROR_ACCESS: 1366 return ("Permissions error"); 1367 case LIBUSB20_ERROR_NO_DEVICE: 1368 return ("No device"); 1369 case LIBUSB20_ERROR_NOT_FOUND: 1370 return ("Not found"); 1371 case LIBUSB20_ERROR_BUSY: 1372 return ("Device busy"); 1373 case LIBUSB20_ERROR_TIMEOUT: 1374 return ("Timeout"); 1375 case LIBUSB20_ERROR_OVERFLOW: 1376 return ("Overflow"); 1377 case LIBUSB20_ERROR_PIPE: 1378 return ("Pipe error"); 1379 case LIBUSB20_ERROR_INTERRUPTED: 1380 return ("Interrupted"); 1381 case LIBUSB20_ERROR_NO_MEM: 1382 return ("Out of memory"); 1383 case LIBUSB20_ERROR_NOT_SUPPORTED: 1384 return ("Not supported"); 1385 case LIBUSB20_ERROR_OTHER: 1386 return ("Other error"); 1387 default: 1388 return ("Unknown error"); 1389 } 1390 } 1391 1392 const char * 1393 libusb20_error_name(int code) 1394 { 1395 switch (code) { 1396 case LIBUSB20_SUCCESS: 1397 return ("LIBUSB20_SUCCESS"); 1398 case LIBUSB20_ERROR_IO: 1399 return ("LIBUSB20_ERROR_IO"); 1400 case LIBUSB20_ERROR_INVALID_PARAM: 1401 return ("LIBUSB20_ERROR_INVALID_PARAM"); 1402 case LIBUSB20_ERROR_ACCESS: 1403 return ("LIBUSB20_ERROR_ACCESS"); 1404 case LIBUSB20_ERROR_NO_DEVICE: 1405 return ("LIBUSB20_ERROR_NO_DEVICE"); 1406 case LIBUSB20_ERROR_NOT_FOUND: 1407 return ("LIBUSB20_ERROR_NOT_FOUND"); 1408 case LIBUSB20_ERROR_BUSY: 1409 return ("LIBUSB20_ERROR_BUSY"); 1410 case LIBUSB20_ERROR_TIMEOUT: 1411 return ("LIBUSB20_ERROR_TIMEOUT"); 1412 case LIBUSB20_ERROR_OVERFLOW: 1413 return ("LIBUSB20_ERROR_OVERFLOW"); 1414 case LIBUSB20_ERROR_PIPE: 1415 return ("LIBUSB20_ERROR_PIPE"); 1416 case LIBUSB20_ERROR_INTERRUPTED: 1417 return ("LIBUSB20_ERROR_INTERRUPTED"); 1418 case LIBUSB20_ERROR_NO_MEM: 1419 return ("LIBUSB20_ERROR_NO_MEM"); 1420 case LIBUSB20_ERROR_NOT_SUPPORTED: 1421 return ("LIBUSB20_ERROR_NOT_SUPPORTED"); 1422 case LIBUSB20_ERROR_OTHER: 1423 return ("LIBUSB20_ERROR_OTHER"); 1424 default: 1425 return ("LIBUSB20_ERROR_UNKNOWN"); 1426 } 1427 } 1428