libusb10_io.c revision 194676
1/* $FreeBSD: head/lib/libusb/libusb10_io.c 194676 2009-06-23 01:04:58Z thompsa $ */ 2/*- 3 * Copyright (c) 2009 Sylvestre Gallon. 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 <sys/queue.h> 28#include <stdlib.h> 29#include <unistd.h> 30#include <stdio.h> 31#include <poll.h> 32#include <pthread.h> 33#include <time.h> 34#include <errno.h> 35 36#include "libusb20.h" 37#include "libusb20_desc.h" 38#include "libusb20_int.h" 39#include "libusb.h" 40#include "libusb10.h" 41 42static int 43get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out) 44{ 45 struct timeval timeout; 46 int ret; 47 48 ret = libusb_get_next_timeout(ctx, &timeout); 49 50 if (ret) { 51 if (timerisset(&timeout) == 0) 52 return 1; 53 if (timercmp(&timeout, tv, <) != 0) 54 *out = timeout; 55 else 56 *out = *tv; 57 } else { 58 *out = *tv; 59 } 60 61 return (0); 62} 63 64static int 65handle_timeouts(struct libusb_context *ctx) 66{ 67 struct timespec sys_ts; 68 struct timeval sys_tv; 69 struct timeval *cur_tv; 70 struct usb_transfer *xfer; 71 struct libusb_transfer *uxfer; 72 int ret; 73 74 GET_CONTEXT(ctx); 75 ret = 0; 76 77 pthread_mutex_lock(&ctx->flying_transfers_lock); 78 if (USB_LIST_EMPTY(&ctx->flying_transfers)) 79 goto out; 80 81 ret = clock_gettime(CLOCK_MONOTONIC, &sys_ts); 82 TIMESPEC_TO_TIMEVAL(&sys_tv, &sys_ts); 83 84 LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) { 85 cur_tv = &xfer->timeout; 86 87 if (timerisset(cur_tv) == 0) 88 goto out; 89 90 if (xfer->flags & USB_TIMED_OUT) 91 continue; 92 93 if ((cur_tv->tv_sec > sys_tv.tv_sec) || (cur_tv->tv_sec == sys_tv.tv_sec && 94 cur_tv->tv_usec > sys_tv.tv_usec)) 95 goto out; 96 97 xfer->flags |= USB_TIMED_OUT; 98 uxfer = (libusb_transfer *) ((uint8_t *)xfer + 99 sizeof(struct usb_transfer)); 100 ret = libusb_cancel_transfer(uxfer); 101 } 102out: 103 pthread_mutex_unlock(&ctx->flying_transfers_lock); 104 return (ret); 105} 106 107static int 108handle_events(struct libusb_context *ctx, struct timeval *tv) 109{ 110 struct libusb_pollfd *tmppollfd; 111 struct libusb_device_handle *devh; 112 struct usb_pollfd *ipollfd; 113 struct usb_transfer *cur; 114 struct usb_transfer *cancel; 115 struct libusb_transfer *xfer; 116 struct pollfd *fds; 117 struct pollfd *tfds; 118 nfds_t nfds; 119 int tmpfd; 120 int tmp; 121 int ret; 122 int timeout; 123 int i; 124 125 GET_CONTEXT(ctx); 126 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events enter"); 127 128 nfds = 0; 129 i = -1; 130 131 pthread_mutex_lock(&ctx->pollfds_lock); 132 LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list) 133 nfds++; 134 135 fds = malloc(sizeof(*fds) * nfds); 136 if (fds == NULL) 137 return (LIBUSB_ERROR_NO_MEM); 138 139 LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list) { 140 tmppollfd = &ipollfd->pollfd; 141 tmpfd = tmppollfd->fd; 142 i++; 143 fds[i].fd = tmpfd; 144 fds[i].events = tmppollfd->events; 145 fds[i].revents = 0; 146 } 147 148 pthread_mutex_unlock(&ctx->pollfds_lock); 149 150 timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); 151 if (tv->tv_usec % 1000) 152 timeout++; 153 154 ret = poll(fds, nfds, timeout); 155 if (ret == 0) { 156 free(fds); 157 return (handle_timeouts(ctx)); 158 } else if (ret == -1 && errno == EINTR) { 159 free(fds); 160 return (LIBUSB_ERROR_INTERRUPTED); 161 } else if (ret < 0) { 162 free(fds); 163 return (LIBUSB_ERROR_IO); 164 } 165 166 if (fds[0].revents) { 167 if (ret == 1){ 168 ret = 0; 169 goto handled; 170 } else { 171 fds[0].revents = 0; 172 ret--; 173 } 174 } 175 176 pthread_mutex_lock(&ctx->open_devs_lock); 177 for (i = 0 ; i < nfds && ret > 0 ; i++) { 178 179 tfds = &fds[i]; 180 if (!tfds->revents) 181 continue; 182 183 ret--; 184 LIST_FOREACH_ENTRY(devh, &ctx->open_devs, list) { 185 if (libusb20_dev_get_fd(devh->os_priv) == tfds->fd) 186 break ; 187 } 188 189 if (tfds->revents & POLLERR) { 190 usb_remove_pollfd(ctx, libusb20_dev_get_fd(devh->os_priv)); 191 usb_handle_disconnect(devh); 192 continue ; 193 } 194 195 196 pthread_mutex_lock(&libusb20_lock); 197 dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20_PROCESS"); 198 ret = libusb20_dev_process(devh->os_priv); 199 pthread_mutex_unlock(&libusb20_lock); 200 201 202 if (ret == 0 || ret == LIBUSB20_ERROR_NO_DEVICE) 203 continue; 204 else if (ret < 0) 205 goto out; 206 } 207 208 ret = 0; 209out: 210 pthread_mutex_unlock(&ctx->open_devs_lock); 211 212handled: 213 free(fds); 214 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events leave"); 215 return ret; 216} 217 218/* Polling and timing */ 219 220int 221libusb_try_lock_events(libusb_context * ctx) 222{ 223 int ret; 224 225 GET_CONTEXT(ctx); 226 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events enter"); 227 228 pthread_mutex_lock(&ctx->pollfd_modify_lock); 229 ret = ctx->pollfd_modify; 230 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 231 232 if (ret != 0) 233 return (1); 234 235 ret = pthread_mutex_trylock(&ctx->events_lock); 236 237 if (ret != 0) 238 return (1); 239 240 ctx->event_handler_active = 1; 241 242 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events leave"); 243 return (0); 244} 245 246void 247libusb_lock_events(libusb_context * ctx) 248{ 249 GET_CONTEXT(ctx); 250 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events enter"); 251 252 pthread_mutex_lock(&ctx->events_lock); 253 ctx->event_handler_active = 1; 254 255 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events leave"); 256} 257 258void 259libusb_unlock_events(libusb_context * ctx) 260{ 261 GET_CONTEXT(ctx); 262 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events enter"); 263 264 ctx->event_handler_active = 0; 265 pthread_mutex_unlock(&ctx->events_lock); 266 267 pthread_mutex_lock(&ctx->event_waiters_lock); 268 pthread_cond_broadcast(&ctx->event_waiters_cond); 269 pthread_mutex_unlock(&ctx->event_waiters_lock); 270 271 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events leave"); 272} 273 274int 275libusb_event_handling_ok(libusb_context * ctx) 276{ 277 int ret; 278 279 GET_CONTEXT(ctx); 280 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok enter"); 281 282 pthread_mutex_lock(&ctx->pollfd_modify_lock); 283 ret = ctx->pollfd_modify; 284 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 285 286 if (ret != 0) 287 return (0); 288 289 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok leave"); 290 return (1); 291} 292 293int 294libusb_event_handler_active(libusb_context * ctx) 295{ 296 int ret; 297 298 GET_CONTEXT(ctx); 299 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active enter"); 300 301 pthread_mutex_lock(&ctx->pollfd_modify_lock); 302 ret = ctx->pollfd_modify; 303 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 304 305 if (ret != 0) 306 return (1); 307 308 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active leave"); 309 return (ctx->event_handler_active); 310} 311 312void 313libusb_lock_event_waiters(libusb_context * ctx) 314{ 315 GET_CONTEXT(ctx); 316 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters enter"); 317 318 pthread_mutex_lock(&ctx->event_waiters_lock); 319 320 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters leave"); 321} 322 323void 324libusb_unlock_event_waiters(libusb_context * ctx) 325{ 326 GET_CONTEXT(ctx); 327 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters enter"); 328 329 pthread_mutex_unlock(&ctx->event_waiters_lock); 330 331 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters leave"); 332} 333 334int 335libusb_wait_for_event(libusb_context * ctx, struct timeval *tv) 336{ 337 int ret; 338 struct timespec ts; 339 340 GET_CONTEXT(ctx); 341 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); 342 343 if (tv == NULL) { 344 pthread_cond_wait(&ctx->event_waiters_cond, 345 &ctx->event_waiters_lock); 346 return (0); 347 } 348 349 ret = clock_gettime(CLOCK_REALTIME, &ts); 350 if (ret < 0) 351 return (LIBUSB_ERROR_OTHER); 352 353 ts.tv_sec = tv->tv_sec; 354 ts.tv_nsec = tv->tv_usec * 1000; 355 if (ts.tv_nsec > 1000000000) { 356 ts.tv_nsec -= 1000000000; 357 ts.tv_sec++; 358 } 359 360 ret = pthread_cond_timedwait(&ctx->event_waiters_cond, 361 &ctx->event_waiters_lock, &ts); 362 363 if (ret == ETIMEDOUT) 364 return (1); 365 366 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event leave"); 367 return (0); 368} 369 370int 371libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv) 372{ 373 struct timeval timeout; 374 struct timeval poll_timeout; 375 int ret; 376 377 GET_CONTEXT(ctx); 378 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter"); 379 380 ret = get_next_timeout(ctx, tv, &poll_timeout); 381 if (ret != 0) { 382 return handle_timeouts(ctx); 383 } 384retry: 385 if (libusb_try_lock_events(ctx) == 0) { 386 ret = handle_events(ctx, &poll_timeout); 387 libusb_unlock_events(ctx); 388 return ret; 389 } 390 391 libusb_lock_event_waiters(ctx); 392 if (libusb_event_handler_active(ctx) == 0) { 393 libusb_unlock_event_waiters(ctx); 394 goto retry; 395 } 396 397 ret = libusb_wait_for_event(ctx, &poll_timeout); 398 libusb_unlock_event_waiters(ctx); 399 400 if (ret < 0) 401 return ret; 402 else if (ret == 1) 403 return (handle_timeouts(ctx)); 404 405 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave"); 406 return (0); 407} 408 409int 410libusb_handle_events(libusb_context * ctx) 411{ 412 struct timeval tv; 413 int ret; 414 415 GET_CONTEXT(ctx); 416 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events enter"); 417 418 tv.tv_sec = 2; 419 tv.tv_usec = 0; 420 ret = libusb_handle_events_timeout(ctx, &tv); 421 422 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events leave"); 423 return (ret); 424} 425 426int 427libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv) 428{ 429 int ret; 430 struct timeval poll_tv; 431 432 GET_CONTEXT(ctx); 433 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked enter"); 434 435 ret = get_next_timeout(ctx, tv, &poll_tv); 436 if (ret != 0) { 437 return handle_timeouts(ctx); 438 } 439 440 ret = handle_events(ctx, &poll_tv); 441 442 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked leave"); 443 return (ret); 444} 445 446int 447libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv) 448{ 449 struct usb_transfer *xfer; 450 struct timeval *next_tv; 451 struct timeval cur_tv; 452 struct timespec cur_ts; 453 int found; 454 int ret; 455 456 GET_CONTEXT(ctx); 457 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout enter"); 458 459 found = 0; 460 pthread_mutex_lock(&ctx->flying_transfers_lock); 461 if (USB_LIST_EMPTY(&ctx->flying_transfers)) { 462 pthread_mutex_unlock(&ctx->flying_transfers_lock); 463 return (0); 464 } 465 466 LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) { 467 if (!(xfer->flags & USB_TIMED_OUT)) { 468 found = 1; 469 break ; 470 } 471 } 472 pthread_mutex_unlock(&ctx->flying_transfers_lock); 473 474 if (found == 0) { 475 return 0; 476 } 477 478 next_tv = &xfer->timeout; 479 if (timerisset(next_tv) == 0) 480 return (0); 481 482 ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts); 483 if (ret < 0) 484 return (LIBUSB_ERROR_OTHER); 485 TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); 486 487 if (timercmp(&cur_tv, next_tv, >=) != 0) 488 timerclear(tv); 489 else 490 timersub(next_tv, &cur_tv, tv); 491 492 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout leave"); 493 return (1); 494} 495 496void 497libusb_set_pollfd_notifiers(libusb_context * ctx, 498 libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, 499 void *user_data) 500{ 501 GET_CONTEXT(ctx); 502 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers enter"); 503 504 ctx->fd_added_cb = added_cb; 505 ctx->fd_removed_cb = removed_cb; 506 ctx->fd_cb_user_data = user_data; 507 508 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers leave"); 509} 510 511struct libusb_pollfd ** 512libusb_get_pollfds(libusb_context * ctx) 513{ 514 struct usb_pollfd *pollfd; 515 libusb_pollfd **ret; 516 int i; 517 518 GET_CONTEXT(ctx); 519 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds enter"); 520 521 i = 0; 522 pthread_mutex_lock(&ctx->pollfds_lock); 523 LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list) 524 i++; 525 526 ret = calloc(i + 1 , sizeof(struct libusb_pollfd *)); 527 if (ret == NULL) { 528 pthread_mutex_unlock(&ctx->pollfds_lock); 529 return (ret); 530 } 531 532 i = 0; 533 LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list) 534 ret[i++] = (struct libusb_pollfd *) pollfd; 535 ret[i] = NULL; 536 537 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds leave"); 538 return (ret); 539} 540 541 542/* Synchronous device I/O */ 543 544static void ctrl_tr_cb(struct libusb_transfer *transfer) 545{ 546 libusb_context *ctx; 547 int *complet; 548 549 ctx = NULL; 550 GET_CONTEXT(ctx); 551 dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "CALLBACK ENTER"); 552 553 complet = transfer->user_data; 554 *complet = 1; 555} 556 557int 558libusb_control_transfer(libusb_device_handle * devh, 559 uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, 560 unsigned char *data, uint16_t wLength, unsigned int timeout) 561{ 562 struct libusb_transfer *xfer; 563 struct libusb_control_setup *ctr; 564 libusb_context *ctx; 565 unsigned char *buff; 566 int complet; 567 int ret; 568 569 ctx = devh->dev->ctx; 570 GET_CONTEXT(ctx); 571 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer enter"); 572 573 if (devh == NULL || data == NULL) 574 return (LIBUSB_ERROR_NO_MEM); 575 576 xfer = libusb_alloc_transfer(0); 577 if (xfer == NULL) 578 return (LIBUSB_ERROR_NO_MEM); 579 580 buff = malloc(sizeof(libusb_control_setup) + wLength); 581 if (buff == NULL) { 582 libusb_free_transfer(xfer); 583 return (LIBUSB_ERROR_NO_MEM); 584 } 585 586 ctr = (libusb_control_setup *)buff; 587 ctr->bmRequestType = bmRequestType; 588 ctr->bRequest = bRequest; 589 ctr->wValue = wValue; 590 ctr->wIndex = wIndex; 591 ctr->wLength = wLength; 592 if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) 593 memcpy(buff + sizeof(libusb_control_setup), data, wLength); 594 595 xfer->dev_handle = devh; 596 xfer->endpoint = 0; 597 xfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; 598 xfer->timeout = timeout; 599 xfer->buffer = buff; 600 xfer->length = sizeof(libusb_control_setup) + wLength; 601 xfer->user_data = &complet; 602 xfer->callback = ctrl_tr_cb; 603 xfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER; 604 complet = 0; 605 606 if ((ret = libusb_submit_transfer(xfer)) < 0) { 607 libusb_free_transfer(xfer); 608 return (ret); 609 } 610 611 while (complet == 0) 612 if ((ret = libusb_handle_events(ctx)) < 0) { 613 libusb_cancel_transfer(xfer); 614 while (complet == 0) 615 if (libusb_handle_events(ctx) < 0) { 616 break; 617 } 618 libusb_free_transfer(xfer); 619 return (ret); 620 } 621 622 623 if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) 624 memcpy(data, buff + sizeof(libusb_control_setup), wLength); 625 626 switch (xfer->status) { 627 case LIBUSB_TRANSFER_COMPLETED: 628 ret = xfer->actual_length; 629 break; 630 case LIBUSB_TRANSFER_TIMED_OUT: 631 case LIBUSB_TRANSFER_STALL: 632 case LIBUSB_TRANSFER_NO_DEVICE: 633 ret = xfer->status; 634 break; 635 default: 636 ret = LIBUSB_ERROR_OTHER; 637 } 638 libusb_free_transfer(xfer); 639 640 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer leave"); 641 return (ret); 642} 643 644static int 645do_transfer(struct libusb_device_handle *devh, 646 unsigned char endpoint, unsigned char *data, int length, 647 int *transferred, unsigned int timeout, int type) 648{ 649 struct libusb_transfer *xfer; 650 libusb_context *ctx; 651 int complet; 652 int ret; 653 654 if (devh == NULL || data == NULL) 655 return (LIBUSB_ERROR_NO_MEM); 656 657 xfer = libusb_alloc_transfer(0); 658 if (xfer == NULL) 659 return (LIBUSB_ERROR_NO_MEM); 660 661 ctx = devh->dev->ctx; 662 663 xfer->dev_handle = devh; 664 xfer->endpoint = endpoint; 665 xfer->type = type; 666 xfer->timeout = timeout; 667 xfer->buffer = data; 668 xfer->length = length; 669 xfer->user_data = &complet; 670 xfer->callback = ctrl_tr_cb; 671 complet = 0; 672 673 if ((ret = libusb_submit_transfer(xfer)) < 0) { 674 libusb_free_transfer(xfer); 675 return (ret); 676 } 677 678 while (complet == 0) { 679 if ((ret = libusb_handle_events(ctx)) < 0) { 680 libusb_cancel_transfer(xfer); 681 libusb_free_transfer(xfer); 682 while (complet == 0) { 683 if (libusb_handle_events(ctx) < 0) 684 break ; 685 } 686 return (ret); 687 } 688 } 689 690 *transferred = xfer->actual_length; 691 switch (xfer->status) { 692 case LIBUSB_TRANSFER_COMPLETED: 693 ret = xfer->actual_length; 694 break; 695 case LIBUSB_TRANSFER_TIMED_OUT: 696 case LIBUSB_TRANSFER_OVERFLOW: 697 case LIBUSB_TRANSFER_STALL: 698 case LIBUSB_TRANSFER_NO_DEVICE: 699 ret = xfer->status; 700 break; 701 default: 702 ret = LIBUSB_ERROR_OTHER; 703 } 704 705 libusb_free_transfer(xfer); 706 return (ret); 707} 708 709int 710libusb_bulk_transfer(struct libusb_device_handle *devh, 711 unsigned char endpoint, unsigned char *data, int length, 712 int *transferred, unsigned int timeout) 713{ 714 libusb_context *ctx; 715 int ret; 716 717 ctx = NULL; 718 GET_CONTEXT(ctx); 719 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); 720 721 ret = do_transfer(devh, endpoint, data, length, transferred, 722 timeout, LIBUSB_TRANSFER_TYPE_BULK); 723 724 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); 725 return (ret); 726} 727 728/* 729 * Need to fix xfer->type 730 */ 731int 732libusb_interrupt_transfer(struct libusb_device_handle *devh, 733 unsigned char endpoint, unsigned char *data, int length, 734 int *transferred, unsigned int timeout) 735{ 736 libusb_context *ctx; 737 int ret; 738 739 ctx = NULL; 740 GET_CONTEXT(ctx); 741 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); 742 743 ret = do_transfer(devh, endpoint, data, length, transferred, 744 timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); 745 746 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); 747 return (ret); 748} 749