libusb10_io.c revision 203815
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10_io.c 203815 2010-02-13 09:45:50Z wkoszek $ */ 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 27203815Swkoszek#include <sys/queue.h> 28203815Swkoszek 29203815Swkoszek#include <errno.h> 30194676Sthompsa#include <poll.h> 31194676Sthompsa#include <pthread.h> 32203815Swkoszek#include <stdio.h> 33203815Swkoszek#include <stdlib.h> 34194676Sthompsa#include <time.h> 35203815Swkoszek#include <unistd.h> 36194676Sthompsa 37194676Sthompsa#include "libusb20.h" 38194676Sthompsa#include "libusb20_desc.h" 39194676Sthompsa#include "libusb20_int.h" 40194676Sthompsa#include "libusb.h" 41194676Sthompsa#include "libusb10.h" 42194676Sthompsa 43195957SalfredUNEXPORTED void 44195957Salfredlibusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, 45195957Salfred struct libusb20_device *pdev, int fd, short events) 46195560Sthompsa{ 47195560Sthompsa if (ctx == NULL) 48195957Salfred return; /* invalid */ 49195560Sthompsa 50195957Salfred if (pollfd->entry.tqe_prev != NULL) 51195957Salfred return; /* already queued */ 52195957Salfred 53195957Salfred if (fd < 0) 54195957Salfred return; /* invalid */ 55195957Salfred 56195957Salfred pollfd->pdev = pdev; 57195560Sthompsa pollfd->pollfd.fd = fd; 58195560Sthompsa pollfd->pollfd.events = events; 59195560Sthompsa 60195957Salfred CTX_LOCK(ctx); 61195957Salfred TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry); 62195957Salfred CTX_UNLOCK(ctx); 63195560Sthompsa 64195560Sthompsa if (ctx->fd_added_cb) 65195560Sthompsa ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); 66195560Sthompsa} 67195560Sthompsa 68195560SthompsaUNEXPORTED void 69195957Salfredlibusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd) 70195560Sthompsa{ 71195957Salfred if (ctx == NULL) 72195957Salfred return; /* invalid */ 73195560Sthompsa 74195957Salfred if (pollfd->entry.tqe_prev == NULL) 75195957Salfred return; /* already dequeued */ 76195560Sthompsa 77195957Salfred CTX_LOCK(ctx); 78195957Salfred TAILQ_REMOVE(&ctx->pollfds, pollfd, entry); 79195957Salfred pollfd->entry.tqe_prev = NULL; 80195957Salfred CTX_UNLOCK(ctx); 81195560Sthompsa 82195560Sthompsa if (ctx->fd_removed_cb) 83195957Salfred ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data); 84195560Sthompsa} 85195560Sthompsa 86195957Salfred/* This function must be called locked */ 87195560Sthompsa 88195957Salfredstatic int 89195957Salfredlibusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) 90195560Sthompsa{ 91195957Salfred struct libusb_device *dev; 92195957Salfred struct libusb20_device **ppdev; 93195957Salfred struct libusb_super_pollfd *pfd; 94195957Salfred struct pollfd *fds; 95195957Salfred struct libusb_super_transfer *sxfer; 96194676Sthompsa struct libusb_transfer *uxfer; 97194676Sthompsa nfds_t nfds; 98194676Sthompsa int timeout; 99194676Sthompsa int i; 100195957Salfred int err; 101194676Sthompsa 102195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); 103195957Salfred 104194676Sthompsa nfds = 0; 105195957Salfred i = 0; 106195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) 107195957Salfred nfds++; 108194676Sthompsa 109195560Sthompsa fds = alloca(sizeof(*fds) * nfds); 110194676Sthompsa if (fds == NULL) 111194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 112194676Sthompsa 113195957Salfred ppdev = alloca(sizeof(*ppdev) * nfds); 114195957Salfred if (ppdev == NULL) 115195957Salfred return (LIBUSB_ERROR_NO_MEM); 116195957Salfred 117195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) { 118195957Salfred fds[i].fd = pfd->pollfd.fd; 119195957Salfred fds[i].events = pfd->pollfd.events; 120195957Salfred fds[i].revents = 0; 121195957Salfred ppdev[i] = pfd->pdev; 122195957Salfred if (pfd->pdev != NULL) 123195957Salfred libusb_get_device(pfd->pdev)->refcnt++; 124194676Sthompsa i++; 125194676Sthompsa } 126194676Sthompsa 127195957Salfred if (tv == NULL) 128195957Salfred timeout = -1; 129195957Salfred else 130195957Salfred timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 131194676Sthompsa 132195957Salfred CTX_UNLOCK(ctx); 133195957Salfred err = poll(fds, nfds, timeout); 134195957Salfred CTX_LOCK(ctx); 135194676Sthompsa 136195957Salfred if ((err == -1) && (errno == EINTR)) 137195957Salfred err = LIBUSB_ERROR_INTERRUPTED; 138195957Salfred else if (err < 0) 139195957Salfred err = LIBUSB_ERROR_IO; 140194676Sthompsa 141195957Salfred if (err < 1) { 142195957Salfred for (i = 0; i != nfds; i++) { 143195957Salfred if (ppdev[i] != NULL) { 144195957Salfred CTX_UNLOCK(ctx); 145195957Salfred libusb_unref_device(libusb_get_device(ppdev[i])); 146195957Salfred CTX_LOCK(ctx); 147195957Salfred } 148194676Sthompsa } 149195957Salfred goto do_done; 150194676Sthompsa } 151195957Salfred for (i = 0; i != nfds; i++) { 152195957Salfred if (ppdev[i] != NULL) { 153195957Salfred dev = libusb_get_device(ppdev[i]); 154194676Sthompsa 155199055Sthompsa if (fds[i].revents == 0) 156199055Sthompsa err = 0; /* nothing to do */ 157199055Sthompsa else 158199055Sthompsa err = libusb20_dev_process(ppdev[i]); 159199055Sthompsa 160195957Salfred if (err) { 161195957Salfred /* cancel all transfers - device is gone */ 162195957Salfred libusb10_cancel_all_transfer(dev); 163199055Sthompsa 164199055Sthompsa /* remove USB device from polling loop */ 165195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 166195957Salfred } 167195957Salfred CTX_UNLOCK(ctx); 168195957Salfred libusb_unref_device(dev); 169195957Salfred CTX_LOCK(ctx); 170194676Sthompsa 171195957Salfred } else { 172195957Salfred uint8_t dummy; 173194676Sthompsa 174195957Salfred while (1) { 175195957Salfred if (read(fds[i].fd, &dummy, 1) != 1) 176195957Salfred break; 177195957Salfred } 178194676Sthompsa } 179195957Salfred } 180194676Sthompsa 181195957Salfred err = 0; 182194676Sthompsa 183195957Salfreddo_done: 184194676Sthompsa 185195957Salfred /* Do all done callbacks */ 186194676Sthompsa 187195957Salfred while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) { 188195957Salfred TAILQ_REMOVE(&ctx->tr_done, sxfer, entry); 189195957Salfred sxfer->entry.tqe_prev = NULL; 190194676Sthompsa 191195957Salfred ctx->tr_done_ref++; 192195957Salfred 193195957Salfred CTX_UNLOCK(ctx); 194195957Salfred 195195957Salfred uxfer = (struct libusb_transfer *)( 196195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 197195957Salfred 198195957Salfred if (uxfer->callback != NULL) 199195957Salfred (uxfer->callback) (uxfer); 200195957Salfred 201195957Salfred if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 202195957Salfred free(uxfer->buffer); 203195957Salfred 204195957Salfred if (uxfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER) 205195957Salfred libusb_free_transfer(uxfer); 206195957Salfred 207195957Salfred CTX_LOCK(ctx); 208195957Salfred 209195957Salfred ctx->tr_done_ref--; 210195957Salfred ctx->tr_done_gen++; 211194676Sthompsa } 212194676Sthompsa 213195957Salfred /* Wakeup other waiters */ 214195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 215194676Sthompsa 216195957Salfred return (err); 217194676Sthompsa} 218194676Sthompsa 219194676Sthompsa/* Polling and timing */ 220194676Sthompsa 221194676Sthompsaint 222195957Salfredlibusb_try_lock_events(libusb_context *ctx) 223194676Sthompsa{ 224195957Salfred int err; 225194676Sthompsa 226195957Salfred ctx = GET_CONTEXT(ctx); 227195957Salfred if (ctx == NULL) 228194676Sthompsa return (1); 229194676Sthompsa 230195957Salfred err = CTX_TRYLOCK(ctx); 231195957Salfred if (err) 232194676Sthompsa return (1); 233194676Sthompsa 234195957Salfred err = (ctx->ctx_handler != NO_THREAD); 235195957Salfred if (err) 236195957Salfred CTX_UNLOCK(ctx); 237195957Salfred else 238195957Salfred ctx->ctx_handler = pthread_self(); 239195957Salfred 240195957Salfred return (err); 241194676Sthompsa} 242194676Sthompsa 243194676Sthompsavoid 244195957Salfredlibusb_lock_events(libusb_context *ctx) 245194676Sthompsa{ 246195957Salfred ctx = GET_CONTEXT(ctx); 247195957Salfred CTX_LOCK(ctx); 248195957Salfred if (ctx->ctx_handler == NO_THREAD) 249195957Salfred ctx->ctx_handler = pthread_self(); 250194676Sthompsa} 251194676Sthompsa 252194676Sthompsavoid 253195957Salfredlibusb_unlock_events(libusb_context *ctx) 254194676Sthompsa{ 255195957Salfred ctx = GET_CONTEXT(ctx); 256195957Salfred if (ctx->ctx_handler == pthread_self()) { 257195957Salfred ctx->ctx_handler = NO_THREAD; 258195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 259195957Salfred } 260195957Salfred CTX_UNLOCK(ctx); 261194676Sthompsa} 262194676Sthompsa 263194676Sthompsaint 264195957Salfredlibusb_event_handling_ok(libusb_context *ctx) 265194676Sthompsa{ 266195957Salfred ctx = GET_CONTEXT(ctx); 267195957Salfred return (ctx->ctx_handler == pthread_self()); 268194676Sthompsa} 269194676Sthompsa 270194676Sthompsaint 271195957Salfredlibusb_event_handler_active(libusb_context *ctx) 272194676Sthompsa{ 273195957Salfred ctx = GET_CONTEXT(ctx); 274195957Salfred return (ctx->ctx_handler != NO_THREAD); 275194676Sthompsa} 276194676Sthompsa 277194676Sthompsavoid 278195957Salfredlibusb_lock_event_waiters(libusb_context *ctx) 279194676Sthompsa{ 280195957Salfred ctx = GET_CONTEXT(ctx); 281195957Salfred CTX_LOCK(ctx); 282194676Sthompsa} 283194676Sthompsa 284194676Sthompsavoid 285195957Salfredlibusb_unlock_event_waiters(libusb_context *ctx) 286194676Sthompsa{ 287195957Salfred ctx = GET_CONTEXT(ctx); 288195957Salfred CTX_UNLOCK(ctx); 289194676Sthompsa} 290194676Sthompsa 291194676Sthompsaint 292195957Salfredlibusb_wait_for_event(libusb_context *ctx, struct timeval *tv) 293194676Sthompsa{ 294194676Sthompsa struct timespec ts; 295195957Salfred int err; 296194676Sthompsa 297195957Salfred ctx = GET_CONTEXT(ctx); 298195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); 299194676Sthompsa 300194676Sthompsa if (tv == NULL) { 301195957Salfred pthread_cond_wait(&ctx->ctx_cond, 302195957Salfred &ctx->ctx_lock); 303194676Sthompsa return (0); 304194676Sthompsa } 305195957Salfred err = clock_gettime(CLOCK_REALTIME, &ts); 306195957Salfred if (err < 0) 307194676Sthompsa return (LIBUSB_ERROR_OTHER); 308194676Sthompsa 309194676Sthompsa ts.tv_sec = tv->tv_sec; 310194676Sthompsa ts.tv_nsec = tv->tv_usec * 1000; 311195957Salfred if (ts.tv_nsec >= 1000000000) { 312194676Sthompsa ts.tv_nsec -= 1000000000; 313194676Sthompsa ts.tv_sec++; 314194676Sthompsa } 315195957Salfred err = pthread_cond_timedwait(&ctx->ctx_cond, 316195957Salfred &ctx->ctx_lock, &ts); 317194676Sthompsa 318195957Salfred if (err == ETIMEDOUT) 319194676Sthompsa return (1); 320194676Sthompsa 321194676Sthompsa return (0); 322194676Sthompsa} 323194676Sthompsa 324194676Sthompsaint 325195957Salfredlibusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) 326194676Sthompsa{ 327195957Salfred int err; 328195957Salfred 329195957Salfred ctx = GET_CONTEXT(ctx); 330195957Salfred 331195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter"); 332194676Sthompsa 333195957Salfred libusb_lock_events(ctx); 334194676Sthompsa 335195957Salfred err = libusb_handle_events_locked(ctx, tv); 336194676Sthompsa 337195957Salfred libusb_unlock_events(ctx); 338194676Sthompsa 339195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave"); 340195957Salfred 341195957Salfred return (err); 342194676Sthompsa} 343194676Sthompsa 344194676Sthompsaint 345195957Salfredlibusb_handle_events(libusb_context *ctx) 346194676Sthompsa{ 347195957Salfred return (libusb_handle_events_timeout(ctx, NULL)); 348194676Sthompsa} 349194676Sthompsa 350194676Sthompsaint 351195957Salfredlibusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) 352194676Sthompsa{ 353195957Salfred int err; 354194676Sthompsa 355195957Salfred ctx = GET_CONTEXT(ctx); 356194676Sthompsa 357195957Salfred if (libusb_event_handling_ok(ctx)) { 358195957Salfred err = libusb10_handle_events_sub(ctx, tv); 359195957Salfred } else { 360195957Salfred libusb_wait_for_event(ctx, tv); 361195957Salfred err = 0; 362194676Sthompsa } 363195957Salfred return (err); 364194676Sthompsa} 365194676Sthompsa 366194676Sthompsaint 367195957Salfredlibusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) 368194676Sthompsa{ 369195957Salfred /* all timeouts are currently being done by the kernel */ 370195957Salfred timerclear(tv); 371195957Salfred return (0); 372194676Sthompsa} 373194676Sthompsa 374194676Sthompsavoid 375195957Salfredlibusb_set_pollfd_notifiers(libusb_context *ctx, 376194676Sthompsa libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, 377194676Sthompsa void *user_data) 378194676Sthompsa{ 379195957Salfred ctx = GET_CONTEXT(ctx); 380194676Sthompsa 381194676Sthompsa ctx->fd_added_cb = added_cb; 382194676Sthompsa ctx->fd_removed_cb = removed_cb; 383194676Sthompsa ctx->fd_cb_user_data = user_data; 384194676Sthompsa} 385194676Sthompsa 386194676Sthompsastruct libusb_pollfd ** 387195957Salfredlibusb_get_pollfds(libusb_context *ctx) 388194676Sthompsa{ 389195957Salfred struct libusb_super_pollfd *pollfd; 390194676Sthompsa libusb_pollfd **ret; 391194676Sthompsa int i; 392194676Sthompsa 393195957Salfred ctx = GET_CONTEXT(ctx); 394194676Sthompsa 395195957Salfred CTX_LOCK(ctx); 396195957Salfred 397194676Sthompsa i = 0; 398195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 399195957Salfred i++; 400194676Sthompsa 401195957Salfred ret = calloc(i + 1, sizeof(struct libusb_pollfd *)); 402195957Salfred if (ret == NULL) 403195957Salfred goto done; 404194676Sthompsa 405194676Sthompsa i = 0; 406195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 407195957Salfred ret[i++] = &pollfd->pollfd; 408194676Sthompsa ret[i] = NULL; 409194676Sthompsa 410195957Salfreddone: 411195957Salfred CTX_UNLOCK(ctx); 412194676Sthompsa return (ret); 413194676Sthompsa} 414194676Sthompsa 415194676Sthompsa 416194676Sthompsa/* Synchronous device I/O */ 417194676Sthompsa 418194676Sthompsaint 419195957Salfredlibusb_control_transfer(libusb_device_handle *devh, 420194676Sthompsa uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, 421195957Salfred uint8_t *data, uint16_t wLength, unsigned int timeout) 422194676Sthompsa{ 423195957Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 424195957Salfred int err; 425195957Salfred uint16_t actlen; 426194676Sthompsa 427195957Salfred if (devh == NULL) 428195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 429194676Sthompsa 430195957Salfred if ((wLength != 0) && (data == NULL)) 431195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 432194676Sthompsa 433195957Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 434194676Sthompsa 435195957Salfred req.bmRequestType = bmRequestType; 436195957Salfred req.bRequest = bRequest; 437195957Salfred req.wValue = wValue; 438195957Salfred req.wIndex = wIndex; 439195957Salfred req.wLength = wLength; 440194676Sthompsa 441195957Salfred err = libusb20_dev_request_sync(devh, &req, data, 442195957Salfred &actlen, timeout, 0); 443194676Sthompsa 444195957Salfred if (err == LIBUSB20_ERROR_PIPE) 445195957Salfred return (LIBUSB_ERROR_PIPE); 446195957Salfred else if (err == LIBUSB20_ERROR_TIMEOUT) 447195957Salfred return (LIBUSB_ERROR_TIMEOUT); 448195957Salfred else if (err) 449195957Salfred return (LIBUSB_ERROR_NO_DEVICE); 450194676Sthompsa 451195957Salfred return (actlen); 452195957Salfred} 453194676Sthompsa 454195957Salfredstatic void 455195957Salfredlibusb10_do_transfer_cb(struct libusb_transfer *transfer) 456195957Salfred{ 457195957Salfred libusb_context *ctx; 458195957Salfred int *pdone; 459194676Sthompsa 460195957Salfred ctx = GET_CONTEXT(NULL); 461194676Sthompsa 462195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); 463194676Sthompsa 464195957Salfred pdone = transfer->user_data; 465195957Salfred *pdone = 1; 466194676Sthompsa} 467194676Sthompsa 468195957Salfred/* 469195957Salfred * TODO: Replace the following function. Allocating and freeing on a 470195957Salfred * per-transfer basis is slow. --HPS 471195957Salfred */ 472194676Sthompsastatic int 473195957Salfredlibusb10_do_transfer(libusb_device_handle *devh, 474195957Salfred uint8_t endpoint, uint8_t *data, int length, 475194676Sthompsa int *transferred, unsigned int timeout, int type) 476194676Sthompsa{ 477195957Salfred libusb_context *ctx; 478194676Sthompsa struct libusb_transfer *xfer; 479195957Salfred volatile int complet; 480194676Sthompsa int ret; 481194676Sthompsa 482195957Salfred if (devh == NULL) 483195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 484194676Sthompsa 485195957Salfred if ((length != 0) && (data == NULL)) 486195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 487195957Salfred 488194676Sthompsa xfer = libusb_alloc_transfer(0); 489194676Sthompsa if (xfer == NULL) 490194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 491194676Sthompsa 492195957Salfred ctx = libusb_get_device(devh)->ctx; 493194676Sthompsa 494194676Sthompsa xfer->dev_handle = devh; 495194676Sthompsa xfer->endpoint = endpoint; 496194676Sthompsa xfer->type = type; 497194676Sthompsa xfer->timeout = timeout; 498194676Sthompsa xfer->buffer = data; 499194676Sthompsa xfer->length = length; 500195957Salfred xfer->user_data = (void *)&complet; 501195957Salfred xfer->callback = libusb10_do_transfer_cb; 502194676Sthompsa complet = 0; 503194676Sthompsa 504194676Sthompsa if ((ret = libusb_submit_transfer(xfer)) < 0) { 505194676Sthompsa libusb_free_transfer(xfer); 506194676Sthompsa return (ret); 507194676Sthompsa } 508194676Sthompsa while (complet == 0) { 509194676Sthompsa if ((ret = libusb_handle_events(ctx)) < 0) { 510194676Sthompsa libusb_cancel_transfer(xfer); 511195957Salfred usleep(1000); /* nice it */ 512194676Sthompsa } 513194676Sthompsa } 514194676Sthompsa 515194676Sthompsa *transferred = xfer->actual_length; 516195957Salfred 517194676Sthompsa switch (xfer->status) { 518194676Sthompsa case LIBUSB_TRANSFER_COMPLETED: 519195957Salfred ret = 0; 520194676Sthompsa break; 521194676Sthompsa case LIBUSB_TRANSFER_TIMED_OUT: 522195957Salfred ret = LIBUSB_ERROR_TIMEOUT; 523195957Salfred break; 524194676Sthompsa case LIBUSB_TRANSFER_OVERFLOW: 525195957Salfred ret = LIBUSB_ERROR_OVERFLOW; 526195957Salfred break; 527194676Sthompsa case LIBUSB_TRANSFER_STALL: 528195957Salfred ret = LIBUSB_ERROR_PIPE; 529195957Salfred break; 530194676Sthompsa case LIBUSB_TRANSFER_NO_DEVICE: 531195957Salfred ret = LIBUSB_ERROR_NO_DEVICE; 532194676Sthompsa break; 533194676Sthompsa default: 534194676Sthompsa ret = LIBUSB_ERROR_OTHER; 535195957Salfred break; 536194676Sthompsa } 537194676Sthompsa 538194676Sthompsa libusb_free_transfer(xfer); 539194676Sthompsa return (ret); 540194676Sthompsa} 541194676Sthompsa 542194676Sthompsaint 543195957Salfredlibusb_bulk_transfer(libusb_device_handle *devh, 544195957Salfred uint8_t endpoint, uint8_t *data, int length, 545194676Sthompsa int *transferred, unsigned int timeout) 546194676Sthompsa{ 547194676Sthompsa libusb_context *ctx; 548194676Sthompsa int ret; 549195957Salfred 550195957Salfred ctx = GET_CONTEXT(NULL); 551195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); 552194676Sthompsa 553195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 554194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_BULK); 555194676Sthompsa 556195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); 557194676Sthompsa return (ret); 558194676Sthompsa} 559194676Sthompsa 560194676Sthompsaint 561195957Salfredlibusb_interrupt_transfer(libusb_device_handle *devh, 562195957Salfred uint8_t endpoint, uint8_t *data, int length, 563194676Sthompsa int *transferred, unsigned int timeout) 564194676Sthompsa{ 565194676Sthompsa libusb_context *ctx; 566194676Sthompsa int ret; 567194676Sthompsa 568195957Salfred ctx = GET_CONTEXT(NULL); 569195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); 570194676Sthompsa 571195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 572194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); 573194676Sthompsa 574195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); 575194676Sthompsa return (ret); 576194676Sthompsa} 577199055Sthompsa 578199055Sthompsauint8_t * 579199055Sthompsalibusb_get_iso_packet_buffer(struct libusb_transfer *transfer, uint32_t index) 580199055Sthompsa{ 581199055Sthompsa uint8_t *ptr; 582199055Sthompsa uint32_t n; 583199055Sthompsa 584199055Sthompsa if (transfer->num_iso_packets < 0) 585199055Sthompsa return (NULL); 586199055Sthompsa 587199055Sthompsa if (index >= (uint32_t)transfer->num_iso_packets) 588199055Sthompsa return (NULL); 589199055Sthompsa 590199055Sthompsa ptr = transfer->buffer; 591199055Sthompsa if (ptr == NULL) 592199055Sthompsa return (NULL); 593199055Sthompsa 594199055Sthompsa for (n = 0; n != index; n++) { 595199055Sthompsa ptr += transfer->iso_packet_desc[n].length; 596199055Sthompsa } 597199055Sthompsa return (ptr); 598199055Sthompsa} 599199055Sthompsa 600199055Sthompsauint8_t * 601199055Sthompsalibusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, uint32_t index) 602199055Sthompsa{ 603199055Sthompsa uint8_t *ptr; 604199055Sthompsa 605199055Sthompsa if (transfer->num_iso_packets < 0) 606199055Sthompsa return (NULL); 607199055Sthompsa 608199055Sthompsa if (index >= (uint32_t)transfer->num_iso_packets) 609199055Sthompsa return (NULL); 610199055Sthompsa 611199055Sthompsa ptr = transfer->buffer; 612199055Sthompsa if (ptr == NULL) 613199055Sthompsa return (NULL); 614199055Sthompsa 615199055Sthompsa ptr += transfer->iso_packet_desc[0].length * index; 616199055Sthompsa 617199055Sthompsa return (ptr); 618199055Sthompsa} 619199055Sthompsa 620199055Sthompsavoid 621199055Sthompsalibusb_set_iso_packet_lengths(struct libusb_transfer *transfer, uint32_t length) 622199055Sthompsa{ 623199055Sthompsa int n; 624199055Sthompsa 625199055Sthompsa if (transfer->num_iso_packets < 0) 626199055Sthompsa return; 627199055Sthompsa 628199055Sthompsa for (n = 0; n != transfer->num_iso_packets; n++) 629199055Sthompsa transfer->iso_packet_desc[n].length = length; 630199055Sthompsa} 631199055Sthompsa 632199055Sthompsauint8_t * 633199055Sthompsalibusb_control_transfer_get_data(struct libusb_transfer *transfer) 634199055Sthompsa{ 635199055Sthompsa if (transfer->buffer == NULL) 636199055Sthompsa return (NULL); 637199055Sthompsa 638199055Sthompsa return (transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE); 639199055Sthompsa} 640199055Sthompsa 641199055Sthompsastruct libusb_control_setup * 642199055Sthompsalibusb_control_transfer_get_setup(struct libusb_transfer *transfer) 643199055Sthompsa{ 644199055Sthompsa return ((struct libusb_control_setup *)transfer->buffer); 645199055Sthompsa} 646199055Sthompsa 647199055Sthompsavoid 648199055Sthompsalibusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType, 649199055Sthompsa uint8_t bRequest, uint16_t wValue, 650199055Sthompsa uint16_t wIndex, uint16_t wLength) 651199055Sthompsa{ 652199055Sthompsa struct libusb_control_setup *req = (struct libusb_control_setup *)buf; 653199055Sthompsa 654199055Sthompsa /* The alignment is OK for all fields below. */ 655199055Sthompsa req->bmRequestType = bmRequestType; 656199055Sthompsa req->bRequest = bRequest; 657199055Sthompsa req->wValue = htole16(wValue); 658199055Sthompsa req->wIndex = htole16(wIndex); 659199055Sthompsa req->wLength = htole16(wLength); 660199055Sthompsa} 661199055Sthompsa 662199055Sthompsavoid 663199055Sthompsalibusb_fill_control_transfer(struct libusb_transfer *transfer, 664199055Sthompsa libusb_device_handle *devh, uint8_t *buf, 665199055Sthompsa libusb_transfer_cb_fn callback, void *user_data, 666199055Sthompsa uint32_t timeout) 667199055Sthompsa{ 668199055Sthompsa struct libusb_control_setup *setup = (struct libusb_control_setup *)buf; 669199055Sthompsa 670199055Sthompsa transfer->dev_handle = devh; 671199055Sthompsa transfer->endpoint = 0; 672199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; 673199055Sthompsa transfer->timeout = timeout; 674199055Sthompsa transfer->buffer = buf; 675199055Sthompsa if (setup != NULL) 676199055Sthompsa transfer->length = LIBUSB_CONTROL_SETUP_SIZE 677199055Sthompsa + le16toh(setup->wLength); 678199055Sthompsa else 679199055Sthompsa transfer->length = 0; 680199055Sthompsa transfer->user_data = user_data; 681199055Sthompsa transfer->callback = callback; 682199055Sthompsa 683199055Sthompsa} 684199055Sthompsa 685199055Sthompsavoid 686199055Sthompsalibusb_fill_bulk_transfer(struct libusb_transfer *transfer, 687199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 688199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 689199055Sthompsa uint32_t timeout) 690199055Sthompsa{ 691199055Sthompsa transfer->dev_handle = devh; 692199055Sthompsa transfer->endpoint = endpoint; 693199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_BULK; 694199055Sthompsa transfer->timeout = timeout; 695199055Sthompsa transfer->buffer = buf; 696199055Sthompsa transfer->length = length; 697199055Sthompsa transfer->user_data = user_data; 698199055Sthompsa transfer->callback = callback; 699199055Sthompsa} 700199055Sthompsa 701199055Sthompsavoid 702199055Sthompsalibusb_fill_interrupt_transfer(struct libusb_transfer *transfer, 703199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 704199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 705199055Sthompsa uint32_t timeout) 706199055Sthompsa{ 707199055Sthompsa transfer->dev_handle = devh; 708199055Sthompsa transfer->endpoint = endpoint; 709199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; 710199055Sthompsa transfer->timeout = timeout; 711199055Sthompsa transfer->buffer = buf; 712199055Sthompsa transfer->length = length; 713199055Sthompsa transfer->user_data = user_data; 714199055Sthompsa transfer->callback = callback; 715199055Sthompsa} 716199055Sthompsa 717199055Sthompsavoid 718199055Sthompsalibusb_fill_iso_transfer(struct libusb_transfer *transfer, 719199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 720199055Sthompsa int length, int npacket, libusb_transfer_cb_fn callback, 721199055Sthompsa void *user_data, uint32_t timeout) 722199055Sthompsa{ 723199055Sthompsa transfer->dev_handle = devh; 724199055Sthompsa transfer->endpoint = endpoint; 725199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; 726199055Sthompsa transfer->timeout = timeout; 727199055Sthompsa transfer->buffer = buf; 728199055Sthompsa transfer->length = length; 729199055Sthompsa transfer->num_iso_packets = npacket; 730199055Sthompsa transfer->user_data = user_data; 731199055Sthompsa transfer->callback = callback; 732199055Sthompsa} 733199055Sthompsa 734