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