1194676Sthompsa/* $FreeBSD: stable/11/lib/libusb/libusb10_io.c 339189 2018-10-05 07:49:01Z 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 27248236Shselasky#ifdef LIBUSB_GLOBAL_INCLUDE_FILE 28248236Shselasky#include LIBUSB_GLOBAL_INCLUDE_FILE 29248236Shselasky#else 30203815Swkoszek#include <errno.h> 31194676Sthompsa#include <poll.h> 32194676Sthompsa#include <pthread.h> 33203815Swkoszek#include <stdio.h> 34203815Swkoszek#include <stdlib.h> 35248236Shselasky#include <string.h> 36194676Sthompsa#include <time.h> 37203815Swkoszek#include <unistd.h> 38248236Shselasky#include <sys/queue.h> 39248236Shselasky#include <sys/endian.h> 40248236Shselasky#endif 41194676Sthompsa 42208020Sthompsa#define libusb_device_handle libusb20_device 43208020Sthompsa 44194676Sthompsa#include "libusb20.h" 45194676Sthompsa#include "libusb20_desc.h" 46194676Sthompsa#include "libusb20_int.h" 47194676Sthompsa#include "libusb.h" 48194676Sthompsa#include "libusb10.h" 49194676Sthompsa 50195957SalfredUNEXPORTED void 51195957Salfredlibusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, 52195957Salfred struct libusb20_device *pdev, int fd, short events) 53195560Sthompsa{ 54195560Sthompsa if (ctx == NULL) 55195957Salfred return; /* invalid */ 56195560Sthompsa 57195957Salfred if (pollfd->entry.tqe_prev != NULL) 58195957Salfred return; /* already queued */ 59195957Salfred 60195957Salfred if (fd < 0) 61195957Salfred return; /* invalid */ 62195957Salfred 63195957Salfred pollfd->pdev = pdev; 64195560Sthompsa pollfd->pollfd.fd = fd; 65195560Sthompsa pollfd->pollfd.events = events; 66195560Sthompsa 67195957Salfred CTX_LOCK(ctx); 68195957Salfred TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry); 69195957Salfred CTX_UNLOCK(ctx); 70195560Sthompsa 71195560Sthompsa if (ctx->fd_added_cb) 72195560Sthompsa ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); 73195560Sthompsa} 74195560Sthompsa 75195560SthompsaUNEXPORTED void 76195957Salfredlibusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd) 77195560Sthompsa{ 78195957Salfred if (ctx == NULL) 79195957Salfred return; /* invalid */ 80195560Sthompsa 81195957Salfred if (pollfd->entry.tqe_prev == NULL) 82195957Salfred return; /* already dequeued */ 83195560Sthompsa 84195957Salfred CTX_LOCK(ctx); 85195957Salfred TAILQ_REMOVE(&ctx->pollfds, pollfd, entry); 86195957Salfred pollfd->entry.tqe_prev = NULL; 87195957Salfred CTX_UNLOCK(ctx); 88195560Sthompsa 89195560Sthompsa if (ctx->fd_removed_cb) 90195957Salfred ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data); 91195560Sthompsa} 92195560Sthompsa 93195957Salfred/* This function must be called locked */ 94195560Sthompsa 95195957Salfredstatic int 96195957Salfredlibusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) 97195560Sthompsa{ 98195957Salfred struct libusb_device *dev; 99195957Salfred struct libusb20_device **ppdev; 100195957Salfred struct libusb_super_pollfd *pfd; 101195957Salfred struct pollfd *fds; 102195957Salfred struct libusb_super_transfer *sxfer; 103194676Sthompsa struct libusb_transfer *uxfer; 104194676Sthompsa nfds_t nfds; 105194676Sthompsa int timeout; 106194676Sthompsa int i; 107195957Salfred int err; 108194676Sthompsa 109195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); 110195957Salfred 111194676Sthompsa nfds = 0; 112195957Salfred i = 0; 113195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) 114195957Salfred nfds++; 115194676Sthompsa 116195560Sthompsa fds = alloca(sizeof(*fds) * nfds); 117194676Sthompsa if (fds == NULL) 118194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 119194676Sthompsa 120195957Salfred ppdev = alloca(sizeof(*ppdev) * nfds); 121195957Salfred if (ppdev == NULL) 122195957Salfred return (LIBUSB_ERROR_NO_MEM); 123195957Salfred 124195957Salfred TAILQ_FOREACH(pfd, &ctx->pollfds, entry) { 125195957Salfred fds[i].fd = pfd->pollfd.fd; 126195957Salfred fds[i].events = pfd->pollfd.events; 127195957Salfred fds[i].revents = 0; 128195957Salfred ppdev[i] = pfd->pdev; 129195957Salfred if (pfd->pdev != NULL) 130195957Salfred libusb_get_device(pfd->pdev)->refcnt++; 131194676Sthompsa i++; 132194676Sthompsa } 133194676Sthompsa 134195957Salfred if (tv == NULL) 135195957Salfred timeout = -1; 136195957Salfred else 137195957Salfred timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 138194676Sthompsa 139195957Salfred CTX_UNLOCK(ctx); 140195957Salfred err = poll(fds, nfds, timeout); 141195957Salfred CTX_LOCK(ctx); 142194676Sthompsa 143195957Salfred if ((err == -1) && (errno == EINTR)) 144195957Salfred err = LIBUSB_ERROR_INTERRUPTED; 145195957Salfred else if (err < 0) 146195957Salfred err = LIBUSB_ERROR_IO; 147194676Sthompsa 148195957Salfred if (err < 1) { 149213849Shselasky for (i = 0; i != (int)nfds; i++) { 150195957Salfred if (ppdev[i] != NULL) { 151195957Salfred CTX_UNLOCK(ctx); 152195957Salfred libusb_unref_device(libusb_get_device(ppdev[i])); 153195957Salfred CTX_LOCK(ctx); 154195957Salfred } 155194676Sthompsa } 156195957Salfred goto do_done; 157194676Sthompsa } 158213849Shselasky for (i = 0; i != (int)nfds; i++) { 159195957Salfred if (ppdev[i] != NULL) { 160195957Salfred dev = libusb_get_device(ppdev[i]); 161194676Sthompsa 162338788Shselasky if (fds[i].revents != 0) { 163199055Sthompsa err = libusb20_dev_process(ppdev[i]); 164199055Sthompsa 165338788Shselasky if (err) { 166338788Shselasky /* set device is gone */ 167338788Shselasky dev->device_is_gone = 1; 168199055Sthompsa 169338788Shselasky /* remove USB device from polling loop */ 170338788Shselasky libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 171338788Shselasky 172338788Shselasky /* cancel all pending transfers */ 173338788Shselasky libusb10_cancel_all_transfer_locked(ppdev[i], dev); 174338788Shselasky } 175195957Salfred } 176195957Salfred CTX_UNLOCK(ctx); 177195957Salfred libusb_unref_device(dev); 178195957Salfred CTX_LOCK(ctx); 179194676Sthompsa 180195957Salfred } else { 181195957Salfred uint8_t dummy; 182194676Sthompsa 183338788Shselasky while (read(fds[i].fd, &dummy, 1) == 1) 184338788Shselasky ; 185194676Sthompsa } 186195957Salfred } 187194676Sthompsa 188195957Salfred err = 0; 189194676Sthompsa 190195957Salfreddo_done: 191194676Sthompsa 192195957Salfred /* Do all done callbacks */ 193194676Sthompsa 194195957Salfred while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) { 195215253Shselasky uint8_t flags; 196215253Shselasky 197195957Salfred TAILQ_REMOVE(&ctx->tr_done, sxfer, entry); 198195957Salfred sxfer->entry.tqe_prev = NULL; 199194676Sthompsa 200195957Salfred ctx->tr_done_ref++; 201195957Salfred 202195957Salfred CTX_UNLOCK(ctx); 203195957Salfred 204195957Salfred uxfer = (struct libusb_transfer *)( 205195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 206195957Salfred 207215253Shselasky /* Allow the callback to free the transfer itself. */ 208215253Shselasky flags = uxfer->flags; 209215253Shselasky 210195957Salfred if (uxfer->callback != NULL) 211195957Salfred (uxfer->callback) (uxfer); 212195957Salfred 213215253Shselasky /* Check if the USB transfer should be automatically freed. */ 214215253Shselasky if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) 215195957Salfred libusb_free_transfer(uxfer); 216195957Salfred 217195957Salfred CTX_LOCK(ctx); 218195957Salfred 219195957Salfred ctx->tr_done_ref--; 220195957Salfred ctx->tr_done_gen++; 221194676Sthompsa } 222194676Sthompsa 223195957Salfred /* Wakeup other waiters */ 224195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 225194676Sthompsa 226195957Salfred return (err); 227194676Sthompsa} 228194676Sthompsa 229194676Sthompsa/* Polling and timing */ 230194676Sthompsa 231194676Sthompsaint 232195957Salfredlibusb_try_lock_events(libusb_context *ctx) 233194676Sthompsa{ 234195957Salfred int err; 235194676Sthompsa 236195957Salfred ctx = GET_CONTEXT(ctx); 237195957Salfred if (ctx == NULL) 238194676Sthompsa return (1); 239194676Sthompsa 240195957Salfred err = CTX_TRYLOCK(ctx); 241195957Salfred if (err) 242194676Sthompsa return (1); 243194676Sthompsa 244195957Salfred err = (ctx->ctx_handler != NO_THREAD); 245195957Salfred if (err) 246195957Salfred CTX_UNLOCK(ctx); 247195957Salfred else 248195957Salfred ctx->ctx_handler = pthread_self(); 249195957Salfred 250195957Salfred return (err); 251194676Sthompsa} 252194676Sthompsa 253194676Sthompsavoid 254195957Salfredlibusb_lock_events(libusb_context *ctx) 255194676Sthompsa{ 256195957Salfred ctx = GET_CONTEXT(ctx); 257195957Salfred CTX_LOCK(ctx); 258195957Salfred if (ctx->ctx_handler == NO_THREAD) 259195957Salfred ctx->ctx_handler = pthread_self(); 260194676Sthompsa} 261194676Sthompsa 262194676Sthompsavoid 263195957Salfredlibusb_unlock_events(libusb_context *ctx) 264194676Sthompsa{ 265195957Salfred ctx = GET_CONTEXT(ctx); 266195957Salfred if (ctx->ctx_handler == pthread_self()) { 267195957Salfred ctx->ctx_handler = NO_THREAD; 268195957Salfred pthread_cond_broadcast(&ctx->ctx_cond); 269195957Salfred } 270195957Salfred CTX_UNLOCK(ctx); 271194676Sthompsa} 272194676Sthompsa 273194676Sthompsaint 274195957Salfredlibusb_event_handling_ok(libusb_context *ctx) 275194676Sthompsa{ 276195957Salfred ctx = GET_CONTEXT(ctx); 277195957Salfred return (ctx->ctx_handler == pthread_self()); 278194676Sthompsa} 279194676Sthompsa 280194676Sthompsaint 281195957Salfredlibusb_event_handler_active(libusb_context *ctx) 282194676Sthompsa{ 283195957Salfred ctx = GET_CONTEXT(ctx); 284195957Salfred return (ctx->ctx_handler != NO_THREAD); 285194676Sthompsa} 286194676Sthompsa 287194676Sthompsavoid 288195957Salfredlibusb_lock_event_waiters(libusb_context *ctx) 289194676Sthompsa{ 290195957Salfred ctx = GET_CONTEXT(ctx); 291195957Salfred CTX_LOCK(ctx); 292194676Sthompsa} 293194676Sthompsa 294194676Sthompsavoid 295195957Salfredlibusb_unlock_event_waiters(libusb_context *ctx) 296194676Sthompsa{ 297195957Salfred ctx = GET_CONTEXT(ctx); 298195957Salfred CTX_UNLOCK(ctx); 299194676Sthompsa} 300194676Sthompsa 301194676Sthompsaint 302195957Salfredlibusb_wait_for_event(libusb_context *ctx, struct timeval *tv) 303194676Sthompsa{ 304194676Sthompsa struct timespec ts; 305195957Salfred int err; 306194676Sthompsa 307195957Salfred ctx = GET_CONTEXT(ctx); 308195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); 309194676Sthompsa 310194676Sthompsa if (tv == NULL) { 311195957Salfred pthread_cond_wait(&ctx->ctx_cond, 312195957Salfred &ctx->ctx_lock); 313339189Shselasky /* try to grab polling of actual events, if any */ 314339189Shselasky if (ctx->ctx_handler == NO_THREAD) 315339189Shselasky ctx->ctx_handler = pthread_self(); 316194676Sthompsa return (0); 317194676Sthompsa } 318236944Shselasky err = clock_gettime(CLOCK_MONOTONIC, &ts); 319195957Salfred if (err < 0) 320194676Sthompsa return (LIBUSB_ERROR_OTHER); 321194676Sthompsa 322236944Shselasky /* 323236944Shselasky * The "tv" arguments points to a relative time structure and 324236944Shselasky * not an absolute time structure. 325236944Shselasky */ 326236944Shselasky ts.tv_sec += tv->tv_sec; 327236944Shselasky ts.tv_nsec += tv->tv_usec * 1000; 328195957Salfred if (ts.tv_nsec >= 1000000000) { 329194676Sthompsa ts.tv_nsec -= 1000000000; 330194676Sthompsa ts.tv_sec++; 331194676Sthompsa } 332195957Salfred err = pthread_cond_timedwait(&ctx->ctx_cond, 333195957Salfred &ctx->ctx_lock, &ts); 334339189Shselasky /* try to grab polling of actual events, if any */ 335339189Shselasky if (ctx->ctx_handler == NO_THREAD) 336339189Shselasky ctx->ctx_handler = pthread_self(); 337194676Sthompsa 338195957Salfred if (err == ETIMEDOUT) 339194676Sthompsa return (1); 340194676Sthompsa 341194676Sthompsa return (0); 342194676Sthompsa} 343194676Sthompsa 344194676Sthompsaint 345260315Shselaskylibusb_handle_events_timeout_completed(libusb_context *ctx, 346260315Shselasky struct timeval *tv, int *completed) 347194676Sthompsa{ 348260315Shselasky int err = 0; 349195957Salfred 350195957Salfred ctx = GET_CONTEXT(ctx); 351195957Salfred 352260315Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed enter"); 353194676Sthompsa 354195957Salfred libusb_lock_events(ctx); 355194676Sthompsa 356260315Shselasky while (1) { 357260315Shselasky if (completed != NULL) { 358260315Shselasky if (*completed != 0 || err != 0) 359260315Shselasky break; 360260315Shselasky } 361260315Shselasky err = libusb_handle_events_locked(ctx, tv); 362260315Shselasky if (completed == NULL) 363260315Shselasky break; 364260315Shselasky } 365194676Sthompsa 366195957Salfred libusb_unlock_events(ctx); 367194676Sthompsa 368260315Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed exit"); 369195957Salfred 370195957Salfred return (err); 371194676Sthompsa} 372194676Sthompsa 373194676Sthompsaint 374260315Shselaskylibusb_handle_events_completed(libusb_context *ctx, int *completed) 375260315Shselasky{ 376260315Shselasky return (libusb_handle_events_timeout_completed(ctx, NULL, completed)); 377260315Shselasky} 378260315Shselasky 379260315Shselaskyint 380260315Shselaskylibusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) 381260315Shselasky{ 382260315Shselasky return (libusb_handle_events_timeout_completed(ctx, tv, NULL)); 383260315Shselasky} 384260315Shselasky 385260315Shselaskyint 386195957Salfredlibusb_handle_events(libusb_context *ctx) 387194676Sthompsa{ 388260315Shselasky return (libusb_handle_events_timeout_completed(ctx, NULL, NULL)); 389194676Sthompsa} 390194676Sthompsa 391194676Sthompsaint 392195957Salfredlibusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) 393194676Sthompsa{ 394195957Salfred int err; 395194676Sthompsa 396195957Salfred ctx = GET_CONTEXT(ctx); 397194676Sthompsa 398195957Salfred if (libusb_event_handling_ok(ctx)) { 399195957Salfred err = libusb10_handle_events_sub(ctx, tv); 400195957Salfred } else { 401260315Shselasky err = libusb_wait_for_event(ctx, tv); 402260315Shselasky if (err != 0) 403260315Shselasky err = LIBUSB_ERROR_TIMEOUT; 404194676Sthompsa } 405195957Salfred return (err); 406194676Sthompsa} 407194676Sthompsa 408194676Sthompsaint 409195957Salfredlibusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) 410194676Sthompsa{ 411195957Salfred /* all timeouts are currently being done by the kernel */ 412195957Salfred timerclear(tv); 413195957Salfred return (0); 414194676Sthompsa} 415194676Sthompsa 416194676Sthompsavoid 417195957Salfredlibusb_set_pollfd_notifiers(libusb_context *ctx, 418194676Sthompsa libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, 419194676Sthompsa void *user_data) 420194676Sthompsa{ 421195957Salfred ctx = GET_CONTEXT(ctx); 422194676Sthompsa 423194676Sthompsa ctx->fd_added_cb = added_cb; 424194676Sthompsa ctx->fd_removed_cb = removed_cb; 425194676Sthompsa ctx->fd_cb_user_data = user_data; 426194676Sthompsa} 427194676Sthompsa 428250335Semasteconst struct libusb_pollfd ** 429195957Salfredlibusb_get_pollfds(libusb_context *ctx) 430194676Sthompsa{ 431195957Salfred struct libusb_super_pollfd *pollfd; 432194676Sthompsa libusb_pollfd **ret; 433194676Sthompsa int i; 434194676Sthompsa 435195957Salfred ctx = GET_CONTEXT(ctx); 436194676Sthompsa 437195957Salfred CTX_LOCK(ctx); 438195957Salfred 439194676Sthompsa i = 0; 440195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 441195957Salfred i++; 442194676Sthompsa 443195957Salfred ret = calloc(i + 1, sizeof(struct libusb_pollfd *)); 444195957Salfred if (ret == NULL) 445195957Salfred goto done; 446194676Sthompsa 447194676Sthompsa i = 0; 448195957Salfred TAILQ_FOREACH(pollfd, &ctx->pollfds, entry) 449195957Salfred ret[i++] = &pollfd->pollfd; 450194676Sthompsa ret[i] = NULL; 451194676Sthompsa 452195957Salfreddone: 453195957Salfred CTX_UNLOCK(ctx); 454250335Semaste return ((const struct libusb_pollfd **)ret); 455194676Sthompsa} 456194676Sthompsa 457194676Sthompsa 458194676Sthompsa/* Synchronous device I/O */ 459194676Sthompsa 460194676Sthompsaint 461195957Salfredlibusb_control_transfer(libusb_device_handle *devh, 462194676Sthompsa uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, 463195957Salfred uint8_t *data, uint16_t wLength, unsigned int timeout) 464194676Sthompsa{ 465195957Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 466195957Salfred int err; 467195957Salfred uint16_t actlen; 468194676Sthompsa 469195957Salfred if (devh == NULL) 470195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 471194676Sthompsa 472195957Salfred if ((wLength != 0) && (data == NULL)) 473195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 474194676Sthompsa 475195957Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 476194676Sthompsa 477195957Salfred req.bmRequestType = bmRequestType; 478195957Salfred req.bRequest = bRequest; 479195957Salfred req.wValue = wValue; 480195957Salfred req.wIndex = wIndex; 481195957Salfred req.wLength = wLength; 482194676Sthompsa 483195957Salfred err = libusb20_dev_request_sync(devh, &req, data, 484195957Salfred &actlen, timeout, 0); 485194676Sthompsa 486195957Salfred if (err == LIBUSB20_ERROR_PIPE) 487195957Salfred return (LIBUSB_ERROR_PIPE); 488195957Salfred else if (err == LIBUSB20_ERROR_TIMEOUT) 489195957Salfred return (LIBUSB_ERROR_TIMEOUT); 490195957Salfred else if (err) 491195957Salfred return (LIBUSB_ERROR_NO_DEVICE); 492194676Sthompsa 493195957Salfred return (actlen); 494195957Salfred} 495194676Sthompsa 496338791Shselaskystatic libusb_context * 497338791Shselaskylibusb10_get_context_by_device_handle(libusb_device_handle *devh) 498338791Shselasky{ 499338791Shselasky libusb_context *ctx; 500338791Shselasky 501338791Shselasky if (devh != NULL) 502338791Shselasky ctx = libusb_get_device(devh)->ctx; 503338791Shselasky else 504338791Shselasky ctx = NULL; 505338791Shselasky 506338791Shselasky return (GET_CONTEXT(ctx)); 507338791Shselasky} 508338791Shselasky 509195957Salfredstatic void 510195957Salfredlibusb10_do_transfer_cb(struct libusb_transfer *transfer) 511195957Salfred{ 512195957Salfred libusb_context *ctx; 513195957Salfred int *pdone; 514194676Sthompsa 515338791Shselasky ctx = libusb10_get_context_by_device_handle(transfer->dev_handle); 516194676Sthompsa 517195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); 518194676Sthompsa 519195957Salfred pdone = transfer->user_data; 520195957Salfred *pdone = 1; 521194676Sthompsa} 522194676Sthompsa 523195957Salfred/* 524195957Salfred * TODO: Replace the following function. Allocating and freeing on a 525195957Salfred * per-transfer basis is slow. --HPS 526195957Salfred */ 527194676Sthompsastatic int 528195957Salfredlibusb10_do_transfer(libusb_device_handle *devh, 529195957Salfred uint8_t endpoint, uint8_t *data, int length, 530194676Sthompsa int *transferred, unsigned int timeout, int type) 531194676Sthompsa{ 532195957Salfred libusb_context *ctx; 533194676Sthompsa struct libusb_transfer *xfer; 534234491Shselasky int done; 535194676Sthompsa int ret; 536194676Sthompsa 537195957Salfred if (devh == NULL) 538195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 539194676Sthompsa 540195957Salfred if ((length != 0) && (data == NULL)) 541195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 542195957Salfred 543194676Sthompsa xfer = libusb_alloc_transfer(0); 544194676Sthompsa if (xfer == NULL) 545194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 546194676Sthompsa 547195957Salfred ctx = libusb_get_device(devh)->ctx; 548194676Sthompsa 549194676Sthompsa xfer->dev_handle = devh; 550194676Sthompsa xfer->endpoint = endpoint; 551194676Sthompsa xfer->type = type; 552194676Sthompsa xfer->timeout = timeout; 553194676Sthompsa xfer->buffer = data; 554194676Sthompsa xfer->length = length; 555234491Shselasky xfer->user_data = (void *)&done; 556195957Salfred xfer->callback = libusb10_do_transfer_cb; 557234491Shselasky done = 0; 558194676Sthompsa 559194676Sthompsa if ((ret = libusb_submit_transfer(xfer)) < 0) { 560194676Sthompsa libusb_free_transfer(xfer); 561194676Sthompsa return (ret); 562194676Sthompsa } 563234491Shselasky while (done == 0) { 564194676Sthompsa if ((ret = libusb_handle_events(ctx)) < 0) { 565194676Sthompsa libusb_cancel_transfer(xfer); 566195957Salfred usleep(1000); /* nice it */ 567194676Sthompsa } 568194676Sthompsa } 569194676Sthompsa 570194676Sthompsa *transferred = xfer->actual_length; 571195957Salfred 572194676Sthompsa switch (xfer->status) { 573194676Sthompsa case LIBUSB_TRANSFER_COMPLETED: 574195957Salfred ret = 0; 575194676Sthompsa break; 576194676Sthompsa case LIBUSB_TRANSFER_TIMED_OUT: 577195957Salfred ret = LIBUSB_ERROR_TIMEOUT; 578195957Salfred break; 579194676Sthompsa case LIBUSB_TRANSFER_OVERFLOW: 580195957Salfred ret = LIBUSB_ERROR_OVERFLOW; 581195957Salfred break; 582194676Sthompsa case LIBUSB_TRANSFER_STALL: 583195957Salfred ret = LIBUSB_ERROR_PIPE; 584195957Salfred break; 585194676Sthompsa case LIBUSB_TRANSFER_NO_DEVICE: 586195957Salfred ret = LIBUSB_ERROR_NO_DEVICE; 587194676Sthompsa break; 588194676Sthompsa default: 589194676Sthompsa ret = LIBUSB_ERROR_OTHER; 590195957Salfred break; 591194676Sthompsa } 592194676Sthompsa 593194676Sthompsa libusb_free_transfer(xfer); 594194676Sthompsa return (ret); 595194676Sthompsa} 596194676Sthompsa 597194676Sthompsaint 598195957Salfredlibusb_bulk_transfer(libusb_device_handle *devh, 599195957Salfred uint8_t endpoint, uint8_t *data, int length, 600194676Sthompsa int *transferred, unsigned int timeout) 601194676Sthompsa{ 602194676Sthompsa libusb_context *ctx; 603194676Sthompsa int ret; 604195957Salfred 605338791Shselasky ctx = libusb10_get_context_by_device_handle(devh); 606338791Shselasky 607195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); 608194676Sthompsa 609195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 610194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_BULK); 611194676Sthompsa 612195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); 613194676Sthompsa return (ret); 614194676Sthompsa} 615194676Sthompsa 616194676Sthompsaint 617195957Salfredlibusb_interrupt_transfer(libusb_device_handle *devh, 618195957Salfred uint8_t endpoint, uint8_t *data, int length, 619194676Sthompsa int *transferred, unsigned int timeout) 620194676Sthompsa{ 621194676Sthompsa libusb_context *ctx; 622194676Sthompsa int ret; 623194676Sthompsa 624338791Shselasky ctx = libusb10_get_context_by_device_handle(devh); 625338791Shselasky 626195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); 627194676Sthompsa 628195957Salfred ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, 629194676Sthompsa timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); 630194676Sthompsa 631195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); 632194676Sthompsa return (ret); 633194676Sthompsa} 634199055Sthompsa 635199055Sthompsauint8_t * 636234491Shselaskylibusb_get_iso_packet_buffer(struct libusb_transfer *transfer, uint32_t off) 637199055Sthompsa{ 638199055Sthompsa uint8_t *ptr; 639199055Sthompsa uint32_t n; 640199055Sthompsa 641199055Sthompsa if (transfer->num_iso_packets < 0) 642199055Sthompsa return (NULL); 643199055Sthompsa 644234491Shselasky if (off >= (uint32_t)transfer->num_iso_packets) 645199055Sthompsa return (NULL); 646199055Sthompsa 647199055Sthompsa ptr = transfer->buffer; 648199055Sthompsa if (ptr == NULL) 649199055Sthompsa return (NULL); 650199055Sthompsa 651234491Shselasky for (n = 0; n != off; n++) { 652199055Sthompsa ptr += transfer->iso_packet_desc[n].length; 653199055Sthompsa } 654199055Sthompsa return (ptr); 655199055Sthompsa} 656199055Sthompsa 657199055Sthompsauint8_t * 658234491Shselaskylibusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, uint32_t off) 659199055Sthompsa{ 660199055Sthompsa uint8_t *ptr; 661199055Sthompsa 662199055Sthompsa if (transfer->num_iso_packets < 0) 663199055Sthompsa return (NULL); 664199055Sthompsa 665234491Shselasky if (off >= (uint32_t)transfer->num_iso_packets) 666199055Sthompsa return (NULL); 667199055Sthompsa 668199055Sthompsa ptr = transfer->buffer; 669199055Sthompsa if (ptr == NULL) 670199055Sthompsa return (NULL); 671199055Sthompsa 672234491Shselasky ptr += transfer->iso_packet_desc[0].length * off; 673199055Sthompsa 674199055Sthompsa return (ptr); 675199055Sthompsa} 676199055Sthompsa 677199055Sthompsavoid 678199055Sthompsalibusb_set_iso_packet_lengths(struct libusb_transfer *transfer, uint32_t length) 679199055Sthompsa{ 680199055Sthompsa int n; 681199055Sthompsa 682199055Sthompsa if (transfer->num_iso_packets < 0) 683199055Sthompsa return; 684199055Sthompsa 685199055Sthompsa for (n = 0; n != transfer->num_iso_packets; n++) 686199055Sthompsa transfer->iso_packet_desc[n].length = length; 687199055Sthompsa} 688199055Sthompsa 689199055Sthompsauint8_t * 690199055Sthompsalibusb_control_transfer_get_data(struct libusb_transfer *transfer) 691199055Sthompsa{ 692199055Sthompsa if (transfer->buffer == NULL) 693199055Sthompsa return (NULL); 694199055Sthompsa 695199055Sthompsa return (transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE); 696199055Sthompsa} 697199055Sthompsa 698199055Sthompsastruct libusb_control_setup * 699199055Sthompsalibusb_control_transfer_get_setup(struct libusb_transfer *transfer) 700199055Sthompsa{ 701199055Sthompsa return ((struct libusb_control_setup *)transfer->buffer); 702199055Sthompsa} 703199055Sthompsa 704199055Sthompsavoid 705199055Sthompsalibusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType, 706199055Sthompsa uint8_t bRequest, uint16_t wValue, 707199055Sthompsa uint16_t wIndex, uint16_t wLength) 708199055Sthompsa{ 709199055Sthompsa struct libusb_control_setup *req = (struct libusb_control_setup *)buf; 710199055Sthompsa 711199055Sthompsa /* The alignment is OK for all fields below. */ 712199055Sthompsa req->bmRequestType = bmRequestType; 713199055Sthompsa req->bRequest = bRequest; 714199055Sthompsa req->wValue = htole16(wValue); 715199055Sthompsa req->wIndex = htole16(wIndex); 716199055Sthompsa req->wLength = htole16(wLength); 717199055Sthompsa} 718199055Sthompsa 719199055Sthompsavoid 720199055Sthompsalibusb_fill_control_transfer(struct libusb_transfer *transfer, 721199055Sthompsa libusb_device_handle *devh, uint8_t *buf, 722199055Sthompsa libusb_transfer_cb_fn callback, void *user_data, 723199055Sthompsa uint32_t timeout) 724199055Sthompsa{ 725199055Sthompsa struct libusb_control_setup *setup = (struct libusb_control_setup *)buf; 726199055Sthompsa 727199055Sthompsa transfer->dev_handle = devh; 728199055Sthompsa transfer->endpoint = 0; 729199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; 730199055Sthompsa transfer->timeout = timeout; 731199055Sthompsa transfer->buffer = buf; 732199055Sthompsa if (setup != NULL) 733199055Sthompsa transfer->length = LIBUSB_CONTROL_SETUP_SIZE 734199055Sthompsa + le16toh(setup->wLength); 735199055Sthompsa else 736199055Sthompsa transfer->length = 0; 737199055Sthompsa transfer->user_data = user_data; 738199055Sthompsa transfer->callback = callback; 739199055Sthompsa 740199055Sthompsa} 741199055Sthompsa 742199055Sthompsavoid 743199055Sthompsalibusb_fill_bulk_transfer(struct libusb_transfer *transfer, 744199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 745199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 746199055Sthompsa uint32_t timeout) 747199055Sthompsa{ 748199055Sthompsa transfer->dev_handle = devh; 749199055Sthompsa transfer->endpoint = endpoint; 750199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_BULK; 751199055Sthompsa transfer->timeout = timeout; 752199055Sthompsa transfer->buffer = buf; 753199055Sthompsa transfer->length = length; 754199055Sthompsa transfer->user_data = user_data; 755199055Sthompsa transfer->callback = callback; 756199055Sthompsa} 757199055Sthompsa 758199055Sthompsavoid 759199055Sthompsalibusb_fill_interrupt_transfer(struct libusb_transfer *transfer, 760199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 761199055Sthompsa int length, libusb_transfer_cb_fn callback, void *user_data, 762199055Sthompsa uint32_t timeout) 763199055Sthompsa{ 764199055Sthompsa transfer->dev_handle = devh; 765199055Sthompsa transfer->endpoint = endpoint; 766199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; 767199055Sthompsa transfer->timeout = timeout; 768199055Sthompsa transfer->buffer = buf; 769199055Sthompsa transfer->length = length; 770199055Sthompsa transfer->user_data = user_data; 771199055Sthompsa transfer->callback = callback; 772199055Sthompsa} 773199055Sthompsa 774199055Sthompsavoid 775199055Sthompsalibusb_fill_iso_transfer(struct libusb_transfer *transfer, 776199055Sthompsa libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, 777199055Sthompsa int length, int npacket, libusb_transfer_cb_fn callback, 778199055Sthompsa void *user_data, uint32_t timeout) 779199055Sthompsa{ 780199055Sthompsa transfer->dev_handle = devh; 781199055Sthompsa transfer->endpoint = endpoint; 782199055Sthompsa transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; 783199055Sthompsa transfer->timeout = timeout; 784199055Sthompsa transfer->buffer = buf; 785199055Sthompsa transfer->length = length; 786199055Sthompsa transfer->num_iso_packets = npacket; 787199055Sthompsa transfer->user_data = user_data; 788199055Sthompsa transfer->callback = callback; 789199055Sthompsa} 790199055Sthompsa 791302125Shselaskyint 792302125Shselaskylibusb_alloc_streams(libusb_device_handle *dev, uint32_t num_streams, 793302125Shselasky unsigned char *endpoints, int num_endpoints) 794302125Shselasky{ 795302125Shselasky if (num_streams > 1) 796302125Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 797302125Shselasky return (0); 798302125Shselasky} 799302125Shselasky 800302125Shselaskyint 801302125Shselaskylibusb_free_streams(libusb_device_handle *dev, unsigned char *endpoints, int num_endpoints) 802302125Shselasky{ 803302125Shselasky 804302125Shselasky return (0); 805302125Shselasky} 806302125Shselasky 807302125Shselaskyvoid 808302125Shselaskylibusb_transfer_set_stream_id(struct libusb_transfer *transfer, uint32_t stream_id) 809302125Shselasky{ 810302125Shselasky struct libusb_super_transfer *sxfer; 811302125Shselasky 812302125Shselasky if (transfer == NULL) 813302125Shselasky return; 814302125Shselasky 815302125Shselasky sxfer = (struct libusb_super_transfer *)( 816302125Shselasky ((uint8_t *)transfer) - sizeof(*sxfer)); 817302125Shselasky 818302125Shselasky /* set stream ID */ 819302125Shselasky sxfer->stream_id = stream_id; 820302125Shselasky} 821302125Shselasky 822302125Shselaskyuint32_t 823302125Shselaskylibusb_transfer_get_stream_id(struct libusb_transfer *transfer) 824302125Shselasky{ 825302125Shselasky struct libusb_super_transfer *sxfer; 826302125Shselasky 827302125Shselasky if (transfer == NULL) 828302125Shselasky return (0); 829302125Shselasky 830302125Shselasky sxfer = (struct libusb_super_transfer *)( 831302125Shselasky ((uint8_t *)transfer) - sizeof(*sxfer)); 832302125Shselasky 833302125Shselasky /* get stream ID */ 834302125Shselasky return (sxfer->stream_id); 835302125Shselasky} 836