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