libusb20.c revision 356399
1/* $FreeBSD: stable/10/lib/libusb/libusb20.c 356399 2020-01-06 09:22:33Z hselasky $ */ 2/*- 3 * Copyright (c) 2008-2009 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#ifdef LIBUSB_GLOBAL_INCLUDE_FILE 28#include LIBUSB_GLOBAL_INCLUDE_FILE 29#else 30#include <ctype.h> 31#include <poll.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <time.h> 36#include <sys/queue.h> 37#endif 38 39#include "libusb20.h" 40#include "libusb20_desc.h" 41#include "libusb20_int.h" 42 43static int 44dummy_int(void) 45{ 46 return (LIBUSB20_ERROR_NOT_SUPPORTED); 47} 48 49static void 50dummy_void(void) 51{ 52 return; 53} 54 55static void 56dummy_callback(struct libusb20_transfer *xfer) 57{ 58 ; /* style fix */ 59 switch (libusb20_tr_get_status(xfer)) { 60 case LIBUSB20_TRANSFER_START: 61 libusb20_tr_submit(xfer); 62 break; 63 default: 64 /* complete or error */ 65 break; 66 } 67 return; 68} 69 70#define dummy_get_config_desc_full (void *)dummy_int 71#define dummy_get_config_index (void *)dummy_int 72#define dummy_set_config_index (void *)dummy_int 73#define dummy_set_alt_index (void *)dummy_int 74#define dummy_reset_device (void *)dummy_int 75#define dummy_check_connected (void *)dummy_int 76#define dummy_set_power_mode (void *)dummy_int 77#define dummy_get_power_mode (void *)dummy_int 78#define dummy_get_port_path (void *)dummy_int 79#define dummy_get_power_usage (void *)dummy_int 80#define dummy_get_stats (void *)dummy_int 81#define dummy_kernel_driver_active (void *)dummy_int 82#define dummy_detach_kernel_driver (void *)dummy_int 83#define dummy_do_request_sync (void *)dummy_int 84#define dummy_tr_open (void *)dummy_int 85#define dummy_tr_close (void *)dummy_int 86#define dummy_tr_clear_stall_sync (void *)dummy_int 87#define dummy_process (void *)dummy_int 88#define dummy_dev_info (void *)dummy_int 89#define dummy_dev_get_iface_driver (void *)dummy_int 90 91#define dummy_tr_submit (void *)dummy_void 92#define dummy_tr_cancel_async (void *)dummy_void 93 94static const struct libusb20_device_methods libusb20_dummy_methods = { 95 LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 96}; 97 98void 99libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 100{ 101 ; /* style fix */ 102 103repeat: 104 105 if (!xfer->is_pending) { 106 xfer->status = LIBUSB20_TRANSFER_START; 107 } else { 108 xfer->is_pending = 0; 109 } 110 111 xfer->callback(xfer); 112 113 if (xfer->is_restart) { 114 xfer->is_restart = 0; 115 goto repeat; 116 } 117 if (xfer->is_draining && 118 (!xfer->is_pending)) { 119 xfer->is_draining = 0; 120 xfer->status = LIBUSB20_TRANSFER_DRAINED; 121 xfer->callback(xfer); 122 } 123 return; 124} 125 126int 127libusb20_tr_close(struct libusb20_transfer *xfer) 128{ 129 int error; 130 131 if (!xfer->is_opened) { 132 return (LIBUSB20_ERROR_OTHER); 133 } 134 error = xfer->pdev->methods->tr_close(xfer); 135 136 if (xfer->pLength) { 137 free(xfer->pLength); 138 } 139 if (xfer->ppBuffer) { 140 free(xfer->ppBuffer); 141 } 142 /* reset variable fields in case the transfer is opened again */ 143 xfer->priv_sc0 = 0; 144 xfer->priv_sc1 = 0; 145 xfer->is_opened = 0; 146 xfer->is_pending = 0; 147 xfer->is_cancel = 0; 148 xfer->is_draining = 0; 149 xfer->is_restart = 0; 150 xfer->status = 0; 151 xfer->flags = 0; 152 xfer->nFrames = 0; 153 xfer->aFrames = 0; 154 xfer->timeout = 0; 155 xfer->maxFrames = 0; 156 xfer->maxTotalLength = 0; 157 xfer->maxPacketLen = 0; 158 return (error); 159} 160 161int 162libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 163 uint32_t MaxFrameCount, uint8_t ep_no) 164{ 165 return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0)); 166} 167 168int 169libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 170 uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id) 171{ 172 uint32_t size; 173 uint8_t pre_scale; 174 int error; 175 176 if (xfer->is_opened) 177 return (LIBUSB20_ERROR_BUSY); 178 if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) { 179 MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE; 180 /* 181 * The kernel can setup 8 times more frames when 182 * pre-scaling ISOCHRONOUS transfers. Make sure the 183 * length and pointer buffers are big enough: 184 */ 185 MaxFrameCount *= 8; 186 pre_scale = 1; 187 } else { 188 pre_scale = 0; 189 } 190 if (MaxFrameCount == 0) 191 return (LIBUSB20_ERROR_INVALID_PARAM); 192 193 xfer->maxFrames = MaxFrameCount; 194 195 size = MaxFrameCount * sizeof(xfer->pLength[0]); 196 xfer->pLength = malloc(size); 197 if (xfer->pLength == NULL) { 198 return (LIBUSB20_ERROR_NO_MEM); 199 } 200 memset(xfer->pLength, 0, size); 201 202 size = MaxFrameCount * sizeof(xfer->ppBuffer[0]); 203 xfer->ppBuffer = malloc(size); 204 if (xfer->ppBuffer == NULL) { 205 free(xfer->pLength); 206 return (LIBUSB20_ERROR_NO_MEM); 207 } 208 memset(xfer->ppBuffer, 0, size); 209 210 if (pre_scale) { 211 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 212 MaxFrameCount / 8, ep_no, stream_id, 1); 213 } else { 214 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 215 MaxFrameCount, ep_no, stream_id, 0); 216 } 217 218 if (error) { 219 free(xfer->ppBuffer); 220 free(xfer->pLength); 221 } else { 222 xfer->is_opened = 1; 223 } 224 return (error); 225} 226 227struct libusb20_transfer * 228libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex) 229{ 230 if (trIndex >= pdev->nTransfer) { 231 return (NULL); 232 } 233 return (pdev->pTransfer + trIndex); 234} 235 236uint32_t 237libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 238{ 239 return (xfer->aFrames); 240} 241 242uint16_t 243libusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 244{ 245 return (xfer->timeComplete); 246} 247 248uint32_t 249libusb20_tr_get_actual_length(struct libusb20_transfer *xfer) 250{ 251 uint32_t x; 252 uint32_t actlen = 0; 253 254 for (x = 0; x != xfer->aFrames; x++) { 255 actlen += xfer->pLength[x]; 256 } 257 return (actlen); 258} 259 260uint32_t 261libusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 262{ 263 return (xfer->maxFrames); 264} 265 266uint32_t 267libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer) 268{ 269 /* 270 * Special Case NOTE: If the packet multiplier is non-zero for 271 * High Speed USB, the value returned is equal to 272 * "wMaxPacketSize * multiplier" ! 273 */ 274 return (xfer->maxPacketLen); 275} 276 277uint32_t 278libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 279{ 280 return (xfer->maxTotalLength); 281} 282 283uint8_t 284libusb20_tr_get_status(struct libusb20_transfer *xfer) 285{ 286 return (xfer->status); 287} 288 289uint8_t 290libusb20_tr_pending(struct libusb20_transfer *xfer) 291{ 292 return (xfer->is_pending); 293} 294 295void * 296libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 297{ 298 return (xfer->priv_sc0); 299} 300 301void * 302libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 303{ 304 return (xfer->priv_sc1); 305} 306 307void 308libusb20_tr_stop(struct libusb20_transfer *xfer) 309{ 310 if (!xfer->is_opened) { 311 /* transfer is not opened */ 312 return; 313 } 314 if (!xfer->is_pending) { 315 /* transfer not pending */ 316 return; 317 } 318 if (xfer->is_cancel) { 319 /* already cancelling */ 320 return; 321 } 322 xfer->is_cancel = 1; /* we are cancelling */ 323 324 xfer->pdev->methods->tr_cancel_async(xfer); 325 return; 326} 327 328void 329libusb20_tr_drain(struct libusb20_transfer *xfer) 330{ 331 if (!xfer->is_opened) { 332 /* transfer is not opened */ 333 return; 334 } 335 /* make sure that we are cancelling */ 336 libusb20_tr_stop(xfer); 337 338 if (xfer->is_pending) { 339 xfer->is_draining = 1; 340 } 341 return; 342} 343 344void 345libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 346{ 347 xfer->pdev->methods->tr_clear_stall_sync(xfer); 348 return; 349} 350 351void 352libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 353{ 354 xfer->ppBuffer[frIndex] = libusb20_pass_ptr(buffer); 355 return; 356} 357 358void 359libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 360{ 361 xfer->callback = cb; 362 return; 363} 364 365void 366libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 367{ 368 xfer->flags = flags; 369 return; 370} 371 372uint32_t 373libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex) 374{ 375 return (xfer->pLength[frIndex]); 376} 377 378void 379libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 380{ 381 xfer->pLength[frIndex] = length; 382 return; 383} 384 385void 386libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 387{ 388 xfer->priv_sc0 = sc0; 389 return; 390} 391 392void 393libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 394{ 395 xfer->priv_sc1 = sc1; 396 return; 397} 398 399void 400libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 401{ 402 xfer->timeout = timeout; 403 return; 404} 405 406void 407libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames) 408{ 409 if (nFrames > xfer->maxFrames) { 410 /* should not happen */ 411 nFrames = xfer->maxFrames; 412 } 413 xfer->nFrames = nFrames; 414 return; 415} 416 417void 418libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 419{ 420 xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf); 421 xfer->pLength[0] = length; 422 xfer->timeout = timeout; 423 xfer->nFrames = 1; 424 return; 425} 426 427void 428libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout) 429{ 430 uint16_t len; 431 432 xfer->ppBuffer[0] = libusb20_pass_ptr(psetup); 433 xfer->pLength[0] = 8; /* fixed */ 434 xfer->timeout = timeout; 435 436 len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8); 437 438 if (len != 0) { 439 xfer->nFrames = 2; 440 xfer->ppBuffer[1] = libusb20_pass_ptr(pBuf); 441 xfer->pLength[1] = len; 442 } else { 443 xfer->nFrames = 1; 444 } 445 return; 446} 447 448void 449libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 450{ 451 xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf); 452 xfer->pLength[0] = length; 453 xfer->timeout = timeout; 454 xfer->nFrames = 1; 455 return; 456} 457 458void 459libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex) 460{ 461 if (frIndex >= xfer->maxFrames) { 462 /* should not happen */ 463 return; 464 } 465 xfer->ppBuffer[frIndex] = libusb20_pass_ptr(pBuf); 466 xfer->pLength[frIndex] = length; 467 return; 468} 469 470uint8_t 471libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer, 472 void *pbuf, uint32_t length, uint32_t *pactlen, 473 uint32_t timeout) 474{ 475 struct libusb20_device *pdev = xfer->pdev; 476 uint32_t transfer_max; 477 uint32_t transfer_act; 478 uint8_t retval; 479 480 /* set some sensible default value */ 481 if (pactlen != NULL) 482 *pactlen = 0; 483 484 /* check for error condition */ 485 if (libusb20_tr_pending(xfer)) 486 return (LIBUSB20_ERROR_OTHER); 487 488 do { 489 /* compute maximum transfer length */ 490 transfer_max = 491 libusb20_tr_get_max_total_length(xfer); 492 493 if (transfer_max > length) 494 transfer_max = length; 495 496 /* setup bulk or interrupt transfer */ 497 libusb20_tr_setup_bulk(xfer, pbuf, 498 transfer_max, timeout); 499 500 /* start the transfer */ 501 libusb20_tr_start(xfer); 502 503 /* wait for transfer completion */ 504 while (libusb20_dev_process(pdev) == 0) { 505 506 if (libusb20_tr_pending(xfer) == 0) 507 break; 508 509 libusb20_dev_wait_process(pdev, -1); 510 } 511 512 transfer_act = libusb20_tr_get_actual_length(xfer); 513 514 /* update actual length, if any */ 515 if (pactlen != NULL) 516 pactlen[0] += transfer_act; 517 518 /* check transfer status */ 519 retval = libusb20_tr_get_status(xfer); 520 if (retval) 521 break; 522 523 /* check for short transfer */ 524 if (transfer_act != transfer_max) 525 break; 526 527 /* update buffer pointer and length */ 528 pbuf = ((uint8_t *)pbuf) + transfer_max; 529 length = length - transfer_max; 530 531 } while (length != 0); 532 533 return (retval); 534} 535 536void 537libusb20_tr_submit(struct libusb20_transfer *xfer) 538{ 539 if (!xfer->is_opened) { 540 /* transfer is not opened */ 541 return; 542 } 543 if (xfer->is_pending) { 544 /* should not happen */ 545 return; 546 } 547 xfer->is_pending = 1; /* we are pending */ 548 xfer->is_cancel = 0; /* not cancelling */ 549 xfer->is_restart = 0; /* not restarting */ 550 551 xfer->pdev->methods->tr_submit(xfer); 552 return; 553} 554 555void 556libusb20_tr_start(struct libusb20_transfer *xfer) 557{ 558 if (!xfer->is_opened) { 559 /* transfer is not opened */ 560 return; 561 } 562 if (xfer->is_pending) { 563 if (xfer->is_cancel) { 564 /* cancelling - restart */ 565 xfer->is_restart = 1; 566 } 567 /* transfer not pending */ 568 return; 569 } 570 /* get into the callback */ 571 libusb20_tr_callback_wrapper(xfer); 572 return; 573} 574 575/* USB device operations */ 576 577int 578libusb20_dev_close(struct libusb20_device *pdev) 579{ 580 struct libusb20_transfer *xfer; 581 uint16_t x; 582 int error = 0; 583 584 if (!pdev->is_opened) { 585 return (LIBUSB20_ERROR_OTHER); 586 } 587 for (x = 0; x != pdev->nTransfer; x++) { 588 xfer = pdev->pTransfer + x; 589 590 if (!xfer->is_opened) { 591 /* transfer is not opened */ 592 continue; 593 } 594 595 libusb20_tr_drain(xfer); 596 597 libusb20_tr_close(xfer); 598 } 599 600 if (pdev->pTransfer != NULL) { 601 free(pdev->pTransfer); 602 pdev->pTransfer = NULL; 603 } 604 error = pdev->beMethods->close_device(pdev); 605 606 pdev->methods = &libusb20_dummy_methods; 607 608 pdev->is_opened = 0; 609 610 /* 611 * The following variable is only used by the libusb v0.1 612 * compat layer: 613 */ 614 pdev->claimed_interface = 0; 615 616 /* 617 * The following variable is only used by the libusb v1.0 618 * compat layer: 619 */ 620 pdev->auto_detach = 0; 621 622 return (error); 623} 624 625int 626libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex) 627{ 628 int error; 629 630 error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex); 631 return (error); 632} 633 634struct LIBUSB20_DEVICE_DESC_DECODED * 635libusb20_dev_get_device_desc(struct libusb20_device *pdev) 636{ 637 return (&(pdev->ddesc)); 638} 639 640int 641libusb20_dev_get_fd(struct libusb20_device *pdev) 642{ 643 return (pdev->file); 644} 645 646int 647libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex) 648{ 649 int error; 650 651 error = pdev->methods->kernel_driver_active(pdev, ifaceIndex); 652 return (error); 653} 654 655int 656libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax) 657{ 658 struct libusb20_transfer *xfer; 659 uint32_t size; 660 uint16_t x; 661 int error; 662 663 if (pdev->is_opened) { 664 return (LIBUSB20_ERROR_BUSY); 665 } 666 if (nTransferMax >= 256) { 667 return (LIBUSB20_ERROR_INVALID_PARAM); 668 } else if (nTransferMax != 0) { 669 size = sizeof(pdev->pTransfer[0]) * nTransferMax; 670 pdev->pTransfer = malloc(size); 671 if (pdev->pTransfer == NULL) { 672 return (LIBUSB20_ERROR_NO_MEM); 673 } 674 memset(pdev->pTransfer, 0, size); 675 } 676 /* initialise all transfers */ 677 for (x = 0; x != nTransferMax; x++) { 678 679 xfer = pdev->pTransfer + x; 680 681 xfer->pdev = pdev; 682 xfer->trIndex = x; 683 xfer->callback = &dummy_callback; 684 } 685 686 /* set "nTransfer" early */ 687 pdev->nTransfer = nTransferMax; 688 689 error = pdev->beMethods->open_device(pdev, nTransferMax); 690 691 if (error) { 692 if (pdev->pTransfer != NULL) { 693 free(pdev->pTransfer); 694 pdev->pTransfer = NULL; 695 } 696 pdev->file = -1; 697 pdev->file_ctrl = -1; 698 pdev->nTransfer = 0; 699 } else { 700 pdev->is_opened = 1; 701 } 702 return (error); 703} 704 705int 706libusb20_dev_reset(struct libusb20_device *pdev) 707{ 708 int error; 709 710 error = pdev->methods->reset_device(pdev); 711 return (error); 712} 713 714int 715libusb20_dev_check_connected(struct libusb20_device *pdev) 716{ 717 int error; 718 719 error = pdev->methods->check_connected(pdev); 720 return (error); 721} 722 723int 724libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 725{ 726 int error; 727 728 error = pdev->methods->set_power_mode(pdev, power_mode); 729 return (error); 730} 731 732uint8_t 733libusb20_dev_get_power_mode(struct libusb20_device *pdev) 734{ 735 int error; 736 uint8_t power_mode; 737 738 error = pdev->methods->get_power_mode(pdev, &power_mode); 739 if (error) 740 power_mode = LIBUSB20_POWER_ON; /* fake power mode */ 741 return (power_mode); 742} 743 744int 745libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize) 746{ 747 return (pdev->methods->get_port_path(pdev, buf, bufsize)); 748} 749 750uint16_t 751libusb20_dev_get_power_usage(struct libusb20_device *pdev) 752{ 753 int error; 754 uint16_t power_usage; 755 756 error = pdev->methods->get_power_usage(pdev, &power_usage); 757 if (error) 758 power_usage = 0; 759 return (power_usage); 760} 761 762int 763libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) 764{ 765 int error; 766 767 error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex); 768 return (error); 769} 770 771int 772libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex) 773{ 774 int error; 775 776 error = pdev->methods->set_config_index(pdev, configIndex); 777 return (error); 778} 779 780int 781libusb20_dev_request_sync(struct libusb20_device *pdev, 782 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data, 783 uint16_t *pactlen, uint32_t timeout, uint8_t flags) 784{ 785 int error; 786 787 error = pdev->methods->do_request_sync(pdev, 788 setup, data, pactlen, timeout, flags); 789 return (error); 790} 791 792int 793libusb20_dev_req_string_sync(struct libusb20_device *pdev, 794 uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) 795{ 796 struct LIBUSB20_CONTROL_SETUP_DECODED req; 797 int error; 798 int flags; 799 800 /* make sure memory is initialised */ 801 memset(ptr, 0, len); 802 803 if (len < 4) { 804 /* invalid length */ 805 return (LIBUSB20_ERROR_INVALID_PARAM); 806 } 807 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 808 809 /* 810 * We need to read the USB string in two steps else some USB 811 * devices will complain. 812 */ 813 req.bmRequestType = 814 LIBUSB20_REQUEST_TYPE_STANDARD | 815 LIBUSB20_RECIPIENT_DEVICE | 816 LIBUSB20_ENDPOINT_IN; 817 req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; 818 req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; 819 req.wIndex = langid; 820 req.wLength = 4; /* bytes */ 821 822 error = libusb20_dev_request_sync(pdev, &req, 823 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 824 if (error) { 825 /* try to request full string */ 826 req.wLength = 255; 827 flags = 0; 828 } else { 829 /* extract length and request full string */ 830 req.wLength = *(uint8_t *)ptr; 831 flags = LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK; 832 } 833 if (req.wLength > len) { 834 /* partial string read */ 835 req.wLength = len; 836 } 837 error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, flags); 838 if (error) 839 return (error); 840 841 if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) 842 return (LIBUSB20_ERROR_OTHER); 843 return (0); /* success */ 844} 845 846int 847libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev, 848 uint8_t str_index, void *ptr, uint16_t len) 849{ 850 char *buf; 851 int error; 852 uint16_t langid; 853 uint16_t n; 854 uint16_t i; 855 uint16_t c; 856 uint8_t temp[255]; 857 uint8_t swap; 858 859 /* the following code derives from the FreeBSD USB kernel */ 860 861 if ((len < 1) || (ptr == NULL)) { 862 /* too short buffer */ 863 return (LIBUSB20_ERROR_INVALID_PARAM); 864 } 865 error = libusb20_dev_req_string_sync(pdev, 866 0, 0, temp, sizeof(temp)); 867 if (error < 0) { 868 *(uint8_t *)ptr = 0; /* zero terminate */ 869 return (error); 870 } 871 langid = temp[2] | (temp[3] << 8); 872 873 error = libusb20_dev_req_string_sync(pdev, str_index, 874 langid, temp, sizeof(temp)); 875 if (error < 0) { 876 *(uint8_t *)ptr = 0; /* zero terminate */ 877 return (error); 878 } 879 if (temp[0] < 2) { 880 /* string length is too short */ 881 *(uint8_t *)ptr = 0; /* zero terminate */ 882 return (LIBUSB20_ERROR_OTHER); 883 } 884 /* reserve one byte for terminating zero */ 885 len--; 886 887 /* find maximum length */ 888 n = (temp[0] / 2) - 1; 889 if (n > len) { 890 n = len; 891 } 892 /* reset swap state */ 893 swap = 3; 894 895 /* setup output buffer pointer */ 896 buf = ptr; 897 898 /* convert and filter */ 899 for (i = 0; (i != n); i++) { 900 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8); 901 902 /* convert from Unicode, handle buggy strings */ 903 if (((c & 0xff00) == 0) && (swap & 1)) { 904 /* Little Endian, default */ 905 *buf = c; 906 swap = 1; 907 } else if (((c & 0x00ff) == 0) && (swap & 2)) { 908 /* Big Endian */ 909 *buf = c >> 8; 910 swap = 2; 911 } else { 912 /* skip invalid character */ 913 continue; 914 } 915 /* 916 * Filter by default - we don't allow greater and less than 917 * signs because they might confuse the dmesg printouts! 918 */ 919 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) { 920 /* skip invalid character */ 921 continue; 922 } 923 buf++; 924 } 925 *buf = 0; /* zero terminate string */ 926 927 return (0); 928} 929 930struct libusb20_config * 931libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) 932{ 933 struct libusb20_config *retval = NULL; 934 uint8_t *ptr; 935 uint16_t len; 936 uint8_t do_close; 937 int error; 938 939 /* 940 * Catch invalid configuration descriptor reads early on to 941 * avoid issues with devices that don't check for a valid USB 942 * configuration read request. 943 */ 944 if (configIndex >= pdev->ddesc.bNumConfigurations) 945 return (NULL); 946 947 if (!pdev->is_opened) { 948 error = libusb20_dev_open(pdev, 0); 949 if (error) { 950 return (NULL); 951 } 952 do_close = 1; 953 } else { 954 do_close = 0; 955 } 956 error = pdev->methods->get_config_desc_full(pdev, 957 &ptr, &len, configIndex); 958 959 if (error) { 960 goto done; 961 } 962 /* parse new config descriptor */ 963 retval = libusb20_parse_config_desc(ptr); 964 965 /* free config descriptor */ 966 free(ptr); 967 968done: 969 if (do_close) { 970 error = libusb20_dev_close(pdev); 971 } 972 return (retval); 973} 974 975struct libusb20_device * 976libusb20_dev_alloc(void) 977{ 978 struct libusb20_device *pdev; 979 980 pdev = malloc(sizeof(*pdev)); 981 if (pdev == NULL) { 982 return (NULL); 983 } 984 memset(pdev, 0, sizeof(*pdev)); 985 986 pdev->file = -1; 987 pdev->file_ctrl = -1; 988 pdev->methods = &libusb20_dummy_methods; 989 return (pdev); 990} 991 992uint8_t 993libusb20_dev_get_config_index(struct libusb20_device *pdev) 994{ 995 int error; 996 uint8_t cfg_index; 997 uint8_t do_close; 998 999 if (!pdev->is_opened) { 1000 error = libusb20_dev_open(pdev, 0); 1001 if (error == 0) { 1002 do_close = 1; 1003 } else { 1004 do_close = 0; 1005 } 1006 } else { 1007 do_close = 0; 1008 } 1009 1010 error = pdev->methods->get_config_index(pdev, &cfg_index); 1011 if (error) 1012 cfg_index = 0xFF; /* current config index */ 1013 if (do_close) { 1014 if (libusb20_dev_close(pdev)) { 1015 /* ignore */ 1016 } 1017 } 1018 return (cfg_index); 1019} 1020 1021uint8_t 1022libusb20_dev_get_mode(struct libusb20_device *pdev) 1023{ 1024 return (pdev->usb_mode); 1025} 1026 1027uint8_t 1028libusb20_dev_get_speed(struct libusb20_device *pdev) 1029{ 1030 return (pdev->usb_speed); 1031} 1032 1033int 1034libusb20_dev_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstats) 1035{ 1036 uint8_t do_close; 1037 int error; 1038 1039 if (!pdev->is_opened) { 1040 error = libusb20_dev_open(pdev, 0); 1041 if (error == 0) { 1042 do_close = 1; 1043 } else { 1044 do_close = 0; 1045 } 1046 } else { 1047 do_close = 0; 1048 } 1049 1050 error = pdev->methods->get_stats(pdev, pstats); 1051 1052 if (do_close) 1053 (void) libusb20_dev_close(pdev); 1054 1055 return (error); 1056} 1057 1058/* if this function returns an error, the device is gone */ 1059int 1060libusb20_dev_process(struct libusb20_device *pdev) 1061{ 1062 int error; 1063 1064 error = pdev->methods->process(pdev); 1065 return (error); 1066} 1067 1068void 1069libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout) 1070{ 1071 struct pollfd pfd[1]; 1072 1073 if (!pdev->is_opened) { 1074 return; 1075 } 1076 pfd[0].fd = pdev->file; 1077 pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 1078 pfd[0].revents = 0; 1079 1080 if (poll(pfd, 1, timeout)) { 1081 /* ignore any error */ 1082 } 1083 return; 1084} 1085 1086void 1087libusb20_dev_free(struct libusb20_device *pdev) 1088{ 1089 if (pdev == NULL) { 1090 /* be NULL safe */ 1091 return; 1092 } 1093 if (pdev->is_opened) { 1094 if (libusb20_dev_close(pdev)) { 1095 /* ignore any errors */ 1096 } 1097 } 1098 free(pdev); 1099 return; 1100} 1101 1102int 1103libusb20_dev_get_info(struct libusb20_device *pdev, 1104 struct usb_device_info *pinfo) 1105{ 1106 if (pinfo == NULL) 1107 return (LIBUSB20_ERROR_INVALID_PARAM); 1108 1109 return (pdev->beMethods->dev_get_info(pdev, pinfo)); 1110} 1111 1112const char * 1113libusb20_dev_get_backend_name(struct libusb20_device *pdev) 1114{ 1115 return (pdev->beMethods->get_backend_name()); 1116} 1117 1118const char * 1119libusb20_dev_get_desc(struct libusb20_device *pdev) 1120{ 1121 return (pdev->usb_desc); 1122} 1123 1124void 1125libusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 1126{ 1127 pdev->debug = debug; 1128 return; 1129} 1130 1131int 1132libusb20_dev_get_debug(struct libusb20_device *pdev) 1133{ 1134 return (pdev->debug); 1135} 1136 1137uint8_t 1138libusb20_dev_get_address(struct libusb20_device *pdev) 1139{ 1140 return (pdev->device_address); 1141} 1142 1143uint8_t 1144libusb20_dev_get_parent_address(struct libusb20_device *pdev) 1145{ 1146 return (pdev->parent_address); 1147} 1148 1149uint8_t 1150libusb20_dev_get_parent_port(struct libusb20_device *pdev) 1151{ 1152 return (pdev->parent_port); 1153} 1154 1155uint8_t 1156libusb20_dev_get_bus_number(struct libusb20_device *pdev) 1157{ 1158 return (pdev->bus_number); 1159} 1160 1161int 1162libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1163 uint8_t iface_index, char *buf, uint8_t len) 1164{ 1165 if ((buf == NULL) || (len == 0)) 1166 return (LIBUSB20_ERROR_INVALID_PARAM); 1167 1168 buf[0] = 0; /* set default string value */ 1169 1170 return (pdev->beMethods->dev_get_iface_desc( 1171 pdev, iface_index, buf, len)); 1172} 1173 1174/* USB backend operations */ 1175 1176int 1177libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1178 uint16_t quirk_index, struct libusb20_quirk *pq) 1179{ 1180 return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1181} 1182 1183int 1184libusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1185 uint16_t quirk_index, struct libusb20_quirk *pq) 1186{ 1187 return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1188} 1189 1190int 1191libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1192 struct libusb20_quirk *pq) 1193{ 1194 return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1195} 1196 1197int 1198libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1199 struct libusb20_quirk *pq) 1200{ 1201 return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1202} 1203 1204int 1205libusb20_be_set_template(struct libusb20_backend *pbe, int temp) 1206{ 1207 return (pbe->methods->root_set_template(pbe, temp)); 1208} 1209 1210int 1211libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp) 1212{ 1213 int temp; 1214 1215 if (ptemp == NULL) 1216 ptemp = &temp; 1217 1218 return (pbe->methods->root_get_template(pbe, ptemp)); 1219} 1220 1221struct libusb20_device * 1222libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1223{ 1224 if (pbe == NULL) { 1225 pdev = NULL; 1226 } else if (pdev == NULL) { 1227 pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1228 } else { 1229 pdev = TAILQ_NEXT(pdev, dev_entry); 1230 } 1231 return (pdev); 1232} 1233 1234struct libusb20_backend * 1235libusb20_be_alloc(const struct libusb20_backend_methods *methods) 1236{ 1237 struct libusb20_backend *pbe; 1238 1239 pbe = malloc(sizeof(*pbe)); 1240 if (pbe == NULL) { 1241 return (NULL); 1242 } 1243 memset(pbe, 0, sizeof(*pbe)); 1244 1245 TAILQ_INIT(&(pbe->usb_devs)); 1246 1247 pbe->methods = methods; /* set backend methods */ 1248 1249 /* do the initial device scan */ 1250 if (pbe->methods->init_backend) { 1251 pbe->methods->init_backend(pbe); 1252 } 1253 return (pbe); 1254} 1255 1256struct libusb20_backend * 1257libusb20_be_alloc_linux(void) 1258{ 1259 return (NULL); 1260} 1261 1262struct libusb20_backend * 1263libusb20_be_alloc_ugen20(void) 1264{ 1265 return (libusb20_be_alloc(&libusb20_ugen20_backend)); 1266} 1267 1268struct libusb20_backend * 1269libusb20_be_alloc_default(void) 1270{ 1271 struct libusb20_backend *pbe; 1272 1273#ifdef __linux__ 1274 pbe = libusb20_be_alloc_linux(); 1275 if (pbe) { 1276 return (pbe); 1277 } 1278#endif 1279 pbe = libusb20_be_alloc_ugen20(); 1280 if (pbe) { 1281 return (pbe); 1282 } 1283 return (NULL); /* no backend found */ 1284} 1285 1286void 1287libusb20_be_free(struct libusb20_backend *pbe) 1288{ 1289 struct libusb20_device *pdev; 1290 1291 if (pbe == NULL) { 1292 /* be NULL safe */ 1293 return; 1294 } 1295 while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1296 libusb20_be_dequeue_device(pbe, pdev); 1297 libusb20_dev_free(pdev); 1298 } 1299 if (pbe->methods->exit_backend) { 1300 pbe->methods->exit_backend(pbe); 1301 } 1302 /* free backend */ 1303 free(pbe); 1304} 1305 1306void 1307libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1308{ 1309 pdev->beMethods = pbe->methods; /* copy backend methods */ 1310 TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1311} 1312 1313void 1314libusb20_be_dequeue_device(struct libusb20_backend *pbe, 1315 struct libusb20_device *pdev) 1316{ 1317 TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1318} 1319 1320const char * 1321libusb20_strerror(int code) 1322{ 1323 switch (code) { 1324 case LIBUSB20_SUCCESS: 1325 return ("Success"); 1326 case LIBUSB20_ERROR_IO: 1327 return ("I/O error"); 1328 case LIBUSB20_ERROR_INVALID_PARAM: 1329 return ("Invalid parameter"); 1330 case LIBUSB20_ERROR_ACCESS: 1331 return ("Permissions error"); 1332 case LIBUSB20_ERROR_NO_DEVICE: 1333 return ("No device"); 1334 case LIBUSB20_ERROR_NOT_FOUND: 1335 return ("Not found"); 1336 case LIBUSB20_ERROR_BUSY: 1337 return ("Device busy"); 1338 case LIBUSB20_ERROR_TIMEOUT: 1339 return ("Timeout"); 1340 case LIBUSB20_ERROR_OVERFLOW: 1341 return ("Overflow"); 1342 case LIBUSB20_ERROR_PIPE: 1343 return ("Pipe error"); 1344 case LIBUSB20_ERROR_INTERRUPTED: 1345 return ("Interrupted"); 1346 case LIBUSB20_ERROR_NO_MEM: 1347 return ("Out of memory"); 1348 case LIBUSB20_ERROR_NOT_SUPPORTED: 1349 return ("Not supported"); 1350 case LIBUSB20_ERROR_OTHER: 1351 return ("Other error"); 1352 default: 1353 return ("Unknown error"); 1354 } 1355} 1356 1357const char * 1358libusb20_error_name(int code) 1359{ 1360 switch (code) { 1361 case LIBUSB20_SUCCESS: 1362 return ("LIBUSB20_SUCCESS"); 1363 case LIBUSB20_ERROR_IO: 1364 return ("LIBUSB20_ERROR_IO"); 1365 case LIBUSB20_ERROR_INVALID_PARAM: 1366 return ("LIBUSB20_ERROR_INVALID_PARAM"); 1367 case LIBUSB20_ERROR_ACCESS: 1368 return ("LIBUSB20_ERROR_ACCESS"); 1369 case LIBUSB20_ERROR_NO_DEVICE: 1370 return ("LIBUSB20_ERROR_NO_DEVICE"); 1371 case LIBUSB20_ERROR_NOT_FOUND: 1372 return ("LIBUSB20_ERROR_NOT_FOUND"); 1373 case LIBUSB20_ERROR_BUSY: 1374 return ("LIBUSB20_ERROR_BUSY"); 1375 case LIBUSB20_ERROR_TIMEOUT: 1376 return ("LIBUSB20_ERROR_TIMEOUT"); 1377 case LIBUSB20_ERROR_OVERFLOW: 1378 return ("LIBUSB20_ERROR_OVERFLOW"); 1379 case LIBUSB20_ERROR_PIPE: 1380 return ("LIBUSB20_ERROR_PIPE"); 1381 case LIBUSB20_ERROR_INTERRUPTED: 1382 return ("LIBUSB20_ERROR_INTERRUPTED"); 1383 case LIBUSB20_ERROR_NO_MEM: 1384 return ("LIBUSB20_ERROR_NO_MEM"); 1385 case LIBUSB20_ERROR_NOT_SUPPORTED: 1386 return ("LIBUSB20_ERROR_NOT_SUPPORTED"); 1387 case LIBUSB20_ERROR_OTHER: 1388 return ("LIBUSB20_ERROR_OTHER"); 1389 default: 1390 return ("LIBUSB20_ERROR_UNKNOWN"); 1391 } 1392} 1393