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