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