libusb10_io.c revision 195957
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10_io.c 195957 2009-07-30 00:11:41Z alfred $ */ 2194676Sthompsa/*- 3194676Sthompsa * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. 4194676Sthompsa * 5194676Sthompsa * Redistribution and use in source and binary forms, with or without 6194676Sthompsa * modification, are permitted provided that the following conditions 7194676Sthompsa * are met: 8194676Sthompsa * 1. Redistributions of source code must retain the above copyright 9194676Sthompsa * notice, this list of conditions and the following disclaimer. 10194676Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 11194676Sthompsa * notice, this list of conditions and the following disclaimer in the 12194676Sthompsa * documentation and/or other materials provided with the distribution. 13194676Sthompsa * 14194676Sthompsa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15194676Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17194676Sthompsa * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18194676Sthompsa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19194676Sthompsa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20194676Sthompsa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21194676Sthompsa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22194676Sthompsa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23194676Sthompsa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24194676Sthompsa * SUCH DAMAGE. 25194676Sthompsa */ 26194676Sthompsa 27194676Sthompsa#include <stdlib.h> 28194676Sthompsa#include <unistd.h> 29194676Sthompsa#include <stdio.h> 30194676Sthompsa#include <poll.h> 31194676Sthompsa#include <pthread.h> 32194676Sthompsa#include <time.h> 33194676Sthompsa#include <errno.h> 34195957Salfred#include <sys/queue.h> 35194676Sthompsa 36194676Sthompsa#include "libusb20.h" 37194676Sthompsa#include "libusb20_desc.h" 38194676Sthompsa#include "libusb20_int.h" 39194676Sthompsa#include "libusb.h" 40194676Sthompsa#include "libusb10.h" 41194676Sthompsa 42195957SalfredUNEXPORTED void 43195957Salfredlibusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, 44195957Salfred struct libusb20_device *pdev, int fd, short events) 45195560Sthompsa{ 46195560Sthompsa if (ctx == NULL) 47195957Salfred return; /* invalid */ 48195560Sthompsa 49195957Salfred if (pollfd->entry.tqe_prev != NULL) 50195957Salfred return; /* already queued */ 51195957Salfred 52195957Salfred if (fd < 0) 53195957Salfred return; /* invalid */ 54195957Salfred 55195957Salfred pollfd->pdev = pdev; 56195560Sthompsa pollfd->pollfd.fd = fd; 57195560Sthompsa pollfd->pollfd.events = events; 58195560Sthompsa 59195957Salfred CTX_LOCK(ctx); 60195957Salfred TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry); 61195957Salfred CTX_UNLOCK(ctx); 62195560Sthompsa 63195560Sthompsa if (ctx->fd_added_cb) 64195560Sthompsa ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); 65195560Sthompsa} 66195560Sthompsa 67195560SthompsaUNEXPORTED void 68195957Salfredlibusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd) 69195560Sthompsa{ 70195957Salfred if (ctx == NULL) 71195957Salfred return; /* invalid */ 72195560Sthompsa 73195957Salfred if (pollfd->entry.tqe_prev == NULL) 74195957Salfred return; /* already dequeued */ 75195560Sthompsa 76195957Salfred CTX_LOCK(ctx); 77195957Salfred TAILQ_REMOVE(&ctx->pollfds, pollfd, entry); 78195957Salfred pollfd->entry.tqe_prev = NULL; 79195957Salfred CTX_UNLOCK(ctx); 80195560Sthompsa 81195560Sthompsa if (ctx->fd_removed_cb) 82195957Salfred ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data); 83195560Sthompsa} 84195560Sthompsa 85195957Salfred/* This function must be called locked */ 86195560Sthompsa 87195957Salfredstatic int 88195957Salfredlibusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) 89195560Sthompsa{ 90195957Salfred struct libusb_device *dev; 91195957Salfred struct libusb20_device **ppdev; 92195957Salfred struct libusb_super_pollfd *pfd; 93195957Salfred struct pollfd *fds; 94195957Salfred struct libusb_super_transfer *sxfer; 95194676Sthompsa struct libusb_transfer *uxfer; 96194676Sthompsa nfds_t nfds; 97194676Sthompsa int timeout; 98194676Sthompsa int i; 99195957Salfred int err; 100194676Sthompsa 101195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); 102195957Salfred 103194676Sthompsa nfds = 0; 104195957Salfred i = 0; 105195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) 106195957Salfred nfds++; 107194676Sthompsa 108195560Sthompsa fds = alloca(sizeof(*fds) * nfds); 109194676Sthompsa if (fds == NULL) 110194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 111194676Sthompsa 112195957Salfred ppdev = alloca(sizeof(*ppdev) * nfds); 113195957Salfred if (ppdev == NULL) 114195957Salfred return (LIBUSB_ERROR_NO_MEM); 115195957Salfred 116195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) { 117195957Salfred fds[i].fd = pfd->pollfd.fd; 118195957Salfred fds[i].events = pfd->pollfd.events; 119195957Salfred fds[i].revents = 0; 120195957Salfred ppdev[i] = pfd->pdev; 121195957Salfred if (pfd->pdev != NULL) 122195957Salfred libusb_get_device(pfd->pdev)->refcnt++; 123194676Sthompsa i++; 124194676Sthompsa } 125194676Sthompsa 126195957Salfred if (tv == NULL) 127195957Salfred timeout = -1; 128195957Salfred else 129195957Salfred timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 130194676Sthompsa 131195957Salfred CTX_UNLOCK(ctx); 132195957Salfred err = poll(fds, nfds, timeout); 133195957Salfred CTX_LOCK(ctx); 134194676Sthompsa 135195957Salfred if ((err == -1) && (errno == EINTR)) 136195957Salfred err = LIBUSB_ERROR_INTERRUPTED; 137195957Salfred else if (err < 0) 138195957Salfred err = LIBUSB_ERROR_IO; 139194676Sthompsa 140195957Salfred if (err < 1) { 141195957Salfred for (i = 0; i != nfds; i++) { 142195957Salfred if (ppdev[i] != NULL) { 143195957Salfred CTX_UNLOCK(ctx); 144195957Salfred libusb_unref_device(libusb_get_device(ppdev[i])); 145195957Salfred CTX_LOCK(ctx); 146195957Salfred } 147194676Sthompsa } 148195957Salfred goto do_done; 149194676Sthompsa } 150195957Salfred for (i = 0; i != nfds; i++) { 151195957Salfred if (fds[i].revents == 0) 152195957Salfred continue; 153195957Salfred if (ppdev[i] != NULL) { 154195957Salfred dev = libusb_get_device(ppdev[i]); 155194676Sthompsa 156195957Salfred err = libusb20_dev_process(ppdev[i]); 157195957Salfred if (err) { 158195957Salfred /* cancel all transfers - device is gone */ 159195957Salfred libusb10_cancel_all_transfer(dev); 160195957Salfred /* 161195957Salfred * make sure we don't go into an infinite 162195957Salfred * loop 163195957Salfred */ 164195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 165195957Salfred } 166195957Salfred CTX_UNLOCK(ctx); 167195957Salfred libusb_unref_device(dev); 168195957Salfred CTX_LOCK(ctx); 169194676Sthompsa 170195957Salfred } else { 171195957Salfred uint8_t dummy; 172194676Sthompsa 173195957Salfred while (1) { 174195957Salfred if (read(fds[i].fd, &dummy, 1) != 1) 175195957Salfred break; 176195957Salfred } 177194676Sthompsa } 178195957Salfred } 179194676Sthompsa 180195957Salfred err = 0; 181194676Sthompsa 182195957Salfreddo_done: 183194676Sthompsa 184195957Salfred /* Do all done callbacks */ 185194676Sthompsa 186195957Salfred while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) { 187195957Salfred TAILQ_REMOVE(&ctx->tr_done, sxfer, entry); 188195957Salfred sxfer->entry.tqe_prev = NULL; 189194676Sthompsa 190195957Salfred ctx->tr_done_ref++; 191195957Salfred 192195957Salfred CTX_UNLOCK(ctx); 193195957Salfred 194195957Salfred uxfer = (struct libusb_transfer *)( 195195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 196195957Salfred 197195957Salfred if (uxfer->callback != NULL) 198195957Salfred (uxfer->callback) (uxfer); 199195957Salfred 200195957Salfred if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 201195957Salfred free(uxfer->buffer); 202195957Salfred 203195957Salfred if (uxfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER) 204195957Salfred libusb_free_transfer(uxfer); 205195957Salfred 206195957Salfred CTX_LOCK(ctx); 207195957Salfred 208195957Salfred ctx->tr_done_ref--; 209195957Salfred ctx->tr_done_gen++; 210194676Sthompsa } 211194676Sthompsa 212195957Salfred /* Wakeup other waiters */ 213195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 214194676Sthompsa 215195957Salfred return (err); 216194676Sthompsa} 217194676Sthompsa 218194676Sthompsa/* Polling and timing */ 219194676Sthompsa 220194676Sthompsaint 221195957Salfredlibusb_try_lock_events(libusb_context *ctx) 222194676Sthompsa{ 223195957Salfred int err; 224194676Sthompsa 225195957Salfred ctx = GET_CONTEXT(ctx); 226195957Salfred if (ctx == NULL) 227194676Sthompsa return (1); 228194676Sthompsa 229195957Salfred err = CTX_TRYLOCK(ctx); 230195957Salfred if (err) 231194676Sthompsa return (1); 232194676Sthompsa 233195957Salfred err = (ctx->ctx_handler != NO_THREAD); 234195957Salfred if (err) 235195957Salfred CTX_UNLOCK(ctx); 236195957Salfred else 237195957Salfred ctx->ctx_handler = pthread_self(); 238195957Salfred 239195957Salfred return (err); 240194676Sthompsa} 241194676Sthompsa 242194676Sthompsavoid 243195957Salfredlibusb_lock_events(libusb_context *ctx) 244194676Sthompsa{ 245195957Salfred ctx = GET_CONTEXT(ctx); 246195957Salfred CTX_LOCK(ctx); 247195957Salfred if (ctx->ctx_handler == NO_THREAD) 248195957Salfred ctx->ctx_handler = pthread_self(); 249194676Sthompsa} 250194676Sthompsa 251194676Sthompsavoid 252195957Salfredlibusb_unlock_events(libusb_context *ctx) 253194676Sthompsa{ 254195957Salfred ctx = GET_CONTEXT(ctx); 255195957Salfred if (ctx->ctx_handler == pthread_self()) { 256195957Salfred ctx->ctx_handler = NO_THREAD; 257195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 258195957Salfred } 259195957Salfred CTX_UNLOCK(ctx); 260194676Sthompsa} 261194676Sthompsa 262194676Sthompsaint 263195957Salfredlibusb_event_handling_ok(libusb_context *ctx) 264194676Sthompsa{ 265195957Salfred ctx = GET_CONTEXT(ctx); 266195957Salfred return (ctx->ctx_handler == pthread_self()); 267194676Sthompsa} 268194676Sthompsa 269194676Sthompsaint 270195957Salfredlibusb_event_handler_active(libusb_context *ctx) 271194676Sthompsa{ 272195957Salfred ctx = GET_CONTEXT(ctx); 273195957Salfred return (ctx->ctx_handler != NO_THREAD); 274194676Sthompsa} 275194676Sthompsa 276194676Sthompsavoid 277195957Salfredlibusb_lock_event_waiters(libusb_context *ctx) 278194676Sthompsa{ 279195957Salfred ctx = GET_CONTEXT(ctx); 280195957Salfred CTX_LOCK(ctx); 281194676Sthompsa} 282194676Sthompsa 283194676Sthompsavoid 284195957Salfredlibusb_unlock_event_waiters(libusb_context *ctx) 285194676Sthompsa{ 286195957Salfred ctx = GET_CONTEXT(ctx); 287195957Salfred CTX_UNLOCK(ctx); 288194676Sthompsa} 289194676Sthompsa 290194676Sthompsaint 291195957Salfredlibusb_wait_for_event(libusb_context *ctx, struct timeval *tv) 292194676Sthompsa{ 293194676Sthompsa struct timespec ts; 294195957Salfred int err; 295194676Sthompsa 296195957Salfred ctx = GET_CONTEXT(ctx); 297195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); 298194676Sthompsa 299194676Sthompsa if (tv == NULL) { 300195957Salfred pthread_cond_wait(&ctx->ctx_cond, 301195957Salfred &ctx->ctx_lock); 302194676Sthompsa return (0); 303194676Sthompsa } 304195957Salfred err = clock_gettime(CLOCK_REALTIME, &ts); 305195957Salfred if (err < 0) 306194676Sthompsa return (LIBUSB_ERROR_OTHER); 307194676Sthompsa 308194676Sthompsa ts.tv_sec = tv->tv_sec; 309194676Sthompsa ts.tv_nsec = tv->tv_usec * 1000; 310195957Salfred if (ts.tv_nsec >= 1000000000) { 311194676Sthompsa ts.tv_nsec -= 1000000000; 312194676Sthompsa ts.tv_sec++; 313194676Sthompsa } 314195957Salfred err = pthread_cond_timedwait(&ctx->ctx_cond, 315195957Salfred &ctx->ctx_lock, &ts); 316194676Sthompsa 317195957Salfred if (err == ETIMEDOUT) 318194676Sthompsa return (1); 319194676Sthompsa 320194676Sthompsa return (0); 321194676Sthompsa} 322194676Sthompsa 323194676Sthompsaint 324195957Salfredlibusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) 325194676Sthompsa{ 326195957Salfred int err; 327195957Salfred 328195957Salfred ctx = GET_CONTEXT(ctx); 329195957Salfred 330195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter"); 331194676Sthompsa 332195957Salfred libusb_lock_events(ctx); 333194676Sthompsa 334195957Salfred err = libusb_handle_events_locked(ctx, tv); 335194676Sthompsa 336195957Salfred libusb_unlock_events(ctx); 337194676Sthompsa 338195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave"); 339195957Salfred 340195957Salfred return (err); 341194676Sthompsa} 342194676Sthompsa 343194676Sthompsaint 344195957Salfredlibusb_handle_events(libusb_context *ctx) 345194676Sthompsa{ 346195957Salfred return (libusb_handle_events_timeout(ctx, NULL)); 347194676Sthompsa} 348194676Sthompsa 349194676Sthompsaint 350195957Salfredlibusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) 351194676Sthompsa{ 352195957Salfred int err; 353194676Sthompsa 354195957Salfred ctx = GET_CONTEXT(ctx); 355194676Sthompsa 356195957Salfred if (libusb_event_handling_ok(ctx)) { 357195957Salfred err = libusb10_handle_events_sub(ctx, tv); 358195957Salfred } else { 359195957Salfred libusb_wait_for_event(ctx, tv); 360195957Salfred err = 0; 361194676Sthompsa } 362195957Salfred return (err); 363194676Sthompsa} 364194676Sthompsa 365194676Sthompsaint 366195957Salfredlibusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) 367194676Sthompsa{ 368195957Salfred /* all timeouts are currently being done by the kernel */ 369195957Salfred timerclear(tv); 370195957Salfred return (0); 371194676Sthompsa} 372194676Sthompsa 373194676Sthompsavoid 374195957Salfredlibusb_set_pollfd_notifiers(libusb_context *ctx, 375194676Sthompsa libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, 376194676Sthompsa void *user_data) 377194676Sthompsa{ 378195957Salfred ctx = GET_CONTEXT(ctx); 379194676Sthompsa 380194676Sthompsa ctx->fd_added_cb = added_cb; 381194676Sthompsa ctx->fd_removed_cb = removed_cb; 382194676Sthompsa ctx->fd_cb_user_data = user_data; 383194676Sthompsa} 384194676Sthompsa 385194676Sthompsastruct libusb_pollfd ** 386195957Salfredlibusb_get_pollfds(libusb_context *ctx) 387194676Sthompsa{ 388195957Salfred struct libusb_super_pollfd *pollfd; 389194676Sthompsa libusb_pollfd **ret; 390194676Sthompsa int i; 391194676Sthompsa 392195957Salfred ctx = GET_CONTEXT(ctx); 393194676Sthompsa 394195957Salfred CTX_LOCK(ctx); 395195957Salfred 396194676Sthompsa i = 0; 397195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 398195957Salfred i++; 399194676Sthompsa 400195957Salfred ret = calloc(i + 1, sizeof(struct libusb_pollfd *)); 401195957Salfred if (ret == NULL) 402195957Salfred goto done; 403194676Sthompsa 404194676Sthompsa i = 0; 405195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 406195957Salfred ret[i++] = &pollfd->pollfd; 407194676Sthompsa ret[i] = NULL; 408194676Sthompsa 409195957Salfreddone: 410195957Salfred CTX_UNLOCK(ctx); 411194676Sthompsa return (ret); 412194676Sthompsa} 413194676Sthompsa 414194676Sthompsa 415194676Sthompsa/* Synchronous device I/O */ 416194676Sthompsa 417194676Sthompsaint 418195957Salfredlibusb_control_transfer(libusb_device_handle *devh, 419194676Sthompsa uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, 420195957Salfred uint8_t *data, uint16_t wLength, unsigned int timeout) 421194676Sthompsa{ 422195957Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 423195957Salfred int err; 424195957Salfred uint16_t actlen; 425194676Sthompsa 426195957Salfred if (devh == NULL) 427195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 428194676Sthompsa 429195957Salfred if ((wLength != 0) && (data == NULL)) 430195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 431194676Sthompsa 432195957Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 433194676Sthompsa 434195957Salfred req.bmRequestType = bmRequestType; 435195957Salfred req.bRequest = bRequest; 436195957Salfred req.wValue = wValue; 437195957Salfred req.wIndex = wIndex; 438195957Salfred req.wLength = wLength; 439194676Sthompsa 440195957Salfred err = libusb20_dev_request_sync(devh, &req, data, 441195957Salfred &actlen, timeout, 0); 442194676Sthompsa 443195957Salfred if (err == LIBUSB20_ERROR_PIPE) 444195957Salfred return (LIBUSB_ERROR_PIPE); 445195957Salfred else if (err == LIBUSB20_ERROR_TIMEOUT) 446195957Salfred return (LIBUSB_ERROR_TIMEOUT); 447195957Salfred else if (err) 448195957Salfred return (LIBUSB_ERROR_NO_DEVICE); 449194676Sthompsa 450195957Salfred return (actlen); 451195957Salfred} 452194676Sthompsa 453195957Salfredstatic void 454195957Salfredlibusb10_do_transfer_cb(struct libusb_transfer *transfer) 455195957Salfred{ 456195957Salfred libusb_context *ctx; 457195957Salfred int *pdone; 458194676Sthompsa 459195957Salfred ctx = GET_CONTEXT(NULL); 460194676Sthompsa 461195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); 462194676Sthompsa 463195957Salfred pdone = transfer->user_data; 464195957Salfred *pdone = 1; 465194676Sthompsa} 466194676Sthompsa 467195957Salfred/* 468195957Salfred * TODO: Replace the following function. Allocating and freeing on a 469195957Salfred * per-transfer basis is slow. --HPS 470195957Salfred */ 471194676Sthompsastatic int 472195957Salfredlibusb10_do_transfer(libusb_device_handle *devh, 473195957Salfred uint8_t endpoint, uint8_t *data, int length, 474194676Sthompsa int *transferred, unsigned int timeout, int type) 475194676Sthompsa{ 476195957Salfred libusb_context *ctx; 477194676Sthompsa struct libusb_transfer *xfer; 478195957Salfred volatile int complet; 479194676Sthompsa int ret; 480194676Sthompsa 481195957Salfred if (devh == NULL) 482195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 483194676Sthompsa 484195957Salfred if ((length != 0) && (data == NULL)) 485195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 486195957Salfred 487194676Sthompsa xfer = libusb_alloc_transfer(0); 488194676Sthompsa if (xfer == NULL) 489194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 490194676Sthompsa 491195957Salfred ctx = libusb_get_device(devh)->ctx; 492194676Sthompsa 493194676Sthompsa xfer->dev_handle = devh; 494194676Sthompsa xfer->endpoint = endpoint; 495194676Sthompsa xfer->type = type; 496194676Sthompsa xfer->timeout = timeout; 497194676Sthompsa xfer->buffer = data; 498194676Sthompsa xfer->length = length; 499195957Salfred xfer->user_data = (void *)&complet; 500195957Salfred xfer->callback = libusb10_do_transfer_cb; 501194676Sthompsa complet = 0; 502194676Sthompsa 503194676Sthompsa if ((ret = libusb_submit_transfer(xfer)) < 0) { 504194676Sthompsa libusb_free_transfer(xfer); 505194676Sthompsa return (ret); 506194676Sthompsa } 507194676Sthompsa while (complet == 0) { 508194676Sthompsa if ((ret = libusb_handle_events(ctx)) < 0) { 509194676Sthompsa libusb_cancel_transfer(xfer); 510195957Salfred usleep(1000); /* nice it */ 511194676Sthompsa } 512194676Sthompsa } 513194676Sthompsa 514194676Sthompsa *transferred = xfer->actual_length; 515195957Salfred 516194676Sthompsa switch (xfer->status) { 517194676Sthompsa case LIBUSB_TRANSFER_COMPLETED: 518195957Salfred ret = 0; 519194676Sthompsa break; 520194676Sthompsa case LIBUSB_TRANSFER_TIMED_OUT: 521195957Salfred ret = LIBUSB_ERROR_TIMEOUT; 522195957Salfred break; 523194676Sthompsa case LIBUSB_TRANSFER_OVERFLOW: 524195957Salfred ret = LIBUSB_ERROR_OVERFLOW; 525195957Salfred break; 526194676Sthompsa case LIBUSB_TRANSFER_STALL: 527195957Salfred ret = LIBUSB_ERROR_PIPE; 528195957Salfred break; 529194676Sthompsa case LIBUSB_TRANSFER_NO_DEVICE: 530195957Salfred ret = LIBUSB_ERROR_NO_DEVICE; 531194676Sthompsa break; 532194676Sthompsa default: 533194676Sthompsa ret = LIBUSB_ERROR_OTHER; 534195957Salfred break; 535194676Sthompsa } 536194676Sthompsa 537194676Sthompsa libusb_free_transfer(xfer); 538194676Sthompsa return (ret); 539194676Sthompsa} 540194676Sthompsa 541194676Sthompsaint 542195957Salfredlibusb_bulk_transfer(libusb_device_handle *devh, 543195957Salfred uint8_t endpoint, uint8_t *data, int length, 544194676Sthompsa int *transferred, unsigned int timeout) 545194676Sthompsa{ 546194676Sthompsa libusb_context *ctx; 547194676Sthompsa int ret; 548195957Salfred 549195957Salfred ctx = GET_CONTEXT(NULL); 550195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); 551194676Sthompsa 552195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 553194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_BULK); 554194676Sthompsa 555195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); 556194676Sthompsa return (ret); 557194676Sthompsa} 558194676Sthompsa 559194676Sthompsaint 560195957Salfredlibusb_interrupt_transfer(libusb_device_handle *devh, 561195957Salfred uint8_t endpoint, uint8_t *data, int length, 562194676Sthompsa int *transferred, unsigned int timeout) 563194676Sthompsa{ 564194676Sthompsa libusb_context *ctx; 565194676Sthompsa int ret; 566194676Sthompsa 567195957Salfred ctx = GET_CONTEXT(NULL); 568195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); 569194676Sthompsa 570195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 571194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); 572194676Sthompsa 573195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); 574194676Sthompsa return (ret); 575194676Sthompsa} 576