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