libusb20.c revision 256281
19948Sakulyakh/* $FreeBSD: stable/10/lib/libusb/libusb20.c 253339 2013-07-14 10:22:00Z hselasky $ */ 212747Srriggs/*- 39948Sakulyakh * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved. 49948Sakulyakh * 59948Sakulyakh * Redistribution and use in source and binary forms, with or without 69948Sakulyakh * modification, are permitted provided that the following conditions 79948Sakulyakh * are met: 89948Sakulyakh * 1. Redistributions of source code must retain the above copyright 99948Sakulyakh * notice, this list of conditions and the following disclaimer. 109948Sakulyakh * 2. Redistributions in binary form must reproduce the above copyright 119948Sakulyakh * notice, this list of conditions and the following disclaimer in the 129948Sakulyakh * documentation and/or other materials provided with the distribution. 139948Sakulyakh * 149948Sakulyakh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 159948Sakulyakh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169948Sakulyakh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 179948Sakulyakh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 189948Sakulyakh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 199948Sakulyakh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 209948Sakulyakh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 219948Sakulyakh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 229948Sakulyakh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 239948Sakulyakh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 249948Sakulyakh * SUCH DAMAGE. 259948Sakulyakh */ 269948Sakulyakh 279948Sakulyakh#ifdef LIBUSB_GLOBAL_INCLUDE_FILE 289948Sakulyakh#include LIBUSB_GLOBAL_INCLUDE_FILE 299948Sakulyakh#else 3011098Sdsamersoff#include <ctype.h> 3111833Sctornqvi#include <poll.h> 329948Sakulyakh#include <stdio.h> 339948Sakulyakh#include <stdlib.h> 349948Sakulyakh#include <string.h> 359948Sakulyakh#include <time.h> 369948Sakulyakh#include <sys/queue.h> 379948Sakulyakh#endif 389948Sakulyakh 399948Sakulyakh#include "libusb20.h" 409948Sakulyakh#include "libusb20_desc.h" 419948Sakulyakh#include "libusb20_int.h" 429948Sakulyakh 439948Sakulyakhstatic int 449948Sakulyakhdummy_int(void) 459948Sakulyakh{ 469948Sakulyakh return (LIBUSB20_ERROR_NOT_SUPPORTED); 479948Sakulyakh} 489948Sakulyakh 499948Sakulyakhstatic void 509948Sakulyakhdummy_void(void) 519948Sakulyakh{ 529948Sakulyakh return; 539948Sakulyakh} 549948Sakulyakh 559948Sakulyakhstatic void 569948Sakulyakhdummy_callback(struct libusb20_transfer *xfer) 579948Sakulyakh{ 589948Sakulyakh ; /* style fix */ 599948Sakulyakh switch (libusb20_tr_get_status(xfer)) { 609948Sakulyakh case LIBUSB20_TRANSFER_START: 619948Sakulyakh libusb20_tr_submit(xfer); 629948Sakulyakh break; 639948Sakulyakh default: 649948Sakulyakh /* complete or error */ 659948Sakulyakh break; 669948Sakulyakh } 679948Sakulyakh return; 689948Sakulyakh} 699948Sakulyakh 709948Sakulyakh#define dummy_get_config_desc_full (void *)dummy_int 719948Sakulyakh#define dummy_get_config_index (void *)dummy_int 729948Sakulyakh#define dummy_set_config_index (void *)dummy_int 739948Sakulyakh#define dummy_set_alt_index (void *)dummy_int 749948Sakulyakh#define dummy_reset_device (void *)dummy_int 759948Sakulyakh#define dummy_check_connected (void *)dummy_int 769948Sakulyakh#define dummy_set_power_mode (void *)dummy_int 779948Sakulyakh#define dummy_get_power_mode (void *)dummy_int 789948Sakulyakh#define dummy_get_port_path (void *)dummy_int 799948Sakulyakh#define dummy_get_power_usage (void *)dummy_int 809948Sakulyakh#define dummy_kernel_driver_active (void *)dummy_int 819948Sakulyakh#define dummy_detach_kernel_driver (void *)dummy_int 829948Sakulyakh#define dummy_do_request_sync (void *)dummy_int 839948Sakulyakh#define dummy_tr_open (void *)dummy_int 849948Sakulyakh#define dummy_tr_close (void *)dummy_int 859948Sakulyakh#define dummy_tr_clear_stall_sync (void *)dummy_int 869948Sakulyakh#define dummy_process (void *)dummy_int 879948Sakulyakh#define dummy_dev_info (void *)dummy_int 889948Sakulyakh#define dummy_dev_get_iface_driver (void *)dummy_int 899948Sakulyakh 9010135Sakulyakh#define dummy_tr_submit (void *)dummy_void 919948Sakulyakh#define dummy_tr_cancel_async (void *)dummy_void 929948Sakulyakh 939948Sakulyakhstatic const struct libusb20_device_methods libusb20_dummy_methods = { 949948Sakulyakh LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 959948Sakulyakh}; 969948Sakulyakh 979948Sakulyakhvoid 989948Sakulyakhlibusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 999948Sakulyakh{ 1009948Sakulyakh ; /* style fix */ 1019948Sakulyakh 1029948Sakulyakhrepeat: 1039948Sakulyakh 1049948Sakulyakh if (!xfer->is_pending) { 1059948Sakulyakh xfer->status = LIBUSB20_TRANSFER_START; 1069948Sakulyakh } else { 1079948Sakulyakh xfer->is_pending = 0; 10812747Srriggs } 1099948Sakulyakh 1109948Sakulyakh xfer->callback(xfer); 1119948Sakulyakh 1129948Sakulyakh if (xfer->is_restart) { 1139948Sakulyakh xfer->is_restart = 0; 1149948Sakulyakh goto repeat; 1159948Sakulyakh } 1169948Sakulyakh if (xfer->is_draining && 1179948Sakulyakh (!xfer->is_pending)) { 1189948Sakulyakh xfer->is_draining = 0; 1199948Sakulyakh xfer->status = LIBUSB20_TRANSFER_DRAINED; 1209948Sakulyakh xfer->callback(xfer); 1219948Sakulyakh } 1229948Sakulyakh return; 1239948Sakulyakh} 1249948Sakulyakh 1259948Sakulyakhint 1269948Sakulyakhlibusb20_tr_close(struct libusb20_transfer *xfer) 1279948Sakulyakh{ 1289948Sakulyakh int error; 1299948Sakulyakh 1309948Sakulyakh if (!xfer->is_opened) { 1319948Sakulyakh return (LIBUSB20_ERROR_OTHER); 1329948Sakulyakh } 1339948Sakulyakh error = xfer->pdev->methods->tr_close(xfer); 1349948Sakulyakh 1359948Sakulyakh if (xfer->pLength) { 1369948Sakulyakh free(xfer->pLength); 13710135Sakulyakh } 1389948Sakulyakh if (xfer->ppBuffer) { 1399948Sakulyakh free(xfer->ppBuffer); 1409948Sakulyakh } 1419948Sakulyakh /* reset variable fields in case the transfer is opened again */ 1429948Sakulyakh xfer->priv_sc0 = 0; 1439948Sakulyakh xfer->priv_sc1 = 0; 1449948Sakulyakh xfer->is_opened = 0; 1459948Sakulyakh xfer->is_pending = 0; 1469948Sakulyakh xfer->is_cancel = 0; 1479948Sakulyakh xfer->is_draining = 0; 1489948Sakulyakh xfer->is_restart = 0; 1499948Sakulyakh xfer->status = 0; 1509948Sakulyakh xfer->flags = 0; 1519948Sakulyakh xfer->nFrames = 0; 1529948Sakulyakh xfer->aFrames = 0; 1539948Sakulyakh xfer->timeout = 0; 1549948Sakulyakh xfer->maxFrames = 0; 1559948Sakulyakh xfer->maxTotalLength = 0; 1569948Sakulyakh xfer->maxPacketLen = 0; 1579948Sakulyakh return (error); 1589948Sakulyakh} 1599948Sakulyakh 1609948Sakulyakhint 1619948Sakulyakhlibusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 1629948Sakulyakh uint32_t MaxFrameCount, uint8_t ep_no) 1639948Sakulyakh{ 1649948Sakulyakh return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0)); 1659948Sakulyakh} 1669948Sakulyakh 1679948Sakulyakhint 16810135Sakulyakhlibusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 1699948Sakulyakh uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id) 1709948Sakulyakh{ 1719948Sakulyakh uint32_t size; 1729948Sakulyakh uint8_t pre_scale; 1739948Sakulyakh int error; 1749948Sakulyakh 1759948Sakulyakh if (xfer->is_opened) 1769948Sakulyakh return (LIBUSB20_ERROR_BUSY); 1779948Sakulyakh if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) { 1789948Sakulyakh MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE; 17910135Sakulyakh pre_scale = 1; 18010135Sakulyakh } else { 18110135Sakulyakh pre_scale = 0; 18210135Sakulyakh } 18310135Sakulyakh if (MaxFrameCount == 0) 18410135Sakulyakh return (LIBUSB20_ERROR_INVALID_PARAM); 18510135Sakulyakh 1869948Sakulyakh xfer->maxFrames = MaxFrameCount; 1879948Sakulyakh 1889948Sakulyakh size = MaxFrameCount * sizeof(xfer->pLength[0]); 1899948Sakulyakh xfer->pLength = malloc(size); 1909948Sakulyakh if (xfer->pLength == NULL) { 1919948Sakulyakh return (LIBUSB20_ERROR_NO_MEM); 1929948Sakulyakh } 1939948Sakulyakh memset(xfer->pLength, 0, size); 1949948Sakulyakh 1959948Sakulyakh size = MaxFrameCount * sizeof(xfer->ppBuffer[0]); 1969948Sakulyakh xfer->ppBuffer = malloc(size); 1979948Sakulyakh if (xfer->ppBuffer == NULL) { 1989948Sakulyakh free(xfer->pLength); 199 return (LIBUSB20_ERROR_NO_MEM); 200 } 201 memset(xfer->ppBuffer, 0, size); 202 203 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 204 MaxFrameCount, ep_no, stream_id, pre_scale); 205 206 if (error) { 207 free(xfer->ppBuffer); 208 free(xfer->pLength); 209 } else { 210 xfer->is_opened = 1; 211 } 212 return (error); 213} 214 215struct libusb20_transfer * 216libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex) 217{ 218 if (trIndex >= pdev->nTransfer) { 219 return (NULL); 220 } 221 return (pdev->pTransfer + trIndex); 222} 223 224uint32_t 225libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 226{ 227 return (xfer->aFrames); 228} 229 230uint16_t 231libusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 232{ 233 return (xfer->timeComplete); 234} 235 236uint32_t 237libusb20_tr_get_actual_length(struct libusb20_transfer *xfer) 238{ 239 uint32_t x; 240 uint32_t actlen = 0; 241 242 for (x = 0; x != xfer->aFrames; x++) { 243 actlen += xfer->pLength[x]; 244 } 245 return (actlen); 246} 247 248uint32_t 249libusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 250{ 251 return (xfer->maxFrames); 252} 253 254uint32_t 255libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer) 256{ 257 /* 258 * Special Case NOTE: If the packet multiplier is non-zero for 259 * High Speed USB, the value returned is equal to 260 * "wMaxPacketSize * multiplier" ! 261 */ 262 return (xfer->maxPacketLen); 263} 264 265uint32_t 266libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 267{ 268 return (xfer->maxTotalLength); 269} 270 271uint8_t 272libusb20_tr_get_status(struct libusb20_transfer *xfer) 273{ 274 return (xfer->status); 275} 276 277uint8_t 278libusb20_tr_pending(struct libusb20_transfer *xfer) 279{ 280 return (xfer->is_pending); 281} 282 283void * 284libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 285{ 286 return (xfer->priv_sc0); 287} 288 289void * 290libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 291{ 292 return (xfer->priv_sc1); 293} 294 295void 296libusb20_tr_stop(struct libusb20_transfer *xfer) 297{ 298 if (!xfer->is_opened) { 299 /* transfer is not opened */ 300 return; 301 } 302 if (!xfer->is_pending) { 303 /* transfer not pending */ 304 return; 305 } 306 if (xfer->is_cancel) { 307 /* already cancelling */ 308 return; 309 } 310 xfer->is_cancel = 1; /* we are cancelling */ 311 312 xfer->pdev->methods->tr_cancel_async(xfer); 313 return; 314} 315 316void 317libusb20_tr_drain(struct libusb20_transfer *xfer) 318{ 319 if (!xfer->is_opened) { 320 /* transfer is not opened */ 321 return; 322 } 323 /* make sure that we are cancelling */ 324 libusb20_tr_stop(xfer); 325 326 if (xfer->is_pending) { 327 xfer->is_draining = 1; 328 } 329 return; 330} 331 332void 333libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 334{ 335 xfer->pdev->methods->tr_clear_stall_sync(xfer); 336 return; 337} 338 339void 340libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 341{ 342 xfer->ppBuffer[frIndex] = libusb20_pass_ptr(buffer); 343 return; 344} 345 346void 347libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 348{ 349 xfer->callback = cb; 350 return; 351} 352 353void 354libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 355{ 356 xfer->flags = flags; 357 return; 358} 359 360uint32_t 361libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex) 362{ 363 return (xfer->pLength[frIndex]); 364} 365 366void 367libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 368{ 369 xfer->pLength[frIndex] = length; 370 return; 371} 372 373void 374libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 375{ 376 xfer->priv_sc0 = sc0; 377 return; 378} 379 380void 381libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 382{ 383 xfer->priv_sc1 = sc1; 384 return; 385} 386 387void 388libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 389{ 390 xfer->timeout = timeout; 391 return; 392} 393 394void 395libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames) 396{ 397 if (nFrames > xfer->maxFrames) { 398 /* should not happen */ 399 nFrames = xfer->maxFrames; 400 } 401 xfer->nFrames = nFrames; 402 return; 403} 404 405void 406libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 407{ 408 xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf); 409 xfer->pLength[0] = length; 410 xfer->timeout = timeout; 411 xfer->nFrames = 1; 412 return; 413} 414 415void 416libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout) 417{ 418 uint16_t len; 419 420 xfer->ppBuffer[0] = libusb20_pass_ptr(psetup); 421 xfer->pLength[0] = 8; /* fixed */ 422 xfer->timeout = timeout; 423 424 len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8); 425 426 if (len != 0) { 427 xfer->nFrames = 2; 428 xfer->ppBuffer[1] = libusb20_pass_ptr(pBuf); 429 xfer->pLength[1] = len; 430 } else { 431 xfer->nFrames = 1; 432 } 433 return; 434} 435 436void 437libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 438{ 439 xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf); 440 xfer->pLength[0] = length; 441 xfer->timeout = timeout; 442 xfer->nFrames = 1; 443 return; 444} 445 446void 447libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex) 448{ 449 if (frIndex >= xfer->maxFrames) { 450 /* should not happen */ 451 return; 452 } 453 xfer->ppBuffer[frIndex] = libusb20_pass_ptr(pBuf); 454 xfer->pLength[frIndex] = length; 455 return; 456} 457 458uint8_t 459libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer, 460 void *pbuf, uint32_t length, uint32_t *pactlen, 461 uint32_t timeout) 462{ 463 struct libusb20_device *pdev = xfer->pdev; 464 uint32_t transfer_max; 465 uint32_t transfer_act; 466 uint8_t retval; 467 468 /* set some sensible default value */ 469 if (pactlen != NULL) 470 *pactlen = 0; 471 472 /* check for error condition */ 473 if (libusb20_tr_pending(xfer)) 474 return (LIBUSB20_ERROR_OTHER); 475 476 do { 477 /* compute maximum transfer length */ 478 transfer_max = 479 libusb20_tr_get_max_total_length(xfer); 480 481 if (transfer_max > length) 482 transfer_max = length; 483 484 /* setup bulk or interrupt transfer */ 485 libusb20_tr_setup_bulk(xfer, pbuf, 486 transfer_max, timeout); 487 488 /* start the transfer */ 489 libusb20_tr_start(xfer); 490 491 /* wait for transfer completion */ 492 while (libusb20_dev_process(pdev) == 0) { 493 494 if (libusb20_tr_pending(xfer) == 0) 495 break; 496 497 libusb20_dev_wait_process(pdev, -1); 498 } 499 500 transfer_act = libusb20_tr_get_actual_length(xfer); 501 502 /* update actual length, if any */ 503 if (pactlen != NULL) 504 pactlen[0] += transfer_act; 505 506 /* check transfer status */ 507 retval = libusb20_tr_get_status(xfer); 508 if (retval) 509 break; 510 511 /* check for short transfer */ 512 if (transfer_act != transfer_max) 513 break; 514 515 /* update buffer pointer and length */ 516 pbuf = ((uint8_t *)pbuf) + transfer_max; 517 length = length - transfer_max; 518 519 } while (length != 0); 520 521 return (retval); 522} 523 524void 525libusb20_tr_submit(struct libusb20_transfer *xfer) 526{ 527 if (!xfer->is_opened) { 528 /* transfer is not opened */ 529 return; 530 } 531 if (xfer->is_pending) { 532 /* should not happen */ 533 return; 534 } 535 xfer->is_pending = 1; /* we are pending */ 536 xfer->is_cancel = 0; /* not cancelling */ 537 xfer->is_restart = 0; /* not restarting */ 538 539 xfer->pdev->methods->tr_submit(xfer); 540 return; 541} 542 543void 544libusb20_tr_start(struct libusb20_transfer *xfer) 545{ 546 if (!xfer->is_opened) { 547 /* transfer is not opened */ 548 return; 549 } 550 if (xfer->is_pending) { 551 if (xfer->is_cancel) { 552 /* cancelling - restart */ 553 xfer->is_restart = 1; 554 } 555 /* transfer not pending */ 556 return; 557 } 558 /* get into the callback */ 559 libusb20_tr_callback_wrapper(xfer); 560 return; 561} 562 563/* USB device operations */ 564 565int 566libusb20_dev_close(struct libusb20_device *pdev) 567{ 568 struct libusb20_transfer *xfer; 569 uint16_t x; 570 int error = 0; 571 572 if (!pdev->is_opened) { 573 return (LIBUSB20_ERROR_OTHER); 574 } 575 for (x = 0; x != pdev->nTransfer; x++) { 576 xfer = pdev->pTransfer + x; 577 578 if (!xfer->is_opened) { 579 /* transfer is not opened */ 580 continue; 581 } 582 583 libusb20_tr_drain(xfer); 584 585 libusb20_tr_close(xfer); 586 } 587 588 if (pdev->pTransfer != NULL) { 589 free(pdev->pTransfer); 590 pdev->pTransfer = NULL; 591 } 592 error = pdev->beMethods->close_device(pdev); 593 594 pdev->methods = &libusb20_dummy_methods; 595 596 pdev->is_opened = 0; 597 598 /* 599 * The following variable is only used by the libusb v0.1 600 * compat layer: 601 */ 602 pdev->claimed_interface = 0; 603 604 return (error); 605} 606 607int 608libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex) 609{ 610 int error; 611 612 error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex); 613 return (error); 614} 615 616struct LIBUSB20_DEVICE_DESC_DECODED * 617libusb20_dev_get_device_desc(struct libusb20_device *pdev) 618{ 619 return (&(pdev->ddesc)); 620} 621 622int 623libusb20_dev_get_fd(struct libusb20_device *pdev) 624{ 625 return (pdev->file); 626} 627 628int 629libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex) 630{ 631 int error; 632 633 error = pdev->methods->kernel_driver_active(pdev, ifaceIndex); 634 return (error); 635} 636 637int 638libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax) 639{ 640 struct libusb20_transfer *xfer; 641 uint32_t size; 642 uint16_t x; 643 int error; 644 645 if (pdev->is_opened) { 646 return (LIBUSB20_ERROR_BUSY); 647 } 648 if (nTransferMax >= 256) { 649 return (LIBUSB20_ERROR_INVALID_PARAM); 650 } else if (nTransferMax != 0) { 651 size = sizeof(pdev->pTransfer[0]) * nTransferMax; 652 pdev->pTransfer = malloc(size); 653 if (pdev->pTransfer == NULL) { 654 return (LIBUSB20_ERROR_NO_MEM); 655 } 656 memset(pdev->pTransfer, 0, size); 657 } 658 /* initialise all transfers */ 659 for (x = 0; x != nTransferMax; x++) { 660 661 xfer = pdev->pTransfer + x; 662 663 xfer->pdev = pdev; 664 xfer->trIndex = x; 665 xfer->callback = &dummy_callback; 666 } 667 668 /* set "nTransfer" early */ 669 pdev->nTransfer = nTransferMax; 670 671 error = pdev->beMethods->open_device(pdev, nTransferMax); 672 673 if (error) { 674 if (pdev->pTransfer != NULL) { 675 free(pdev->pTransfer); 676 pdev->pTransfer = NULL; 677 } 678 pdev->file = -1; 679 pdev->file_ctrl = -1; 680 pdev->nTransfer = 0; 681 } else { 682 pdev->is_opened = 1; 683 } 684 return (error); 685} 686 687int 688libusb20_dev_reset(struct libusb20_device *pdev) 689{ 690 int error; 691 692 error = pdev->methods->reset_device(pdev); 693 return (error); 694} 695 696int 697libusb20_dev_check_connected(struct libusb20_device *pdev) 698{ 699 int error; 700 701 error = pdev->methods->check_connected(pdev); 702 return (error); 703} 704 705int 706libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 707{ 708 int error; 709 710 error = pdev->methods->set_power_mode(pdev, power_mode); 711 return (error); 712} 713 714uint8_t 715libusb20_dev_get_power_mode(struct libusb20_device *pdev) 716{ 717 int error; 718 uint8_t power_mode; 719 720 error = pdev->methods->get_power_mode(pdev, &power_mode); 721 if (error) 722 power_mode = LIBUSB20_POWER_ON; /* fake power mode */ 723 return (power_mode); 724} 725 726int 727libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize) 728{ 729 return (pdev->methods->get_port_path(pdev, buf, bufsize)); 730} 731 732uint16_t 733libusb20_dev_get_power_usage(struct libusb20_device *pdev) 734{ 735 int error; 736 uint16_t power_usage; 737 738 error = pdev->methods->get_power_usage(pdev, &power_usage); 739 if (error) 740 power_usage = 0; 741 return (power_usage); 742} 743 744int 745libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) 746{ 747 int error; 748 749 error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex); 750 return (error); 751} 752 753int 754libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex) 755{ 756 int error; 757 758 error = pdev->methods->set_config_index(pdev, configIndex); 759 return (error); 760} 761 762int 763libusb20_dev_request_sync(struct libusb20_device *pdev, 764 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data, 765 uint16_t *pactlen, uint32_t timeout, uint8_t flags) 766{ 767 int error; 768 769 error = pdev->methods->do_request_sync(pdev, 770 setup, data, pactlen, timeout, flags); 771 return (error); 772} 773 774int 775libusb20_dev_req_string_sync(struct libusb20_device *pdev, 776 uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) 777{ 778 struct LIBUSB20_CONTROL_SETUP_DECODED req; 779 int error; 780 781 /* make sure memory is initialised */ 782 memset(ptr, 0, len); 783 784 if (len < 4) { 785 /* invalid length */ 786 return (LIBUSB20_ERROR_INVALID_PARAM); 787 } 788 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 789 790 /* 791 * We need to read the USB string in two steps else some USB 792 * devices will complain. 793 */ 794 req.bmRequestType = 795 LIBUSB20_REQUEST_TYPE_STANDARD | 796 LIBUSB20_RECIPIENT_DEVICE | 797 LIBUSB20_ENDPOINT_IN; 798 req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; 799 req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; 800 req.wIndex = langid; 801 req.wLength = 4; /* bytes */ 802 803 error = libusb20_dev_request_sync(pdev, &req, 804 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 805 if (error) { 806 return (error); 807 } 808 req.wLength = *(uint8_t *)ptr; /* bytes */ 809 if (req.wLength > len) { 810 /* partial string read */ 811 req.wLength = len; 812 } 813 error = libusb20_dev_request_sync(pdev, &req, 814 ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 815 816 if (error) { 817 return (error); 818 } 819 if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) { 820 return (LIBUSB20_ERROR_OTHER); 821 } 822 return (0); /* success */ 823} 824 825int 826libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev, 827 uint8_t str_index, void *ptr, uint16_t len) 828{ 829 char *buf; 830 int error; 831 uint16_t langid; 832 uint16_t n; 833 uint16_t i; 834 uint16_t c; 835 uint8_t temp[255]; 836 uint8_t swap; 837 838 /* the following code derives from the FreeBSD USB kernel */ 839 840 if ((len < 1) || (ptr == NULL)) { 841 /* too short buffer */ 842 return (LIBUSB20_ERROR_INVALID_PARAM); 843 } 844 error = libusb20_dev_req_string_sync(pdev, 845 0, 0, temp, sizeof(temp)); 846 if (error < 0) { 847 *(uint8_t *)ptr = 0; /* zero terminate */ 848 return (error); 849 } 850 langid = temp[2] | (temp[3] << 8); 851 852 error = libusb20_dev_req_string_sync(pdev, str_index, 853 langid, temp, sizeof(temp)); 854 if (error < 0) { 855 *(uint8_t *)ptr = 0; /* zero terminate */ 856 return (error); 857 } 858 if (temp[0] < 2) { 859 /* string length is too short */ 860 *(uint8_t *)ptr = 0; /* zero terminate */ 861 return (LIBUSB20_ERROR_OTHER); 862 } 863 /* reserve one byte for terminating zero */ 864 len--; 865 866 /* find maximum length */ 867 n = (temp[0] / 2) - 1; 868 if (n > len) { 869 n = len; 870 } 871 /* reset swap state */ 872 swap = 3; 873 874 /* setup output buffer pointer */ 875 buf = ptr; 876 877 /* convert and filter */ 878 for (i = 0; (i != n); i++) { 879 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8); 880 881 /* convert from Unicode, handle buggy strings */ 882 if (((c & 0xff00) == 0) && (swap & 1)) { 883 /* Little Endian, default */ 884 *buf = c; 885 swap = 1; 886 } else if (((c & 0x00ff) == 0) && (swap & 2)) { 887 /* Big Endian */ 888 *buf = c >> 8; 889 swap = 2; 890 } else { 891 /* skip invalid character */ 892 continue; 893 } 894 /* 895 * Filter by default - we don't allow greater and less than 896 * signs because they might confuse the dmesg printouts! 897 */ 898 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) { 899 /* skip invalid character */ 900 continue; 901 } 902 buf++; 903 } 904 *buf = 0; /* zero terminate string */ 905 906 return (0); 907} 908 909struct libusb20_config * 910libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) 911{ 912 struct libusb20_config *retval = NULL; 913 uint8_t *ptr; 914 uint16_t len; 915 uint8_t do_close; 916 int error; 917 918 if (!pdev->is_opened) { 919 error = libusb20_dev_open(pdev, 0); 920 if (error) { 921 return (NULL); 922 } 923 do_close = 1; 924 } else { 925 do_close = 0; 926 } 927 error = pdev->methods->get_config_desc_full(pdev, 928 &ptr, &len, configIndex); 929 930 if (error) { 931 goto done; 932 } 933 /* parse new config descriptor */ 934 retval = libusb20_parse_config_desc(ptr); 935 936 /* free config descriptor */ 937 free(ptr); 938 939done: 940 if (do_close) { 941 error = libusb20_dev_close(pdev); 942 } 943 return (retval); 944} 945 946struct libusb20_device * 947libusb20_dev_alloc(void) 948{ 949 struct libusb20_device *pdev; 950 951 pdev = malloc(sizeof(*pdev)); 952 if (pdev == NULL) { 953 return (NULL); 954 } 955 memset(pdev, 0, sizeof(*pdev)); 956 957 pdev->file = -1; 958 pdev->file_ctrl = -1; 959 pdev->methods = &libusb20_dummy_methods; 960 return (pdev); 961} 962 963uint8_t 964libusb20_dev_get_config_index(struct libusb20_device *pdev) 965{ 966 int error; 967 uint8_t cfg_index; 968 uint8_t do_close; 969 970 if (!pdev->is_opened) { 971 error = libusb20_dev_open(pdev, 0); 972 if (error == 0) { 973 do_close = 1; 974 } else { 975 do_close = 0; 976 } 977 } else { 978 do_close = 0; 979 } 980 981 error = pdev->methods->get_config_index(pdev, &cfg_index); 982 if (error) 983 cfg_index = 0xFF; /* current config index */ 984 if (do_close) { 985 if (libusb20_dev_close(pdev)) { 986 /* ignore */ 987 } 988 } 989 return (cfg_index); 990} 991 992uint8_t 993libusb20_dev_get_mode(struct libusb20_device *pdev) 994{ 995 return (pdev->usb_mode); 996} 997 998uint8_t 999libusb20_dev_get_speed(struct libusb20_device *pdev) 1000{ 1001 return (pdev->usb_speed); 1002} 1003 1004/* if this function returns an error, the device is gone */ 1005int 1006libusb20_dev_process(struct libusb20_device *pdev) 1007{ 1008 int error; 1009 1010 error = pdev->methods->process(pdev); 1011 return (error); 1012} 1013 1014void 1015libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout) 1016{ 1017 struct pollfd pfd[1]; 1018 1019 if (!pdev->is_opened) { 1020 return; 1021 } 1022 pfd[0].fd = pdev->file; 1023 pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 1024 pfd[0].revents = 0; 1025 1026 if (poll(pfd, 1, timeout)) { 1027 /* ignore any error */ 1028 } 1029 return; 1030} 1031 1032void 1033libusb20_dev_free(struct libusb20_device *pdev) 1034{ 1035 if (pdev == NULL) { 1036 /* be NULL safe */ 1037 return; 1038 } 1039 if (pdev->is_opened) { 1040 if (libusb20_dev_close(pdev)) { 1041 /* ignore any errors */ 1042 } 1043 } 1044 free(pdev); 1045 return; 1046} 1047 1048int 1049libusb20_dev_get_info(struct libusb20_device *pdev, 1050 struct usb_device_info *pinfo) 1051{ 1052 if (pinfo == NULL) 1053 return (LIBUSB20_ERROR_INVALID_PARAM); 1054 1055 return (pdev->beMethods->dev_get_info(pdev, pinfo)); 1056} 1057 1058const char * 1059libusb20_dev_get_backend_name(struct libusb20_device *pdev) 1060{ 1061 return (pdev->beMethods->get_backend_name()); 1062} 1063 1064const char * 1065libusb20_dev_get_desc(struct libusb20_device *pdev) 1066{ 1067 return (pdev->usb_desc); 1068} 1069 1070void 1071libusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 1072{ 1073 pdev->debug = debug; 1074 return; 1075} 1076 1077int 1078libusb20_dev_get_debug(struct libusb20_device *pdev) 1079{ 1080 return (pdev->debug); 1081} 1082 1083uint8_t 1084libusb20_dev_get_address(struct libusb20_device *pdev) 1085{ 1086 return (pdev->device_address); 1087} 1088 1089uint8_t 1090libusb20_dev_get_parent_address(struct libusb20_device *pdev) 1091{ 1092 return (pdev->parent_address); 1093} 1094 1095uint8_t 1096libusb20_dev_get_parent_port(struct libusb20_device *pdev) 1097{ 1098 return (pdev->parent_port); 1099} 1100 1101uint8_t 1102libusb20_dev_get_bus_number(struct libusb20_device *pdev) 1103{ 1104 return (pdev->bus_number); 1105} 1106 1107int 1108libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1109 uint8_t iface_index, char *buf, uint8_t len) 1110{ 1111 if ((buf == NULL) || (len == 0)) 1112 return (LIBUSB20_ERROR_INVALID_PARAM); 1113 1114 buf[0] = 0; /* set default string value */ 1115 1116 return (pdev->beMethods->dev_get_iface_desc( 1117 pdev, iface_index, buf, len)); 1118} 1119 1120/* USB backend operations */ 1121 1122int 1123libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1124 uint16_t quirk_index, struct libusb20_quirk *pq) 1125{ 1126 return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1127} 1128 1129int 1130libusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1131 uint16_t quirk_index, struct libusb20_quirk *pq) 1132{ 1133 return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1134} 1135 1136int 1137libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1138 struct libusb20_quirk *pq) 1139{ 1140 return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1141} 1142 1143int 1144libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1145 struct libusb20_quirk *pq) 1146{ 1147 return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1148} 1149 1150int 1151libusb20_be_set_template(struct libusb20_backend *pbe, int temp) 1152{ 1153 return (pbe->methods->root_set_template(pbe, temp)); 1154} 1155 1156int 1157libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp) 1158{ 1159 int temp; 1160 1161 if (ptemp == NULL) 1162 ptemp = &temp; 1163 1164 return (pbe->methods->root_get_template(pbe, ptemp)); 1165} 1166 1167struct libusb20_device * 1168libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1169{ 1170 if (pbe == NULL) { 1171 pdev = NULL; 1172 } else if (pdev == NULL) { 1173 pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1174 } else { 1175 pdev = TAILQ_NEXT(pdev, dev_entry); 1176 } 1177 return (pdev); 1178} 1179 1180struct libusb20_backend * 1181libusb20_be_alloc(const struct libusb20_backend_methods *methods) 1182{ 1183 struct libusb20_backend *pbe; 1184 1185 pbe = malloc(sizeof(*pbe)); 1186 if (pbe == NULL) { 1187 return (NULL); 1188 } 1189 memset(pbe, 0, sizeof(*pbe)); 1190 1191 TAILQ_INIT(&(pbe->usb_devs)); 1192 1193 pbe->methods = methods; /* set backend methods */ 1194 1195 /* do the initial device scan */ 1196 if (pbe->methods->init_backend) { 1197 pbe->methods->init_backend(pbe); 1198 } 1199 return (pbe); 1200} 1201 1202struct libusb20_backend * 1203libusb20_be_alloc_linux(void) 1204{ 1205 return (NULL); 1206} 1207 1208struct libusb20_backend * 1209libusb20_be_alloc_ugen20(void) 1210{ 1211 return (libusb20_be_alloc(&libusb20_ugen20_backend)); 1212} 1213 1214struct libusb20_backend * 1215libusb20_be_alloc_default(void) 1216{ 1217 struct libusb20_backend *pbe; 1218 1219#ifdef __linux__ 1220 pbe = libusb20_be_alloc_linux(); 1221 if (pbe) { 1222 return (pbe); 1223 } 1224#endif 1225 pbe = libusb20_be_alloc_ugen20(); 1226 if (pbe) { 1227 return (pbe); 1228 } 1229 return (NULL); /* no backend found */ 1230} 1231 1232void 1233libusb20_be_free(struct libusb20_backend *pbe) 1234{ 1235 struct libusb20_device *pdev; 1236 1237 if (pbe == NULL) { 1238 /* be NULL safe */ 1239 return; 1240 } 1241 while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1242 libusb20_be_dequeue_device(pbe, pdev); 1243 libusb20_dev_free(pdev); 1244 } 1245 if (pbe->methods->exit_backend) { 1246 pbe->methods->exit_backend(pbe); 1247 } 1248 /* free backend */ 1249 free(pbe); 1250} 1251 1252void 1253libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1254{ 1255 pdev->beMethods = pbe->methods; /* copy backend methods */ 1256 TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1257} 1258 1259void 1260libusb20_be_dequeue_device(struct libusb20_backend *pbe, 1261 struct libusb20_device *pdev) 1262{ 1263 TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1264} 1265 1266const char * 1267libusb20_strerror(int code) 1268{ 1269 switch (code) { 1270 case LIBUSB20_SUCCESS: 1271 return ("Success"); 1272 case LIBUSB20_ERROR_IO: 1273 return ("I/O error"); 1274 case LIBUSB20_ERROR_INVALID_PARAM: 1275 return ("Invalid parameter"); 1276 case LIBUSB20_ERROR_ACCESS: 1277 return ("Permissions error"); 1278 case LIBUSB20_ERROR_NO_DEVICE: 1279 return ("No device"); 1280 case LIBUSB20_ERROR_NOT_FOUND: 1281 return ("Not found"); 1282 case LIBUSB20_ERROR_BUSY: 1283 return ("Device busy"); 1284 case LIBUSB20_ERROR_TIMEOUT: 1285 return ("Timeout"); 1286 case LIBUSB20_ERROR_OVERFLOW: 1287 return ("Overflow"); 1288 case LIBUSB20_ERROR_PIPE: 1289 return ("Pipe error"); 1290 case LIBUSB20_ERROR_INTERRUPTED: 1291 return ("Interrupted"); 1292 case LIBUSB20_ERROR_NO_MEM: 1293 return ("Out of memory"); 1294 case LIBUSB20_ERROR_NOT_SUPPORTED: 1295 return ("Not supported"); 1296 case LIBUSB20_ERROR_OTHER: 1297 return ("Other error"); 1298 default: 1299 return ("Unknown error"); 1300 } 1301} 1302 1303const char * 1304libusb20_error_name(int code) 1305{ 1306 switch (code) { 1307 case LIBUSB20_SUCCESS: 1308 return ("LIBUSB20_SUCCESS"); 1309 case LIBUSB20_ERROR_IO: 1310 return ("LIBUSB20_ERROR_IO"); 1311 case LIBUSB20_ERROR_INVALID_PARAM: 1312 return ("LIBUSB20_ERROR_INVALID_PARAM"); 1313 case LIBUSB20_ERROR_ACCESS: 1314 return ("LIBUSB20_ERROR_ACCESS"); 1315 case LIBUSB20_ERROR_NO_DEVICE: 1316 return ("LIBUSB20_ERROR_NO_DEVICE"); 1317 case LIBUSB20_ERROR_NOT_FOUND: 1318 return ("LIBUSB20_ERROR_NOT_FOUND"); 1319 case LIBUSB20_ERROR_BUSY: 1320 return ("LIBUSB20_ERROR_BUSY"); 1321 case LIBUSB20_ERROR_TIMEOUT: 1322 return ("LIBUSB20_ERROR_TIMEOUT"); 1323 case LIBUSB20_ERROR_OVERFLOW: 1324 return ("LIBUSB20_ERROR_OVERFLOW"); 1325 case LIBUSB20_ERROR_PIPE: 1326 return ("LIBUSB20_ERROR_PIPE"); 1327 case LIBUSB20_ERROR_INTERRUPTED: 1328 return ("LIBUSB20_ERROR_INTERRUPTED"); 1329 case LIBUSB20_ERROR_NO_MEM: 1330 return ("LIBUSB20_ERROR_NO_MEM"); 1331 case LIBUSB20_ERROR_NOT_SUPPORTED: 1332 return ("LIBUSB20_ERROR_NOT_SUPPORTED"); 1333 case LIBUSB20_ERROR_OTHER: 1334 return ("LIBUSB20_ERROR_OTHER"); 1335 default: 1336 return ("LIBUSB20_ERROR_UNKNOWN"); 1337 } 1338} 1339