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