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