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