libusb10_io.c revision 234491
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10_io.c 234491 2012-04-20 14:29:45Z hselasky $ */ 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 37208020Sthompsa#define libusb_device_handle libusb20_device 38208020Sthompsa 39194676Sthompsa#include "libusb20.h" 40194676Sthompsa#include "libusb20_desc.h" 41194676Sthompsa#include "libusb20_int.h" 42194676Sthompsa#include "libusb.h" 43194676Sthompsa#include "libusb10.h" 44194676Sthompsa 45195957SalfredUNEXPORTED void 46195957Salfredlibusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, 47195957Salfred struct libusb20_device *pdev, int fd, short events) 48195560Sthompsa{ 49195560Sthompsa if (ctx == NULL) 50195957Salfred return; /* invalid */ 51195560Sthompsa 52195957Salfred if (pollfd->entry.tqe_prev != NULL) 53195957Salfred return; /* already queued */ 54195957Salfred 55195957Salfred if (fd < 0) 56195957Salfred return; /* invalid */ 57195957Salfred 58195957Salfred pollfd->pdev = pdev; 59195560Sthompsa pollfd->pollfd.fd = fd; 60195560Sthompsa pollfd->pollfd.events = events; 61195560Sthompsa 62195957Salfred CTX_LOCK(ctx); 63195957Salfred TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry); 64195957Salfred CTX_UNLOCK(ctx); 65195560Sthompsa 66195560Sthompsa if (ctx->fd_added_cb) 67195560Sthompsa ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); 68195560Sthompsa} 69195560Sthompsa 70195560SthompsaUNEXPORTED void 71195957Salfredlibusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd) 72195560Sthompsa{ 73195957Salfred if (ctx == NULL) 74195957Salfred return; /* invalid */ 75195560Sthompsa 76195957Salfred if (pollfd->entry.tqe_prev == NULL) 77195957Salfred return; /* already dequeued */ 78195560Sthompsa 79195957Salfred CTX_LOCK(ctx); 80195957Salfred TAILQ_REMOVE(&ctx->pollfds, pollfd, entry); 81195957Salfred pollfd->entry.tqe_prev = NULL; 82195957Salfred CTX_UNLOCK(ctx); 83195560Sthompsa 84195560Sthompsa if (ctx->fd_removed_cb) 85195957Salfred ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data); 86195560Sthompsa} 87195560Sthompsa 88195957Salfred/* This function must be called locked */ 89195560Sthompsa 90195957Salfredstatic int 91195957Salfredlibusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) 92195560Sthompsa{ 93195957Salfred struct libusb_device *dev; 94195957Salfred struct libusb20_device **ppdev; 95195957Salfred struct libusb_super_pollfd *pfd; 96195957Salfred struct pollfd *fds; 97195957Salfred struct libusb_super_transfer *sxfer; 98194676Sthompsa struct libusb_transfer *uxfer; 99194676Sthompsa nfds_t nfds; 100194676Sthompsa int timeout; 101194676Sthompsa int i; 102195957Salfred int err; 103194676Sthompsa 104195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); 105195957Salfred 106194676Sthompsa nfds = 0; 107195957Salfred i = 0; 108195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) 109195957Salfred nfds++; 110194676Sthompsa 111195560Sthompsa fds = alloca(sizeof(*fds) * nfds); 112194676Sthompsa if (fds == NULL) 113194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 114194676Sthompsa 115195957Salfred ppdev = alloca(sizeof(*ppdev) * nfds); 116195957Salfred if (ppdev == NULL) 117195957Salfred return (LIBUSB_ERROR_NO_MEM); 118195957Salfred 119195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) { 120195957Salfred fds[i].fd = pfd->pollfd.fd; 121195957Salfred fds[i].events = pfd->pollfd.events; 122195957Salfred fds[i].revents = 0; 123195957Salfred ppdev[i] = pfd->pdev; 124195957Salfred if (pfd->pdev != NULL) 125195957Salfred libusb_get_device(pfd->pdev)->refcnt++; 126194676Sthompsa i++; 127194676Sthompsa } 128194676Sthompsa 129195957Salfred if (tv == NULL) 130195957Salfred timeout = -1; 131195957Salfred else 132195957Salfred timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 133194676Sthompsa 134195957Salfred CTX_UNLOCK(ctx); 135195957Salfred err = poll(fds, nfds, timeout); 136195957Salfred CTX_LOCK(ctx); 137194676Sthompsa 138195957Salfred if ((err == -1) && (errno == EINTR)) 139195957Salfred err = LIBUSB_ERROR_INTERRUPTED; 140195957Salfred else if (err < 0) 141195957Salfred err = LIBUSB_ERROR_IO; 142194676Sthompsa 143195957Salfred if (err < 1) { 144213849Shselasky for (i = 0; i != (int)nfds; i++) { 145195957Salfred if (ppdev[i] != NULL) { 146195957Salfred CTX_UNLOCK(ctx); 147195957Salfred libusb_unref_device(libusb_get_device(ppdev[i])); 148195957Salfred CTX_LOCK(ctx); 149195957Salfred } 150194676Sthompsa } 151195957Salfred goto do_done; 152194676Sthompsa } 153213849Shselasky for (i = 0; i != (int)nfds; i++) { 154195957Salfred if (ppdev[i] != NULL) { 155195957Salfred dev = libusb_get_device(ppdev[i]); 156194676Sthompsa 157199055Sthompsa if (fds[i].revents == 0) 158199055Sthompsa err = 0; /* nothing to do */ 159199055Sthompsa else 160199055Sthompsa err = libusb20_dev_process(ppdev[i]); 161199055Sthompsa 162195957Salfred if (err) { 163195957Salfred /* cancel all transfers - device is gone */ 164195957Salfred libusb10_cancel_all_transfer(dev); 165199055Sthompsa 166199055Sthompsa /* remove USB device from polling loop */ 167195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 168195957Salfred } 169195957Salfred CTX_UNLOCK(ctx); 170195957Salfred libusb_unref_device(dev); 171195957Salfred CTX_LOCK(ctx); 172194676Sthompsa 173195957Salfred } else { 174195957Salfred uint8_t dummy; 175194676Sthompsa 176195957Salfred while (1) { 177195957Salfred if (read(fds[i].fd, &dummy, 1) != 1) 178195957Salfred break; 179195957Salfred } 180194676Sthompsa } 181195957Salfred } 182194676Sthompsa 183195957Salfred err = 0; 184194676Sthompsa 185195957Salfreddo_done: 186194676Sthompsa 187195957Salfred /* Do all done callbacks */ 188194676Sthompsa 189195957Salfred while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) { 190215253Shselasky uint8_t flags; 191215253Shselasky 192195957Salfred TAILQ_REMOVE(&ctx->tr_done, sxfer, entry); 193195957Salfred sxfer->entry.tqe_prev = NULL; 194194676Sthompsa 195195957Salfred ctx->tr_done_ref++; 196195957Salfred 197195957Salfred CTX_UNLOCK(ctx); 198195957Salfred 199195957Salfred uxfer = (struct libusb_transfer *)( 200195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 201195957Salfred 202215253Shselasky /* Allow the callback to free the transfer itself. */ 203215253Shselasky flags = uxfer->flags; 204215253Shselasky 205195957Salfred if (uxfer->callback != NULL) 206195957Salfred (uxfer->callback) (uxfer); 207195957Salfred 208215253Shselasky /* Check if the USB transfer should be automatically freed. */ 209215253Shselasky if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) 210195957Salfred libusb_free_transfer(uxfer); 211195957Salfred 212195957Salfred CTX_LOCK(ctx); 213195957Salfred 214195957Salfred ctx->tr_done_ref--; 215195957Salfred ctx->tr_done_gen++; 216194676Sthompsa } 217194676Sthompsa 218195957Salfred /* Wakeup other waiters */ 219195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 220194676Sthompsa 221195957Salfred return (err); 222194676Sthompsa} 223194676Sthompsa 224194676Sthompsa/* Polling and timing */ 225194676Sthompsa 226194676Sthompsaint 227195957Salfredlibusb_try_lock_events(libusb_context *ctx) 228194676Sthompsa{ 229195957Salfred int err; 230194676Sthompsa 231195957Salfred ctx = GET_CONTEXT(ctx); 232195957Salfred if (ctx == NULL) 233194676Sthompsa return (1); 234194676Sthompsa 235195957Salfred err = CTX_TRYLOCK(ctx); 236195957Salfred if (err) 237194676Sthompsa return (1); 238194676Sthompsa 239195957Salfred err = (ctx->ctx_handler != NO_THREAD); 240195957Salfred if (err) 241195957Salfred CTX_UNLOCK(ctx); 242195957Salfred else 243195957Salfred ctx->ctx_handler = pthread_self(); 244195957Salfred 245195957Salfred return (err); 246194676Sthompsa} 247194676Sthompsa 248194676Sthompsavoid 249195957Salfredlibusb_lock_events(libusb_context *ctx) 250194676Sthompsa{ 251195957Salfred ctx = GET_CONTEXT(ctx); 252195957Salfred CTX_LOCK(ctx); 253195957Salfred if (ctx->ctx_handler == NO_THREAD) 254195957Salfred ctx->ctx_handler = pthread_self(); 255194676Sthompsa} 256194676Sthompsa 257194676Sthompsavoid 258195957Salfredlibusb_unlock_events(libusb_context *ctx) 259194676Sthompsa{ 260195957Salfred ctx = GET_CONTEXT(ctx); 261195957Salfred if (ctx->ctx_handler == pthread_self()) { 262195957Salfred ctx->ctx_handler = NO_THREAD; 263195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 264195957Salfred } 265195957Salfred CTX_UNLOCK(ctx); 266194676Sthompsa} 267194676Sthompsa 268194676Sthompsaint 269195957Salfredlibusb_event_handling_ok(libusb_context *ctx) 270194676Sthompsa{ 271195957Salfred ctx = GET_CONTEXT(ctx); 272195957Salfred return (ctx->ctx_handler == pthread_self()); 273194676Sthompsa} 274194676Sthompsa 275194676Sthompsaint 276195957Salfredlibusb_event_handler_active(libusb_context *ctx) 277194676Sthompsa{ 278195957Salfred ctx = GET_CONTEXT(ctx); 279195957Salfred return (ctx->ctx_handler != NO_THREAD); 280194676Sthompsa} 281194676Sthompsa 282194676Sthompsavoid 283195957Salfredlibusb_lock_event_waiters(libusb_context *ctx) 284194676Sthompsa{ 285195957Salfred ctx = GET_CONTEXT(ctx); 286195957Salfred CTX_LOCK(ctx); 287194676Sthompsa} 288194676Sthompsa 289194676Sthompsavoid 290195957Salfredlibusb_unlock_event_waiters(libusb_context *ctx) 291194676Sthompsa{ 292195957Salfred ctx = GET_CONTEXT(ctx); 293195957Salfred CTX_UNLOCK(ctx); 294194676Sthompsa} 295194676Sthompsa 296194676Sthompsaint 297195957Salfredlibusb_wait_for_event(libusb_context *ctx, struct timeval *tv) 298194676Sthompsa{ 299194676Sthompsa struct timespec ts; 300195957Salfred int err; 301194676Sthompsa 302195957Salfred ctx = GET_CONTEXT(ctx); 303195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); 304194676Sthompsa 305194676Sthompsa if (tv == NULL) { 306195957Salfred pthread_cond_wait(&ctx->ctx_cond, 307195957Salfred &ctx->ctx_lock); 308194676Sthompsa return (0); 309194676Sthompsa } 310195957Salfred err = clock_gettime(CLOCK_REALTIME, &ts); 311195957Salfred if (err < 0) 312194676Sthompsa return (LIBUSB_ERROR_OTHER); 313194676Sthompsa 314194676Sthompsa ts.tv_sec = tv->tv_sec; 315194676Sthompsa ts.tv_nsec = tv->tv_usec * 1000; 316195957Salfred if (ts.tv_nsec >= 1000000000) { 317194676Sthompsa ts.tv_nsec -= 1000000000; 318194676Sthompsa ts.tv_sec++; 319194676Sthompsa } 320195957Salfred err = pthread_cond_timedwait(&ctx->ctx_cond, 321195957Salfred &ctx->ctx_lock, &ts); 322194676Sthompsa 323195957Salfred if (err == ETIMEDOUT) 324194676Sthompsa return (1); 325194676Sthompsa 326194676Sthompsa return (0); 327194676Sthompsa} 328194676Sthompsa 329194676Sthompsaint 330195957Salfredlibusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) 331194676Sthompsa{ 332195957Salfred int err; 333195957Salfred 334195957Salfred ctx = GET_CONTEXT(ctx); 335195957Salfred 336195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter"); 337194676Sthompsa 338195957Salfred libusb_lock_events(ctx); 339194676Sthompsa 340195957Salfred err = libusb_handle_events_locked(ctx, tv); 341194676Sthompsa 342195957Salfred libusb_unlock_events(ctx); 343194676Sthompsa 344195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave"); 345195957Salfred 346195957Salfred return (err); 347194676Sthompsa} 348194676Sthompsa 349194676Sthompsaint 350195957Salfredlibusb_handle_events(libusb_context *ctx) 351194676Sthompsa{ 352195957Salfred return (libusb_handle_events_timeout(ctx, NULL)); 353194676Sthompsa} 354194676Sthompsa 355194676Sthompsaint 356195957Salfredlibusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) 357194676Sthompsa{ 358195957Salfred int err; 359194676Sthompsa 360195957Salfred ctx = GET_CONTEXT(ctx); 361194676Sthompsa 362195957Salfred if (libusb_event_handling_ok(ctx)) { 363195957Salfred err = libusb10_handle_events_sub(ctx, tv); 364195957Salfred } else { 365195957Salfred libusb_wait_for_event(ctx, tv); 366195957Salfred err = 0; 367194676Sthompsa } 368195957Salfred return (err); 369194676Sthompsa} 370194676Sthompsa 371194676Sthompsaint 372195957Salfredlibusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) 373194676Sthompsa{ 374195957Salfred /* all timeouts are currently being done by the kernel */ 375195957Salfred timerclear(tv); 376195957Salfred return (0); 377194676Sthompsa} 378194676Sthompsa 379194676Sthompsavoid 380195957Salfredlibusb_set_pollfd_notifiers(libusb_context *ctx, 381194676Sthompsa libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, 382194676Sthompsa void *user_data) 383194676Sthompsa{ 384195957Salfred ctx = GET_CONTEXT(ctx); 385194676Sthompsa 386194676Sthompsa ctx->fd_added_cb = added_cb; 387194676Sthompsa ctx->fd_removed_cb = removed_cb; 388194676Sthompsa ctx->fd_cb_user_data = user_data; 389194676Sthompsa} 390194676Sthompsa 391194676Sthompsastruct libusb_pollfd ** 392195957Salfredlibusb_get_pollfds(libusb_context *ctx) 393194676Sthompsa{ 394195957Salfred struct libusb_super_pollfd *pollfd; 395194676Sthompsa libusb_pollfd **ret; 396194676Sthompsa int i; 397194676Sthompsa 398195957Salfred ctx = GET_CONTEXT(ctx); 399194676Sthompsa 400195957Salfred CTX_LOCK(ctx); 401195957Salfred 402194676Sthompsa i = 0; 403195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 404195957Salfred i++; 405194676Sthompsa 406195957Salfred ret = calloc(i + 1, sizeof(struct libusb_pollfd *)); 407195957Salfred if (ret == NULL) 408195957Salfred goto done; 409194676Sthompsa 410194676Sthompsa i = 0; 411195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 412195957Salfred ret[i++] = &pollfd->pollfd; 413194676Sthompsa ret[i] = NULL; 414194676Sthompsa 415195957Salfreddone: 416195957Salfred CTX_UNLOCK(ctx); 417194676Sthompsa return (ret); 418194676Sthompsa} 419194676Sthompsa 420194676Sthompsa 421194676Sthompsa/* Synchronous device I/O */ 422194676Sthompsa 423194676Sthompsaint 424195957Salfredlibusb_control_transfer(libusb_device_handle *devh, 425194676Sthompsa uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, 426195957Salfred uint8_t *data, uint16_t wLength, unsigned int timeout) 427194676Sthompsa{ 428195957Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 429195957Salfred int err; 430195957Salfred uint16_t actlen; 431194676Sthompsa 432195957Salfred if (devh == NULL) 433195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 434194676Sthompsa 435195957Salfred if ((wLength != 0) && (data == NULL)) 436195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 437194676Sthompsa 438195957Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 439194676Sthompsa 440195957Salfred req.bmRequestType = bmRequestType; 441195957Salfred req.bRequest = bRequest; 442195957Salfred req.wValue = wValue; 443195957Salfred req.wIndex = wIndex; 444195957Salfred req.wLength = wLength; 445194676Sthompsa 446195957Salfred err = libusb20_dev_request_sync(devh, &req, data, 447195957Salfred &actlen, timeout, 0); 448194676Sthompsa 449195957Salfred if (err == LIBUSB20_ERROR_PIPE) 450195957Salfred return (LIBUSB_ERROR_PIPE); 451195957Salfred else if (err == LIBUSB20_ERROR_TIMEOUT) 452195957Salfred return (LIBUSB_ERROR_TIMEOUT); 453195957Salfred else if (err) 454195957Salfred return (LIBUSB_ERROR_NO_DEVICE); 455194676Sthompsa 456195957Salfred return (actlen); 457195957Salfred} 458194676Sthompsa 459195957Salfredstatic void 460195957Salfredlibusb10_do_transfer_cb(struct libusb_transfer *transfer) 461195957Salfred{ 462195957Salfred libusb_context *ctx; 463195957Salfred int *pdone; 464194676Sthompsa 465195957Salfred ctx = GET_CONTEXT(NULL); 466194676Sthompsa 467195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); 468194676Sthompsa 469195957Salfred pdone = transfer->user_data; 470195957Salfred *pdone = 1; 471194676Sthompsa} 472194676Sthompsa 473195957Salfred/* 474195957Salfred * TODO: Replace the following function. Allocating and freeing on a 475195957Salfred * per-transfer basis is slow. --HPS 476195957Salfred */ 477194676Sthompsastatic int 478195957Salfredlibusb10_do_transfer(libusb_device_handle *devh, 479195957Salfred uint8_t endpoint, uint8_t *data, int length, 480194676Sthompsa int *transferred, unsigned int timeout, int type) 481194676Sthompsa{ 482195957Salfred libusb_context *ctx; 483194676Sthompsa struct libusb_transfer *xfer; 484234491Shselasky int done; 485194676Sthompsa int ret; 486194676Sthompsa 487195957Salfred if (devh == NULL) 488195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 489194676Sthompsa 490195957Salfred if ((length != 0) && (data == NULL)) 491195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 492195957Salfred 493194676Sthompsa xfer = libusb_alloc_transfer(0); 494194676Sthompsa if (xfer == NULL) 495194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 496194676Sthompsa 497195957Salfred ctx = libusb_get_device(devh)->ctx; 498194676Sthompsa 499194676Sthompsa xfer->dev_handle = devh; 500194676Sthompsa xfer->endpoint = endpoint; 501194676Sthompsa xfer->type = type; 502194676Sthompsa xfer->timeout = timeout; 503194676Sthompsa xfer->buffer = data; 504194676Sthompsa xfer->length = length; 505234491Shselasky xfer->user_data = (void *)&done; 506195957Salfred xfer->callback = libusb10_do_transfer_cb; 507234491Shselasky done = 0; 508194676Sthompsa 509194676Sthompsa if ((ret = libusb_submit_transfer(xfer)) < 0) { 510194676Sthompsa libusb_free_transfer(xfer); 511194676Sthompsa return (ret); 512194676Sthompsa } 513234491Shselasky while (done == 0) { 514194676Sthompsa if ((ret = libusb_handle_events(ctx)) < 0) { 515194676Sthompsa libusb_cancel_transfer(xfer); 516195957Salfred usleep(1000); /* nice it */ 517194676Sthompsa } 518194676Sthompsa } 519194676Sthompsa 520194676Sthompsa *transferred = xfer->actual_length; 521195957Salfred 522194676Sthompsa switch (xfer->status) { 523194676Sthompsa case LIBUSB_TRANSFER_COMPLETED: 524195957Salfred ret = 0; 525194676Sthompsa break; 526194676Sthompsa case LIBUSB_TRANSFER_TIMED_OUT: 527195957Salfred ret = LIBUSB_ERROR_TIMEOUT; 528195957Salfred break; 529194676Sthompsa case LIBUSB_TRANSFER_OVERFLOW: 530195957Salfred ret = LIBUSB_ERROR_OVERFLOW; 531195957Salfred break; 532194676Sthompsa case LIBUSB_TRANSFER_STALL: 533195957Salfred ret = LIBUSB_ERROR_PIPE; 534195957Salfred break; 535194676Sthompsa case LIBUSB_TRANSFER_NO_DEVICE: 536195957Salfred ret = LIBUSB_ERROR_NO_DEVICE; 537194676Sthompsa break; 538194676Sthompsa default: 539194676Sthompsa ret = LIBUSB_ERROR_OTHER; 540195957Salfred break; 541194676Sthompsa } 542194676Sthompsa 543194676Sthompsa libusb_free_transfer(xfer); 544194676Sthompsa return (ret); 545194676Sthompsa} 546194676Sthompsa 547194676Sthompsaint 548195957Salfredlibusb_bulk_transfer(libusb_device_handle *devh, 549195957Salfred uint8_t endpoint, uint8_t *data, int length, 550194676Sthompsa int *transferred, unsigned int timeout) 551194676Sthompsa{ 552194676Sthompsa libusb_context *ctx; 553194676Sthompsa int ret; 554195957Salfred 555195957Salfred ctx = GET_CONTEXT(NULL); 556195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); 557194676Sthompsa 558195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 559194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_BULK); 560194676Sthompsa 561195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); 562194676Sthompsa return (ret); 563194676Sthompsa} 564194676Sthompsa 565194676Sthompsaint 566195957Salfredlibusb_interrupt_transfer(libusb_device_handle *devh, 567195957Salfred uint8_t endpoint, uint8_t *data, int length, 568194676Sthompsa int *transferred, unsigned int timeout) 569194676Sthompsa{ 570194676Sthompsa libusb_context *ctx; 571194676Sthompsa int ret; 572194676Sthompsa 573195957Salfred ctx = GET_CONTEXT(NULL); 574195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); 575194676Sthompsa 576195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 577194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); 578194676Sthompsa 579195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); 580194676Sthompsa return (ret); 581194676Sthompsa} 582199055Sthompsa 583199055Sthompsauint8_t * 584234491Shselaskylibusb_get_iso_packet_buffer(struct libusb_transfer *transfer, uint32_t off) 585199055Sthompsa{ 586199055Sthompsa uint8_t *ptr; 587199055Sthompsa uint32_t n; 588199055Sthompsa 589199055Sthompsa if (transfer->num_iso_packets < 0) 590199055Sthompsa return (NULL); 591199055Sthompsa 592234491Shselasky if (off >= (uint32_t)transfer->num_iso_packets) 593199055Sthompsa return (NULL); 594199055Sthompsa 595199055Sthompsa ptr = transfer->buffer; 596199055Sthompsa if (ptr == NULL) 597199055Sthompsa return (NULL); 598199055Sthompsa 599234491Shselasky for (n = 0; n != off; n++) { 600199055Sthompsa ptr += transfer->iso_packet_desc[n].length; 601199055Sthompsa } 602199055Sthompsa return (ptr); 603199055Sthompsa} 604199055Sthompsa 605199055Sthompsauint8_t * 606234491Shselaskylibusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, uint32_t off) 607199055Sthompsa{ 608199055Sthompsa uint8_t *ptr; 609199055Sthompsa 610199055Sthompsa if (transfer->num_iso_packets < 0) 611199055Sthompsa return (NULL); 612199055Sthompsa 613234491Shselasky if (off >= (uint32_t)transfer->num_iso_packets) 614199055Sthompsa return (NULL); 615199055Sthompsa 616199055Sthompsa ptr = transfer->buffer; 617199055Sthompsa if (ptr == NULL) 618199055Sthompsa return (NULL); 619199055Sthompsa 620234491Shselasky ptr += transfer->iso_packet_desc[0].length * off; 621199055Sthompsa 622199055Sthompsa return (ptr); 623199055Sthompsa} 624199055Sthompsa 625199055Sthompsavoid 626199055Sthompsalibusb_set_iso_packet_lengths(struct libusb_transfer *transfer, uint32_t length) 627199055Sthompsa{ 628199055Sthompsa int n; 629199055Sthompsa 630199055Sthompsa if (transfer->num_iso_packets < 0) 631199055Sthompsa return; 632199055Sthompsa 633199055Sthompsa for (n = 0; n != transfer->num_iso_packets; n++) 634199055Sthompsa transfer->iso_packet_desc[n].length = length; 635199055Sthompsa} 636199055Sthompsa 637199055Sthompsauint8_t * 638199055Sthompsalibusb_control_transfer_get_data(struct libusb_transfer *transfer) 639199055Sthompsa{ 640199055Sthompsa if (transfer->buffer == NULL) 641199055Sthompsa return (NULL); 642199055Sthompsa 643199055Sthompsa return (transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE); 644199055Sthompsa} 645199055Sthompsa 646199055Sthompsastruct libusb_control_setup * 647199055Sthompsalibusb_control_transfer_get_setup(struct libusb_transfer *transfer) 648199055Sthompsa{ 649199055Sthompsa return ((struct libusb_control_setup *)transfer->buffer); 650199055Sthompsa} 651199055Sthompsa 652199055Sthompsavoid 653199055Sthompsalibusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType, 654199055Sthompsa uint8_t bRequest, uint16_t wValue, 655199055Sthompsa uint16_t wIndex, uint16_t wLength) 656199055Sthompsa{ 657199055Sthompsa struct libusb_control_setup *req = (struct libusb_control_setup *)buf; 658199055Sthompsa 659199055Sthompsa /* The alignment is OK for all fields below. */ 660199055Sthompsa req->bmRequestType = bmRequestType; 661199055Sthompsa req->bRequest = bRequest; 662199055Sthompsa req->wValue = htole16(wValue); 663199055Sthompsa req->wIndex = htole16(wIndex); 664199055Sthompsa req->wLength = htole16(wLength); 665199055Sthompsa} 666199055Sthompsa 667199055Sthompsavoid 668199055Sthompsalibusb_fill_control_transfer(struct libusb_transfer *transfer, 669199055Sthompsa libusb_device_handle *devh, uint8_t *buf, 670199055Sthompsa libusb_transfer_cb_fn callback, void *user_data, 671199055Sthompsa uint32_t timeout) 672199055Sthompsa{ 673199055Sthompsa struct libusb_control_setup *setup = (struct libusb_control_setup *)buf; 674199055Sthompsa 675199055Sthompsa transfer->dev_handle = devh; 676199055Sthompsa transfer->endpoint = 0; 677199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; 678199055Sthompsa transfer->timeout = timeout; 679199055Sthompsa transfer->buffer = buf; 680199055Sthompsa if (setup != NULL) 681199055Sthompsa transfer->length = LIBUSB_CONTROL_SETUP_SIZE 682199055Sthompsa + le16toh(setup->wLength); 683199055Sthompsa else 684199055Sthompsa transfer->length = 0; 685199055Sthompsa transfer->user_data = user_data; 686199055Sthompsa transfer->callback = callback; 687199055Sthompsa 688199055Sthompsa} 689199055Sthompsa 690199055Sthompsavoid 691199055Sthompsalibusb_fill_bulk_transfer(struct libusb_transfer *transfer, 692199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 693199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 694199055Sthompsa uint32_t timeout) 695199055Sthompsa{ 696199055Sthompsa transfer->dev_handle = devh; 697199055Sthompsa transfer->endpoint = endpoint; 698199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_BULK; 699199055Sthompsa transfer->timeout = timeout; 700199055Sthompsa transfer->buffer = buf; 701199055Sthompsa transfer->length = length; 702199055Sthompsa transfer->user_data = user_data; 703199055Sthompsa transfer->callback = callback; 704199055Sthompsa} 705199055Sthompsa 706199055Sthompsavoid 707199055Sthompsalibusb_fill_interrupt_transfer(struct libusb_transfer *transfer, 708199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 709199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 710199055Sthompsa uint32_t timeout) 711199055Sthompsa{ 712199055Sthompsa transfer->dev_handle = devh; 713199055Sthompsa transfer->endpoint = endpoint; 714199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; 715199055Sthompsa transfer->timeout = timeout; 716199055Sthompsa transfer->buffer = buf; 717199055Sthompsa transfer->length = length; 718199055Sthompsa transfer->user_data = user_data; 719199055Sthompsa transfer->callback = callback; 720199055Sthompsa} 721199055Sthompsa 722199055Sthompsavoid 723199055Sthompsalibusb_fill_iso_transfer(struct libusb_transfer *transfer, 724199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 725199055Sthompsa int length, int npacket, libusb_transfer_cb_fn callback, 726199055Sthompsa void *user_data, uint32_t timeout) 727199055Sthompsa{ 728199055Sthompsa transfer->dev_handle = devh; 729199055Sthompsa transfer->endpoint = endpoint; 730199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; 731199055Sthompsa transfer->timeout = timeout; 732199055Sthompsa transfer->buffer = buf; 733199055Sthompsa transfer->length = length; 734199055Sthompsa transfer->num_iso_packets = npacket; 735199055Sthompsa transfer->user_data = user_data; 736199055Sthompsa transfer->callback = callback; 737199055Sthompsa} 738199055Sthompsa 739