libusb20.c revision 188622
1/* $FreeBSD: head/lib/libusb20/libusb20.c 188622 2009-02-14 23:20:00Z thompsa $ */ 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 38static int 39dummy_int(void) 40{ 41 return (LIBUSB20_ERROR_NOT_SUPPORTED); 42} 43 44static void 45dummy_void(void) 46{ 47 return; 48} 49 50static void 51dummy_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 87static const struct libusb20_device_methods libusb20_dummy_methods = { 88 LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 89}; 90 91void 92libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 93{ 94 ; /* style fix */ 95 96repeat: 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 119int 120libusb20_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 143int 144libusb20_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 185struct libusb20_transfer * 186libusb20_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 194uint32_t 195libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 196{ 197 return (xfer->aFrames); 198} 199 200uint16_t 201libusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 202{ 203 return (xfer->timeComplete); 204} 205 206uint32_t 207libusb20_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 218uint32_t 219libusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 220{ 221 return (xfer->maxFrames); 222} 223 224uint32_t 225libusb20_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 235uint32_t 236libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 237{ 238 return (xfer->maxTotalLength); 239} 240 241uint8_t 242libusb20_tr_get_status(struct libusb20_transfer *xfer) 243{ 244 return (xfer->status); 245} 246 247uint8_t 248libusb20_tr_pending(struct libusb20_transfer *xfer) 249{ 250 return (xfer->is_pending); 251} 252 253void * 254libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 255{ 256 return (xfer->priv_sc0); 257} 258 259void * 260libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 261{ 262 return (xfer->priv_sc1); 263} 264 265void 266libusb20_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 282void 283libusb20_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 294void 295libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 296{ 297 xfer->pdev->methods->tr_clear_stall_sync(xfer); 298 return; 299} 300 301void 302libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 303{ 304 xfer->ppBuffer[frIndex] = buffer; 305 return; 306} 307 308void 309libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 310{ 311 xfer->callback = cb; 312 return; 313} 314 315void 316libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 317{ 318 xfer->flags = flags; 319 return; 320} 321 322void 323libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 324{ 325 xfer->pLength[frIndex] = length; 326 return; 327} 328 329void 330libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 331{ 332 xfer->priv_sc0 = sc0; 333 return; 334} 335 336void 337libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 338{ 339 xfer->priv_sc1 = sc1; 340 return; 341} 342 343void 344libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 345{ 346 xfer->timeout = timeout; 347 return; 348} 349 350void 351libusb20_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 361void 362libusb20_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 371void 372libusb20_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 392void 393libusb20_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 402void 403libusb20_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 414void 415libusb20_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 429void 430libusb20_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 447int 448libusb20_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 465int 466libusb20_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 496int 497libusb20_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 505struct LIBUSB20_DEVICE_DESC_DECODED * 506libusb20_dev_get_device_desc(struct libusb20_device *pdev) 507{ 508 return (&(pdev->ddesc)); 509} 510 511int 512libusb20_dev_get_fd(struct libusb20_device *pdev) 513{ 514 return (pdev->file); 515} 516 517int 518libusb20_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 526int 527libusb20_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 576int 577libusb20_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 594int 595libusb20_dev_reset(struct libusb20_device *pdev) 596{ 597 int error; 598 599 error = pdev->methods->reset_device(pdev); 600 return (error); 601} 602 603int 604libusb20_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 612uint8_t 613libusb20_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 624int 625libusb20_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 633int 634libusb20_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 642int 643libusb20_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 654int 655libusb20_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 702int 703libusb20_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 786struct libusb20_config * 787libusb20_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 816done: 817 if (do_close) { 818 error = libusb20_dev_close(pdev); 819 } 820 return (retval); 821} 822 823struct libusb20_device * 824libusb20_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 840uint8_t 841libusb20_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 870uint8_t 871libusb20_dev_get_mode(struct libusb20_device *pdev) 872{ 873 return (pdev->usb_mode); 874} 875 876uint8_t 877libusb20_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 */ 883int 884libusb20_dev_process(struct libusb20_device *pdev) 885{ 886 int error; 887 888 error = pdev->methods->process(pdev); 889 return (error); 890} 891 892void 893libusb20_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 910void 911libusb20_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 926int 927libusb20_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 936const char * 937libusb20_dev_get_backend_name(struct libusb20_device *pdev) 938{ 939 return (pdev->beMethods->get_backend_name()); 940} 941 942const char * 943libusb20_dev_get_desc(struct libusb20_device *pdev) 944{ 945 return (pdev->usb_desc); 946} 947 948void 949libusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 950{ 951 pdev->debug = debug; 952 return; 953} 954 955int 956libusb20_dev_get_debug(struct libusb20_device *pdev) 957{ 958 return (pdev->debug); 959} 960 961uint8_t 962libusb20_dev_get_address(struct libusb20_device *pdev) 963{ 964 return (pdev->device_address); 965} 966 967uint8_t 968libusb20_dev_get_bus_number(struct libusb20_device *pdev) 969{ 970 return (pdev->bus_number); 971} 972 973int 974libusb20_dev_set_owner(struct libusb20_device *pdev, uid_t user, gid_t group) 975{ 976 return (pdev->beMethods->dev_set_owner(pdev, user, group)); 977} 978 979int 980libusb20_dev_set_perm(struct libusb20_device *pdev, mode_t mode) 981{ 982 return (pdev->beMethods->dev_set_perm(pdev, mode)); 983} 984 985int 986libusb20_dev_set_iface_owner(struct libusb20_device *pdev, 987 uint8_t iface_index, uid_t user, gid_t group) 988{ 989 return (pdev->beMethods->dev_set_iface_owner( 990 pdev, iface_index, user, group)); 991} 992 993int 994libusb20_dev_set_iface_perm(struct libusb20_device *pdev, 995 uint8_t iface_index, mode_t mode) 996{ 997 return (pdev->beMethods->dev_set_iface_perm( 998 pdev, iface_index, mode)); 999} 1000 1001int 1002libusb20_dev_get_owner(struct libusb20_device *pdev, uid_t *user, gid_t *group) 1003{ 1004 uid_t a; 1005 gid_t b; 1006 1007 if (user == NULL) 1008 user = &a; 1009 if (group == NULL) 1010 group = &b; 1011 1012 return (pdev->beMethods->dev_get_owner(pdev, user, group)); 1013} 1014 1015int 1016libusb20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode) 1017{ 1018 mode_t a; 1019 1020 if (mode == NULL) 1021 mode = &a; 1022 return (pdev->beMethods->dev_get_perm(pdev, mode)); 1023} 1024 1025int 1026libusb20_dev_get_iface_owner(struct libusb20_device *pdev, 1027 uint8_t iface_index, uid_t *user, gid_t *group) 1028{ 1029 uid_t a; 1030 gid_t b; 1031 1032 if (user == NULL) 1033 user = &a; 1034 if (group == NULL) 1035 group = &b; 1036 1037 return (pdev->beMethods->dev_get_iface_owner( 1038 pdev, iface_index, user, group)); 1039} 1040 1041int 1042libusb20_dev_get_iface_perm(struct libusb20_device *pdev, 1043 uint8_t iface_index, mode_t *mode) 1044{ 1045 mode_t a; 1046 1047 if (mode == NULL) 1048 mode = &a; 1049 return (pdev->beMethods->dev_get_iface_perm( 1050 pdev, iface_index, mode)); 1051} 1052 1053int 1054libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1055 uint8_t iface_index, char *buf, uint8_t len) 1056{ 1057 if ((buf == NULL) || (len == 0)) 1058 return (LIBUSB20_ERROR_INVALID_PARAM); 1059 1060 return (pdev->beMethods->dev_get_iface_desc( 1061 pdev, iface_index, buf, len)); 1062} 1063 1064/* USB bus operations */ 1065 1066int 1067libusb20_bus_set_owner(struct libusb20_backend *pbe, 1068 uint8_t bus, uid_t user, gid_t group) 1069{ 1070 return (pbe->methods->bus_set_owner(pbe, bus, user, group)); 1071} 1072 1073int 1074libusb20_bus_set_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t mode) 1075{ 1076 return (pbe->methods->bus_set_perm(pbe, bus, mode)); 1077} 1078 1079int 1080libusb20_bus_get_owner(struct libusb20_backend *pbe, 1081 uint8_t bus, uid_t *user, gid_t *group) 1082{ 1083 uid_t a; 1084 gid_t b; 1085 1086 if (user == NULL) 1087 user = &a; 1088 if (group == NULL) 1089 group = &b; 1090 return (pbe->methods->bus_get_owner(pbe, bus, user, group)); 1091} 1092 1093int 1094libusb20_bus_get_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode) 1095{ 1096 mode_t a; 1097 1098 if (mode == NULL) 1099 mode = &a; 1100 return (pbe->methods->bus_get_perm(pbe, bus, mode)); 1101} 1102 1103/* USB backend operations */ 1104 1105int 1106libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1107 uint16_t quirk_index, struct libusb20_quirk *pq) 1108{ 1109 return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1110} 1111 1112int 1113libusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1114 uint16_t quirk_index, struct libusb20_quirk *pq) 1115{ 1116 return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1117} 1118 1119int 1120libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1121 struct libusb20_quirk *pq) 1122{ 1123 return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1124} 1125 1126int 1127libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1128 struct libusb20_quirk *pq) 1129{ 1130 return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1131} 1132 1133int 1134libusb20_be_set_owner(struct libusb20_backend *pbe, uid_t user, gid_t group) 1135{ 1136 return (pbe->methods->root_set_owner(pbe, user, group)); 1137} 1138 1139int 1140libusb20_be_set_perm(struct libusb20_backend *pbe, mode_t mode) 1141{ 1142 return (pbe->methods->root_set_perm(pbe, mode)); 1143} 1144 1145int 1146libusb20_be_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group) 1147{ 1148 uid_t a; 1149 gid_t b; 1150 1151 if (user == NULL) 1152 user = &a; 1153 if (group == NULL) 1154 group = &b; 1155 return (pbe->methods->root_get_owner(pbe, user, group)); 1156} 1157 1158int 1159libusb20_be_get_perm(struct libusb20_backend *pbe, mode_t *mode) 1160{ 1161 mode_t a; 1162 1163 if (mode == NULL) 1164 mode = &a; 1165 return (pbe->methods->root_get_perm(pbe, mode)); 1166} 1167 1168struct libusb20_device * 1169libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1170{ 1171 if (pbe == NULL) { 1172 pdev = NULL; 1173 } else if (pdev == NULL) { 1174 pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1175 } else { 1176 pdev = TAILQ_NEXT(pdev, dev_entry); 1177 } 1178 return (pdev); 1179} 1180 1181struct libusb20_backend * 1182libusb20_be_alloc(const struct libusb20_backend_methods *methods) 1183{ 1184 struct libusb20_backend *pbe; 1185 1186 pbe = malloc(sizeof(*pbe)); 1187 if (pbe == NULL) { 1188 return (NULL); 1189 } 1190 memset(pbe, 0, sizeof(*pbe)); 1191 1192 TAILQ_INIT(&(pbe->usb_devs)); 1193 1194 pbe->methods = methods; /* set backend methods */ 1195 1196 /* do the initial device scan */ 1197 if (pbe->methods->init_backend) { 1198 pbe->methods->init_backend(pbe); 1199 } 1200 return (pbe); 1201} 1202 1203struct libusb20_backend * 1204libusb20_be_alloc_linux(void) 1205{ 1206 struct libusb20_backend *pbe; 1207 1208#ifdef __linux__ 1209 pbe = libusb20_be_alloc(&libusb20_linux_backend); 1210#else 1211 pbe = NULL; 1212#endif 1213 return (pbe); 1214} 1215 1216struct libusb20_backend * 1217libusb20_be_alloc_ugen20(void) 1218{ 1219 struct libusb20_backend *pbe; 1220 1221#ifdef __FreeBSD__ 1222 pbe = libusb20_be_alloc(&libusb20_ugen20_backend); 1223#else 1224 pbe = NULL; 1225#endif 1226 return (pbe); 1227} 1228 1229struct libusb20_backend * 1230libusb20_be_alloc_default(void) 1231{ 1232 struct libusb20_backend *pbe; 1233 1234 pbe = libusb20_be_alloc_linux(); 1235 if (pbe) { 1236 return (pbe); 1237 } 1238 pbe = libusb20_be_alloc_ugen20(); 1239 if (pbe) { 1240 return (pbe); 1241 } 1242 return (NULL); /* no backend found */ 1243} 1244 1245void 1246libusb20_be_free(struct libusb20_backend *pbe) 1247{ 1248 struct libusb20_device *pdev; 1249 1250 if (pbe == NULL) { 1251 /* be NULL safe */ 1252 return; 1253 } 1254 while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1255 libusb20_be_dequeue_device(pbe, pdev); 1256 libusb20_dev_free(pdev); 1257 } 1258 if (pbe->methods->exit_backend) { 1259 pbe->methods->exit_backend(pbe); 1260 } 1261 return; 1262} 1263 1264void 1265libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1266{ 1267 pdev->beMethods = pbe->methods; /* copy backend methods */ 1268 TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1269 return; 1270} 1271 1272void 1273libusb20_be_dequeue_device(struct libusb20_backend *pbe, 1274 struct libusb20_device *pdev) 1275{ 1276 TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1277 return; 1278} 1279