libusb10.c revision 301956
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10.c 301956 2016-06-16 07:48:21Z hselasky $ */ 2194676Sthompsa/*- 3194676Sthompsa * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. 4195957Salfred * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. 5194676Sthompsa * 6194676Sthompsa * Redistribution and use in source and binary forms, with or without 7194676Sthompsa * modification, are permitted provided that the following conditions 8194676Sthompsa * are met: 9194676Sthompsa * 1. Redistributions of source code must retain the above copyright 10194676Sthompsa * notice, this list of conditions and the following disclaimer. 11194676Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 12194676Sthompsa * notice, this list of conditions and the following disclaimer in the 13194676Sthompsa * documentation and/or other materials provided with the distribution. 14194676Sthompsa * 15194676Sthompsa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16194676Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18194676Sthompsa * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19194676Sthompsa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20194676Sthompsa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21194676Sthompsa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22194676Sthompsa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23194676Sthompsa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24194676Sthompsa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25194676Sthompsa * SUCH DAMAGE. 26194676Sthompsa */ 27194676Sthompsa 28248236Shselasky#ifdef LIBUSB_GLOBAL_INCLUDE_FILE 29248236Shselasky#include LIBUSB_GLOBAL_INCLUDE_FILE 30248236Shselasky#else 31203774Swkoszek#include <assert.h> 32203815Swkoszek#include <errno.h> 33203815Swkoszek#include <poll.h> 34203815Swkoszek#include <pthread.h> 35203815Swkoszek#include <stdio.h> 36194676Sthompsa#include <stdlib.h> 37248236Shselasky#include <string.h> 38194676Sthompsa#include <unistd.h> 39248236Shselasky#include <time.h> 40248236Shselasky#include <sys/fcntl.h> 41248236Shselasky#include <sys/ioctl.h> 42248236Shselasky#include <sys/queue.h> 43248236Shselasky#include <sys/endian.h> 44248236Shselasky#endif 45194676Sthompsa 46208020Sthompsa#define libusb_device_handle libusb20_device 47208020Sthompsa 48194676Sthompsa#include "libusb20.h" 49194676Sthompsa#include "libusb20_desc.h" 50194676Sthompsa#include "libusb20_int.h" 51194676Sthompsa#include "libusb.h" 52194676Sthompsa#include "libusb10.h" 53194676Sthompsa 54301842Shselasky#define LIBUSB_NUM_SW_ENDPOINTS (16 * 4) 55301842Shselasky 56194676Sthompsastatic pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER; 57194676Sthompsastruct libusb_context *usbi_default_context = NULL; 58194676Sthompsa 59195957Salfred/* Prototypes */ 60195957Salfred 61195957Salfredstatic struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *, uint8_t, uint8_t); 62195957Salfredstatic int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *); 63195957Salfredstatic int libusb10_convert_error(uint8_t status); 64195957Salfredstatic void libusb10_complete_transfer(struct libusb20_transfer *, struct libusb_super_transfer *, int); 65195957Salfredstatic void libusb10_isoc_proxy(struct libusb20_transfer *); 66195957Salfredstatic void libusb10_bulk_intr_proxy(struct libusb20_transfer *); 67195957Salfredstatic void libusb10_ctrl_proxy(struct libusb20_transfer *); 68195957Salfredstatic void libusb10_submit_transfer_sub(struct libusb20_device *, uint8_t); 69195957Salfred 70194676Sthompsa/* Library initialisation / deinitialisation */ 71194676Sthompsa 72301956Shselaskystatic const struct libusb_version libusb_version = { 73301956Shselasky .major = 1, 74301956Shselasky .minor = 0, 75301956Shselasky .micro = 0, 76301956Shselasky .nano = 2016, 77301956Shselasky .rc = "", 78301956Shselasky .describe = "http://www.freebsd.org" 79301956Shselasky}; 80301956Shselasky 81301956Shselaskyconst struct libusb_version * 82301956Shselaskylibusb_get_version(void) 83301956Shselasky{ 84301956Shselasky 85301956Shselasky return (&libusb_version); 86301956Shselasky} 87301956Shselasky 88194676Sthompsavoid 89195957Salfredlibusb_set_debug(libusb_context *ctx, int level) 90194676Sthompsa{ 91195957Salfred ctx = GET_CONTEXT(ctx); 92194676Sthompsa if (ctx) 93194676Sthompsa ctx->debug = level; 94194676Sthompsa} 95194676Sthompsa 96213853Shselaskystatic void 97213853Shselaskylibusb_set_nonblocking(int f) 98213853Shselasky{ 99213853Shselasky int flags; 100213853Shselasky 101213853Shselasky /* 102213853Shselasky * We ignore any failures in this function, hence the 103213853Shselasky * non-blocking flag is not critical to the operation of 104213853Shselasky * libUSB. We use F_GETFL and F_SETFL to be compatible with 105213853Shselasky * Linux. 106213853Shselasky */ 107213853Shselasky 108213853Shselasky flags = fcntl(f, F_GETFL, NULL); 109213853Shselasky if (flags == -1) 110213853Shselasky return; 111213853Shselasky flags |= O_NONBLOCK; 112213853Shselasky fcntl(f, F_SETFL, flags); 113213853Shselasky} 114213853Shselasky 115194676Sthompsaint 116195957Salfredlibusb_init(libusb_context **context) 117194676Sthompsa{ 118194676Sthompsa struct libusb_context *ctx; 119236944Shselasky pthread_condattr_t attr; 120195957Salfred char *debug; 121194676Sthompsa int ret; 122194676Sthompsa 123194676Sthompsa ctx = malloc(sizeof(*ctx)); 124194676Sthompsa if (!ctx) 125194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 126194676Sthompsa 127194676Sthompsa memset(ctx, 0, sizeof(*ctx)); 128194676Sthompsa 129194676Sthompsa debug = getenv("LIBUSB_DEBUG"); 130194676Sthompsa if (debug != NULL) { 131194676Sthompsa ctx->debug = atoi(debug); 132194676Sthompsa if (ctx->debug != 0) 133194676Sthompsa ctx->debug_fixed = 1; 134194676Sthompsa } 135195957Salfred TAILQ_INIT(&ctx->pollfds); 136195957Salfred TAILQ_INIT(&ctx->tr_done); 137194676Sthompsa 138236944Shselasky if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) { 139236944Shselasky free(ctx); 140236944Shselasky return (LIBUSB_ERROR_NO_MEM); 141236944Shselasky } 142236944Shselasky if (pthread_condattr_init(&attr) != 0) { 143236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 144236944Shselasky free(ctx); 145236944Shselasky return (LIBUSB_ERROR_NO_MEM); 146236944Shselasky } 147236944Shselasky if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) { 148236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 149236944Shselasky pthread_condattr_destroy(&attr); 150236944Shselasky free(ctx); 151236944Shselasky return (LIBUSB_ERROR_OTHER); 152236944Shselasky } 153236944Shselasky if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) { 154236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 155236944Shselasky pthread_condattr_destroy(&attr); 156236944Shselasky free(ctx); 157236944Shselasky return (LIBUSB_ERROR_NO_MEM); 158236944Shselasky } 159236944Shselasky pthread_condattr_destroy(&attr); 160194676Sthompsa 161195957Salfred ctx->ctx_handler = NO_THREAD; 162194676Sthompsa 163194676Sthompsa ret = pipe(ctx->ctrl_pipe); 164194676Sthompsa if (ret < 0) { 165195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 166195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 167194676Sthompsa free(ctx); 168194676Sthompsa return (LIBUSB_ERROR_OTHER); 169194676Sthompsa } 170195957Salfred /* set non-blocking mode on the control pipe to avoid deadlock */ 171213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[0]); 172213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[1]); 173194676Sthompsa 174195957Salfred libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); 175194676Sthompsa 176194676Sthompsa pthread_mutex_lock(&default_context_lock); 177194676Sthompsa if (usbi_default_context == NULL) { 178194676Sthompsa usbi_default_context = ctx; 179194676Sthompsa } 180194676Sthompsa pthread_mutex_unlock(&default_context_lock); 181194676Sthompsa 182194676Sthompsa if (context) 183194676Sthompsa *context = ctx; 184194676Sthompsa 185195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); 186195957Salfred 187194676Sthompsa return (0); 188194676Sthompsa} 189194676Sthompsa 190194676Sthompsavoid 191195957Salfredlibusb_exit(libusb_context *ctx) 192194676Sthompsa{ 193195957Salfred ctx = GET_CONTEXT(ctx); 194194676Sthompsa 195195957Salfred if (ctx == NULL) 196195957Salfred return; 197195957Salfred 198195957Salfred /* XXX cleanup devices */ 199195957Salfred 200195957Salfred libusb10_remove_pollfd(ctx, &ctx->ctx_poll); 201194676Sthompsa close(ctx->ctrl_pipe[0]); 202194676Sthompsa close(ctx->ctrl_pipe[1]); 203195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 204195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 205194676Sthompsa 206194676Sthompsa pthread_mutex_lock(&default_context_lock); 207194676Sthompsa if (ctx == usbi_default_context) { 208194676Sthompsa usbi_default_context = NULL; 209194676Sthompsa } 210194676Sthompsa pthread_mutex_unlock(&default_context_lock); 211194676Sthompsa 212194676Sthompsa free(ctx); 213194676Sthompsa} 214194676Sthompsa 215194676Sthompsa/* Device handling and initialisation. */ 216194676Sthompsa 217194676Sthompsassize_t 218195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list) 219194676Sthompsa{ 220195957Salfred struct libusb20_backend *usb_backend; 221194676Sthompsa struct libusb20_device *pdev; 222194676Sthompsa struct libusb_device *dev; 223194676Sthompsa int i; 224194676Sthompsa 225195957Salfred ctx = GET_CONTEXT(ctx); 226194676Sthompsa 227195957Salfred if (ctx == NULL) 228195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 229195957Salfred 230195957Salfred if (list == NULL) 231195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 232195957Salfred 233194676Sthompsa usb_backend = libusb20_be_alloc_default(); 234194676Sthompsa if (usb_backend == NULL) 235195957Salfred return (LIBUSB_ERROR_NO_MEM); 236194676Sthompsa 237195957Salfred /* figure out how many USB devices are present */ 238194676Sthompsa pdev = NULL; 239194676Sthompsa i = 0; 240194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) 241194676Sthompsa i++; 242194676Sthompsa 243195957Salfred /* allocate device pointer list */ 244194676Sthompsa *list = malloc((i + 1) * sizeof(void *)); 245194676Sthompsa if (*list == NULL) { 246194676Sthompsa libusb20_be_free(usb_backend); 247194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 248194676Sthompsa } 249195957Salfred /* create libusb v1.0 compliant devices */ 250194676Sthompsa i = 0; 251194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 252194676Sthompsa 253194676Sthompsa dev = malloc(sizeof(*dev)); 254194676Sthompsa if (dev == NULL) { 255195560Sthompsa while (i != 0) { 256195560Sthompsa libusb_unref_device((*list)[i - 1]); 257195560Sthompsa i--; 258195560Sthompsa } 259194676Sthompsa free(*list); 260195957Salfred *list = NULL; 261194676Sthompsa libusb20_be_free(usb_backend); 262194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 263194676Sthompsa } 264199055Sthompsa /* get device into libUSB v1.0 list */ 265199055Sthompsa libusb20_be_dequeue_device(usb_backend, pdev); 266199055Sthompsa 267194676Sthompsa memset(dev, 0, sizeof(*dev)); 268194676Sthompsa 269195957Salfred /* init transfer queues */ 270195957Salfred TAILQ_INIT(&dev->tr_head); 271195957Salfred 272195957Salfred /* set context we belong to */ 273194676Sthompsa dev->ctx = ctx; 274194676Sthompsa 275194676Sthompsa /* link together the two structures */ 276194676Sthompsa dev->os_priv = pdev; 277195957Salfred pdev->privLuData = dev; 278194676Sthompsa 279194676Sthompsa (*list)[i] = libusb_ref_device(dev); 280194676Sthompsa i++; 281194676Sthompsa } 282194676Sthompsa (*list)[i] = NULL; 283194676Sthompsa 284194676Sthompsa libusb20_be_free(usb_backend); 285194676Sthompsa return (i); 286194676Sthompsa} 287194676Sthompsa 288194676Sthompsavoid 289194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices) 290194676Sthompsa{ 291194676Sthompsa int i; 292194676Sthompsa 293194676Sthompsa if (list == NULL) 294195957Salfred return; /* be NULL safe */ 295194676Sthompsa 296194676Sthompsa if (unref_devices) { 297194676Sthompsa for (i = 0; list[i] != NULL; i++) 298194676Sthompsa libusb_unref_device(list[i]); 299194676Sthompsa } 300194676Sthompsa free(list); 301194676Sthompsa} 302194676Sthompsa 303194676Sthompsauint8_t 304195957Salfredlibusb_get_bus_number(libusb_device *dev) 305194676Sthompsa{ 306194676Sthompsa if (dev == NULL) 307195957Salfred return (0); /* should not happen */ 308195957Salfred return (libusb20_dev_get_bus_number(dev->os_priv)); 309194676Sthompsa} 310194676Sthompsa 311250342Semasteint 312251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) 313251495Semaste{ 314251495Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 315251495Semaste} 316251495Semaste 317251495Semasteint 318250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, 319250342Semaste uint8_t bufsize) 320250342Semaste{ 321250342Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 322250342Semaste} 323250342Semaste 324194676Sthompsauint8_t 325195957Salfredlibusb_get_device_address(libusb_device *dev) 326194676Sthompsa{ 327194676Sthompsa if (dev == NULL) 328195957Salfred return (0); /* should not happen */ 329195957Salfred return (libusb20_dev_get_address(dev->os_priv)); 330194676Sthompsa} 331194676Sthompsa 332224903Shselaskyenum libusb_speed 333224903Shselaskylibusb_get_device_speed(libusb_device *dev) 334224903Shselasky{ 335224903Shselasky if (dev == NULL) 336225035Shselasky return (LIBUSB_SPEED_UNKNOWN); /* should not happen */ 337224903Shselasky 338224903Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 339224903Shselasky case LIBUSB20_SPEED_LOW: 340224903Shselasky return (LIBUSB_SPEED_LOW); 341224903Shselasky case LIBUSB20_SPEED_FULL: 342224903Shselasky return (LIBUSB_SPEED_FULL); 343224903Shselasky case LIBUSB20_SPEED_HIGH: 344224903Shselasky return (LIBUSB_SPEED_HIGH); 345224903Shselasky case LIBUSB20_SPEED_SUPER: 346224903Shselasky return (LIBUSB_SPEED_SUPER); 347224903Shselasky default: 348224903Shselasky break; 349224903Shselasky } 350224903Shselasky return (LIBUSB_SPEED_UNKNOWN); 351224903Shselasky} 352224903Shselasky 353194676Sthompsaint 354195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint) 355194676Sthompsa{ 356194676Sthompsa struct libusb_config_descriptor *pdconf; 357194676Sthompsa struct libusb_interface *pinf; 358194676Sthompsa struct libusb_interface_descriptor *pdinf; 359194676Sthompsa struct libusb_endpoint_descriptor *pdend; 360195957Salfred int i; 361195957Salfred int j; 362195957Salfred int k; 363195957Salfred int ret; 364194676Sthompsa 365194676Sthompsa if (dev == NULL) 366194676Sthompsa return (LIBUSB_ERROR_NO_DEVICE); 367194676Sthompsa 368195957Salfred ret = libusb_get_active_config_descriptor(dev, &pdconf); 369195957Salfred if (ret < 0) 370195957Salfred return (ret); 371195957Salfred 372194676Sthompsa ret = LIBUSB_ERROR_NOT_FOUND; 373195957Salfred for (i = 0; i < pdconf->bNumInterfaces; i++) { 374194676Sthompsa pinf = &pdconf->interface[i]; 375195957Salfred for (j = 0; j < pinf->num_altsetting; j++) { 376194676Sthompsa pdinf = &pinf->altsetting[j]; 377195957Salfred for (k = 0; k < pdinf->bNumEndpoints; k++) { 378194676Sthompsa pdend = &pdinf->endpoint[k]; 379194676Sthompsa if (pdend->bEndpointAddress == endpoint) { 380194676Sthompsa ret = pdend->wMaxPacketSize; 381194676Sthompsa goto out; 382194676Sthompsa } 383194676Sthompsa } 384194676Sthompsa } 385194676Sthompsa } 386194676Sthompsa 387194676Sthompsaout: 388194676Sthompsa libusb_free_config_descriptor(pdconf); 389194676Sthompsa return (ret); 390194676Sthompsa} 391194676Sthompsa 392234193Shselaskyint 393234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint) 394234193Shselasky{ 395234193Shselasky int multiplier; 396234193Shselasky int ret; 397234193Shselasky 398234193Shselasky ret = libusb_get_max_packet_size(dev, endpoint); 399234193Shselasky 400234193Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 401234193Shselasky case LIBUSB20_SPEED_LOW: 402234193Shselasky case LIBUSB20_SPEED_FULL: 403234193Shselasky break; 404234193Shselasky default: 405234193Shselasky if (ret > -1) { 406234193Shselasky multiplier = (1 + ((ret >> 11) & 3)); 407234193Shselasky if (multiplier > 3) 408234193Shselasky multiplier = 3; 409234193Shselasky ret = (ret & 0x7FF) * multiplier; 410234193Shselasky } 411234193Shselasky break; 412234193Shselasky } 413234193Shselasky return (ret); 414234193Shselasky} 415234193Shselasky 416194676Sthompsalibusb_device * 417195957Salfredlibusb_ref_device(libusb_device *dev) 418194676Sthompsa{ 419194676Sthompsa if (dev == NULL) 420195957Salfred return (NULL); /* be NULL safe */ 421194676Sthompsa 422195957Salfred CTX_LOCK(dev->ctx); 423194676Sthompsa dev->refcnt++; 424195957Salfred CTX_UNLOCK(dev->ctx); 425194676Sthompsa 426194676Sthompsa return (dev); 427194676Sthompsa} 428194676Sthompsa 429194676Sthompsavoid 430195957Salfredlibusb_unref_device(libusb_device *dev) 431194676Sthompsa{ 432194676Sthompsa if (dev == NULL) 433195957Salfred return; /* be NULL safe */ 434194676Sthompsa 435195957Salfred CTX_LOCK(dev->ctx); 436194676Sthompsa dev->refcnt--; 437195957Salfred CTX_UNLOCK(dev->ctx); 438194676Sthompsa 439194676Sthompsa if (dev->refcnt == 0) { 440194676Sthompsa libusb20_dev_free(dev->os_priv); 441194676Sthompsa free(dev); 442194676Sthompsa } 443194676Sthompsa} 444194676Sthompsa 445194676Sthompsaint 446195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh) 447194676Sthompsa{ 448194676Sthompsa libusb_context *ctx = dev->ctx; 449194676Sthompsa struct libusb20_device *pdev = dev->os_priv; 450195957Salfred uint8_t dummy; 451194676Sthompsa int err; 452194676Sthompsa 453194676Sthompsa if (devh == NULL) 454194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 455194676Sthompsa 456195957Salfred /* set default device handle value */ 457195957Salfred *devh = NULL; 458194676Sthompsa 459195957Salfred dev = libusb_ref_device(dev); 460195957Salfred if (dev == NULL) 461195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 462195957Salfred 463301842Shselasky err = libusb20_dev_open(pdev, LIBUSB_NUM_SW_ENDPOINTS); 464194676Sthompsa if (err) { 465195957Salfred libusb_unref_device(dev); 466194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 467194676Sthompsa } 468195957Salfred libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 469194676Sthompsa POLLOUT | POLLRDNORM | POLLWRNORM); 470194676Sthompsa 471195957Salfred /* make sure our event loop detects the new device */ 472195957Salfred dummy = 0; 473194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 474213853Shselasky if (err < (int)sizeof(dummy)) { 475195957Salfred /* ignore error, if any */ 476195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!"); 477194676Sthompsa } 478195957Salfred *devh = pdev; 479194676Sthompsa 480194676Sthompsa return (0); 481194676Sthompsa} 482194676Sthompsa 483194676Sthompsalibusb_device_handle * 484195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, 485194676Sthompsa uint16_t product_id) 486194676Sthompsa{ 487194676Sthompsa struct libusb_device **devs; 488194676Sthompsa struct libusb20_device *pdev; 489194676Sthompsa struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 490195957Salfred int i; 491195957Salfred int j; 492194676Sthompsa 493195957Salfred ctx = GET_CONTEXT(ctx); 494195957Salfred if (ctx == NULL) 495195957Salfred return (NULL); /* be NULL safe */ 496195957Salfred 497195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter"); 498194676Sthompsa 499194676Sthompsa if ((i = libusb_get_device_list(ctx, &devs)) < 0) 500194676Sthompsa return (NULL); 501194676Sthompsa 502228236Shselasky pdev = NULL; 503194676Sthompsa for (j = 0; j < i; j++) { 504228236Shselasky struct libusb20_device *tdev; 505228236Shselasky 506228236Shselasky tdev = devs[j]->os_priv; 507228236Shselasky pdesc = libusb20_dev_get_device_desc(tdev); 508195957Salfred /* 509195957Salfred * NOTE: The USB library will automatically swap the 510195957Salfred * fields in the device descriptor to be of host 511195957Salfred * endian type! 512195957Salfred */ 513194676Sthompsa if (pdesc->idVendor == vendor_id && 514195560Sthompsa pdesc->idProduct == product_id) { 515228235Shselasky libusb_open(devs[j], &pdev); 516195957Salfred break; 517195560Sthompsa } 518194676Sthompsa } 519194676Sthompsa 520194676Sthompsa libusb_free_device_list(devs, 1); 521195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave"); 522195957Salfred return (pdev); 523194676Sthompsa} 524194676Sthompsa 525194676Sthompsavoid 526195957Salfredlibusb_close(struct libusb20_device *pdev) 527194676Sthompsa{ 528194676Sthompsa libusb_context *ctx; 529195957Salfred struct libusb_device *dev; 530195957Salfred uint8_t dummy; 531194676Sthompsa int err; 532194676Sthompsa 533195957Salfred if (pdev == NULL) 534195957Salfred return; /* be NULL safe */ 535194676Sthompsa 536195957Salfred dev = libusb_get_device(pdev); 537195957Salfred ctx = dev->ctx; 538194676Sthompsa 539195957Salfred libusb10_remove_pollfd(ctx, &dev->dev_poll); 540194676Sthompsa 541195957Salfred libusb20_dev_close(pdev); 542199055Sthompsa 543199055Sthompsa /* unref will free the "pdev" when the refcount reaches zero */ 544195957Salfred libusb_unref_device(dev); 545194676Sthompsa 546195957Salfred /* make sure our event loop detects the closed device */ 547195957Salfred dummy = 0; 548194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 549213853Shselasky if (err < (int)sizeof(dummy)) { 550195957Salfred /* ignore error, if any */ 551195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!"); 552194676Sthompsa } 553194676Sthompsa} 554194676Sthompsa 555194676Sthompsalibusb_device * 556195957Salfredlibusb_get_device(struct libusb20_device *pdev) 557194676Sthompsa{ 558195957Salfred if (pdev == NULL) 559194676Sthompsa return (NULL); 560195957Salfred return ((libusb_device *)pdev->privLuData); 561194676Sthompsa} 562194676Sthompsa 563194676Sthompsaint 564195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config) 565194676Sthompsa{ 566195957Salfred struct libusb20_config *pconf; 567194676Sthompsa 568195957Salfred if (pdev == NULL || config == NULL) 569194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 570194676Sthompsa 571195957Salfred pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); 572195957Salfred if (pconf == NULL) 573195957Salfred return (LIBUSB_ERROR_NO_MEM); 574194676Sthompsa 575195957Salfred *config = pconf->desc.bConfigurationValue; 576195957Salfred 577195957Salfred free(pconf); 578195957Salfred 579194676Sthompsa return (0); 580194676Sthompsa} 581194676Sthompsa 582194676Sthompsaint 583195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration) 584194676Sthompsa{ 585195957Salfred struct libusb20_config *pconf; 586195957Salfred struct libusb_device *dev; 587195957Salfred int err; 588195957Salfred uint8_t i; 589194676Sthompsa 590195957Salfred dev = libusb_get_device(pdev); 591195957Salfred if (dev == NULL) 592194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 593194676Sthompsa 594195957Salfred if (configuration < 1) { 595195957Salfred /* unconfigure */ 596195957Salfred i = 255; 597195957Salfred } else { 598195957Salfred for (i = 0; i != 255; i++) { 599195957Salfred uint8_t found; 600194676Sthompsa 601195957Salfred pconf = libusb20_dev_alloc_config(pdev, i); 602195957Salfred if (pconf == NULL) 603195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 604195957Salfred found = (pconf->desc.bConfigurationValue 605195957Salfred == configuration); 606195957Salfred free(pconf); 607195957Salfred 608195957Salfred if (found) 609195957Salfred goto set_config; 610195957Salfred } 611195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 612195957Salfred } 613195957Salfred 614195957Salfredset_config: 615195957Salfred 616195957Salfred libusb10_cancel_all_transfer(dev); 617195957Salfred 618195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 619195957Salfred 620195957Salfred err = libusb20_dev_set_config_index(pdev, i); 621195957Salfred 622195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 623195957Salfred POLLOUT | POLLRDNORM | POLLWRNORM); 624195957Salfred 625195957Salfred return (err ? LIBUSB_ERROR_INVALID_PARAM : 0); 626194676Sthompsa} 627194676Sthompsa 628194676Sthompsaint 629195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number) 630194676Sthompsa{ 631195957Salfred libusb_device *dev; 632194676Sthompsa 633195957Salfred dev = libusb_get_device(pdev); 634194676Sthompsa if (dev == NULL) 635194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 636194676Sthompsa 637195957Salfred if (interface_number < 0 || interface_number > 31) 638194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 639194676Sthompsa 640195957Salfred CTX_LOCK(dev->ctx); 641261224Shselasky dev->claimed_interfaces |= (1 << interface_number); 642261224Shselasky CTX_UNLOCK(dev->ctx); 643194676Sthompsa 644261224Shselasky return (0); 645194676Sthompsa} 646194676Sthompsa 647194676Sthompsaint 648195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number) 649194676Sthompsa{ 650195957Salfred libusb_device *dev; 651195957Salfred int err = 0; 652194676Sthompsa 653195957Salfred dev = libusb_get_device(pdev); 654194676Sthompsa if (dev == NULL) 655194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 656194676Sthompsa 657195957Salfred if (interface_number < 0 || interface_number > 31) 658194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 659194676Sthompsa 660195957Salfred CTX_LOCK(dev->ctx); 661194676Sthompsa if (!(dev->claimed_interfaces & (1 << interface_number))) 662195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 663194676Sthompsa 664195957Salfred if (!err) 665194676Sthompsa dev->claimed_interfaces &= ~(1 << interface_number); 666195957Salfred CTX_UNLOCK(dev->ctx); 667195957Salfred return (err); 668194676Sthompsa} 669194676Sthompsa 670194676Sthompsaint 671195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev, 672194676Sthompsa int interface_number, int alternate_setting) 673194676Sthompsa{ 674195957Salfred libusb_device *dev; 675195957Salfred int err = 0; 676194676Sthompsa 677195957Salfred dev = libusb_get_device(pdev); 678194676Sthompsa if (dev == NULL) 679194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 680194676Sthompsa 681195957Salfred if (interface_number < 0 || interface_number > 31) 682194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 683194676Sthompsa 684195957Salfred CTX_LOCK(dev->ctx); 685195957Salfred if (!(dev->claimed_interfaces & (1 << interface_number))) 686195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 687195957Salfred CTX_UNLOCK(dev->ctx); 688194676Sthompsa 689195957Salfred if (err) 690195957Salfred return (err); 691195957Salfred 692195957Salfred libusb10_cancel_all_transfer(dev); 693195957Salfred 694195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 695195957Salfred 696195957Salfred err = libusb20_dev_set_alt_index(pdev, 697195957Salfred interface_number, alternate_setting); 698195957Salfred 699195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 700195957Salfred pdev, libusb20_dev_get_fd(pdev), 701195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 702195957Salfred 703195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 704194676Sthompsa} 705194676Sthompsa 706195957Salfredstatic struct libusb20_transfer * 707195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev, 708234491Shselasky uint8_t endpoint, uint8_t xfer_index) 709195957Salfred{ 710234491Shselasky xfer_index &= 1; /* double buffering */ 711195957Salfred 712234491Shselasky xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4; 713195957Salfred 714195957Salfred if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) { 715195957Salfred /* this is an IN endpoint */ 716234491Shselasky xfer_index |= 2; 717195957Salfred } 718234491Shselasky return (libusb20_tr_get_pointer(pdev, xfer_index)); 719195957Salfred} 720195957Salfred 721194676Sthompsaint 722195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint) 723194676Sthompsa{ 724194676Sthompsa struct libusb20_transfer *xfer; 725195957Salfred struct libusb_device *dev; 726195957Salfred int err; 727194676Sthompsa 728195957Salfred xfer = libusb10_get_transfer(pdev, endpoint, 0); 729195560Sthompsa if (xfer == NULL) 730195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 731194676Sthompsa 732195957Salfred dev = libusb_get_device(pdev); 733213853Shselasky if (dev == NULL) 734213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 735195957Salfred 736195957Salfred CTX_LOCK(dev->ctx); 737223642Shselasky err = libusb20_tr_open(xfer, 0, 1, endpoint); 738195957Salfred CTX_UNLOCK(dev->ctx); 739195957Salfred 740195957Salfred if (err != 0 && err != LIBUSB20_ERROR_BUSY) 741194676Sthompsa return (LIBUSB_ERROR_OTHER); 742194676Sthompsa 743194676Sthompsa libusb20_tr_clear_stall_sync(xfer); 744195957Salfred 745195957Salfred /* check if we opened the transfer */ 746195957Salfred if (err == 0) { 747195957Salfred CTX_LOCK(dev->ctx); 748194676Sthompsa libusb20_tr_close(xfer); 749195957Salfred CTX_UNLOCK(dev->ctx); 750195957Salfred } 751195957Salfred return (0); /* success */ 752194676Sthompsa} 753194676Sthompsa 754194676Sthompsaint 755195957Salfredlibusb_reset_device(struct libusb20_device *pdev) 756194676Sthompsa{ 757195957Salfred libusb_device *dev; 758195957Salfred int err; 759194676Sthompsa 760195957Salfred dev = libusb_get_device(pdev); 761194676Sthompsa if (dev == NULL) 762213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 763194676Sthompsa 764195957Salfred libusb10_cancel_all_transfer(dev); 765195957Salfred 766195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 767195957Salfred 768195957Salfred err = libusb20_dev_reset(pdev); 769195957Salfred 770195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 771195957Salfred pdev, libusb20_dev_get_fd(pdev), 772195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 773195957Salfred 774195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 775194676Sthompsa} 776194676Sthompsa 777194676Sthompsaint 778213848Shselaskylibusb_check_connected(struct libusb20_device *pdev) 779213848Shselasky{ 780213848Shselasky libusb_device *dev; 781213848Shselasky int err; 782213848Shselasky 783213848Shselasky dev = libusb_get_device(pdev); 784213848Shselasky if (dev == NULL) 785213848Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 786213848Shselasky 787213848Shselasky err = libusb20_dev_check_connected(pdev); 788213848Shselasky 789213848Shselasky return (err ? LIBUSB_ERROR_NO_DEVICE : 0); 790213848Shselasky} 791213848Shselasky 792213848Shselaskyint 793195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface) 794194676Sthompsa{ 795195957Salfred if (pdev == NULL) 796194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 797194676Sthompsa 798226220Shselasky if (libusb20_dev_kernel_driver_active(pdev, interface)) 799226220Shselasky return (0); /* no kernel driver is active */ 800226220Shselasky else 801226220Shselasky return (1); /* kernel driver is active */ 802194676Sthompsa} 803194676Sthompsa 804194676Sthompsaint 805213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface, 806213853Shselasky char *name, int namelen) 807213853Shselasky{ 808213853Shselasky return (libusb_get_driver(pdev, interface, name, namelen)); 809213853Shselasky} 810213853Shselasky 811213853Shselaskyint 812213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface, 813213853Shselasky char *name, int namelen) 814213853Shselasky{ 815213853Shselasky char *ptr; 816213853Shselasky int err; 817213853Shselasky 818213853Shselasky if (pdev == NULL) 819213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 820213853Shselasky if (namelen < 1) 821213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 822224085Shselasky if (namelen > 255) 823224085Shselasky namelen = 255; 824213853Shselasky 825213853Shselasky err = libusb20_dev_get_iface_desc( 826213853Shselasky pdev, interface, name, namelen); 827213853Shselasky 828213853Shselasky if (err != 0) 829213853Shselasky return (LIBUSB_ERROR_OTHER); 830213853Shselasky 831213853Shselasky /* we only want the driver name */ 832213853Shselasky ptr = strstr(name, ":"); 833213853Shselasky if (ptr != NULL) 834213853Shselasky *ptr = 0; 835213853Shselasky 836213853Shselasky return (0); 837213853Shselasky} 838213853Shselasky 839213853Shselaskyint 840213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface) 841213853Shselasky{ 842213853Shselasky return (libusb_detach_kernel_driver(pdev, interface)); 843213853Shselasky} 844213853Shselasky 845213853Shselaskyint 846195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface) 847194676Sthompsa{ 848195957Salfred int err; 849194676Sthompsa 850195957Salfred if (pdev == NULL) 851194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 852194676Sthompsa 853195957Salfred err = libusb20_dev_detach_kernel_driver( 854195957Salfred pdev, interface); 855194676Sthompsa 856213853Shselasky return (err ? LIBUSB_ERROR_OTHER : 0); 857194676Sthompsa} 858194676Sthompsa 859194676Sthompsaint 860195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface) 861194676Sthompsa{ 862195957Salfred if (pdev == NULL) 863194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 864195957Salfred /* stub - currently not supported by libusb20 */ 865194676Sthompsa return (0); 866194676Sthompsa} 867194676Sthompsa 868194676Sthompsa/* Asynchronous device I/O */ 869194676Sthompsa 870194676Sthompsastruct libusb_transfer * 871194676Sthompsalibusb_alloc_transfer(int iso_packets) 872194676Sthompsa{ 873195957Salfred struct libusb_transfer *uxfer; 874195957Salfred struct libusb_super_transfer *sxfer; 875194676Sthompsa int len; 876194676Sthompsa 877194676Sthompsa len = sizeof(struct libusb_transfer) + 878195957Salfred sizeof(struct libusb_super_transfer) + 879194676Sthompsa (iso_packets * sizeof(libusb_iso_packet_descriptor)); 880194676Sthompsa 881195957Salfred sxfer = malloc(len); 882195957Salfred if (sxfer == NULL) 883194676Sthompsa return (NULL); 884194676Sthompsa 885195957Salfred memset(sxfer, 0, len); 886194676Sthompsa 887195957Salfred uxfer = (struct libusb_transfer *)( 888195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 889194676Sthompsa 890195957Salfred /* set default value */ 891195957Salfred uxfer->num_iso_packets = iso_packets; 892195957Salfred 893195957Salfred return (uxfer); 894194676Sthompsa} 895194676Sthompsa 896194676Sthompsavoid 897195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer) 898194676Sthompsa{ 899195957Salfred struct libusb_super_transfer *sxfer; 900194676Sthompsa 901195957Salfred if (uxfer == NULL) 902195957Salfred return; /* be NULL safe */ 903194676Sthompsa 904215253Shselasky /* check if we should free the transfer buffer */ 905215253Shselasky if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 906215253Shselasky free(uxfer->buffer); 907215253Shselasky 908195957Salfred sxfer = (struct libusb_super_transfer *)( 909195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 910194676Sthompsa 911195957Salfred free(sxfer); 912194676Sthompsa} 913194676Sthompsa 914219100Shselaskystatic uint32_t 915195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 916195560Sthompsa{ 917219100Shselasky uint32_t ret; 918195560Sthompsa 919195560Sthompsa switch (xfer->type) { 920195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 921219100Shselasky ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE; /* 60ms */ 922195957Salfred break; 923195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 924195560Sthompsa ret = 2; 925195957Salfred break; 926195560Sthompsa default: 927195560Sthompsa ret = 1; 928195957Salfred break; 929195560Sthompsa } 930195957Salfred return (ret); 931195560Sthompsa} 932195560Sthompsa 933195560Sthompsastatic int 934195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 935195560Sthompsa{ 936195560Sthompsa int ret; 937195560Sthompsa int usb_speed; 938195560Sthompsa 939195560Sthompsa usb_speed = libusb20_dev_get_speed(pdev); 940195560Sthompsa 941195560Sthompsa switch (xfer->type) { 942195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 943195957Salfred ret = 0; /* kernel will auto-select */ 944195957Salfred break; 945195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 946195957Salfred ret = 1024; 947195957Salfred break; 948195957Salfred default: 949195560Sthompsa switch (usb_speed) { 950195957Salfred case LIBUSB20_SPEED_LOW: 951195957Salfred ret = 256; 952195957Salfred break; 953195957Salfred case LIBUSB20_SPEED_FULL: 954195957Salfred ret = 4096; 955195957Salfred break; 956264344Shselasky case LIBUSB20_SPEED_SUPER: 957264344Shselasky ret = 65536; 958264344Shselasky break; 959195957Salfred default: 960195957Salfred ret = 16384; 961195957Salfred break; 962195560Sthompsa } 963195957Salfred break; 964195560Sthompsa } 965195957Salfred return (ret); 966195560Sthompsa} 967195560Sthompsa 968195957Salfredstatic int 969195957Salfredlibusb10_convert_error(uint8_t status) 970195957Salfred{ 971195957Salfred ; /* indent fix */ 972195957Salfred 973195957Salfred switch (status) { 974195957Salfred case LIBUSB20_TRANSFER_START: 975195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 976195957Salfred return (LIBUSB_TRANSFER_COMPLETED); 977195957Salfred case LIBUSB20_TRANSFER_OVERFLOW: 978195957Salfred return (LIBUSB_TRANSFER_OVERFLOW); 979195957Salfred case LIBUSB20_TRANSFER_NO_DEVICE: 980195957Salfred return (LIBUSB_TRANSFER_NO_DEVICE); 981195957Salfred case LIBUSB20_TRANSFER_STALL: 982195957Salfred return (LIBUSB_TRANSFER_STALL); 983195957Salfred case LIBUSB20_TRANSFER_CANCELLED: 984195957Salfred return (LIBUSB_TRANSFER_CANCELLED); 985195957Salfred case LIBUSB20_TRANSFER_TIMED_OUT: 986195957Salfred return (LIBUSB_TRANSFER_TIMED_OUT); 987195957Salfred default: 988195957Salfred return (LIBUSB_TRANSFER_ERROR); 989195957Salfred } 990195957Salfred} 991195957Salfred 992195957Salfred/* This function must be called locked */ 993195957Salfred 994194676Sthompsastatic void 995195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer, 996195957Salfred struct libusb_super_transfer *sxfer, int status) 997194676Sthompsa{ 998195957Salfred struct libusb_transfer *uxfer; 999195957Salfred struct libusb_device *dev; 1000195957Salfred 1001195957Salfred uxfer = (struct libusb_transfer *)( 1002195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1003195957Salfred 1004195957Salfred if (pxfer != NULL) 1005195957Salfred libusb20_tr_set_priv_sc1(pxfer, NULL); 1006195957Salfred 1007199575Sthompsa /* set transfer status */ 1008195957Salfred uxfer->status = status; 1009195957Salfred 1010199575Sthompsa /* update super transfer state */ 1011199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_NONE; 1012199575Sthompsa 1013195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1014195957Salfred 1015195957Salfred TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); 1016195957Salfred} 1017195957Salfred 1018195957Salfred/* This function must be called locked */ 1019195957Salfred 1020195957Salfredstatic void 1021195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer) 1022195957Salfred{ 1023195957Salfred struct libusb_super_transfer *sxfer; 1024195957Salfred struct libusb_transfer *uxfer; 1025195957Salfred uint32_t actlen; 1026195957Salfred uint16_t iso_packets; 1027195957Salfred uint16_t i; 1028194676Sthompsa uint8_t status; 1029194676Sthompsa 1030195957Salfred status = libusb20_tr_get_status(pxfer); 1031195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1032195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1033195957Salfred iso_packets = libusb20_tr_get_max_frames(pxfer); 1034194676Sthompsa 1035195957Salfred if (sxfer == NULL) 1036284744Saraujo return; /* cancelled - nothing to do */ 1037195957Salfred 1038195957Salfred uxfer = (struct libusb_transfer *)( 1039195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1040195957Salfred 1041195957Salfred if (iso_packets > uxfer->num_iso_packets) 1042195957Salfred iso_packets = uxfer->num_iso_packets; 1043195957Salfred 1044195957Salfred if (iso_packets == 0) 1045284744Saraujo return; /* nothing to do */ 1046195957Salfred 1047195957Salfred /* make sure that the number of ISOCHRONOUS packets is valid */ 1048195957Salfred uxfer->num_iso_packets = iso_packets; 1049195957Salfred 1050194676Sthompsa switch (status) { 1051194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1052195957Salfred /* update actual length */ 1053195957Salfred uxfer->actual_length = actlen; 1054195957Salfred for (i = 0; i != iso_packets; i++) { 1055195957Salfred uxfer->iso_packet_desc[i].actual_length = 1056195957Salfred libusb20_tr_get_length(pxfer, i); 1057195957Salfred } 1058195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1059195957Salfred break; 1060194676Sthompsa case LIBUSB20_TRANSFER_START: 1061195957Salfred /* setup length(s) */ 1062195957Salfred actlen = 0; 1063195957Salfred for (i = 0; i != iso_packets; i++) { 1064195957Salfred libusb20_tr_setup_isoc(pxfer, 1065195957Salfred &uxfer->buffer[actlen], 1066195957Salfred uxfer->iso_packet_desc[i].length, i); 1067195957Salfred actlen += uxfer->iso_packet_desc[i].length; 1068194676Sthompsa } 1069195957Salfred 1070195957Salfred /* no remainder */ 1071195957Salfred sxfer->rem_len = 0; 1072195957Salfred 1073195957Salfred libusb20_tr_set_total_frames(pxfer, iso_packets); 1074195957Salfred libusb20_tr_submit(pxfer); 1075195957Salfred 1076195957Salfred /* fork another USB transfer, if any */ 1077195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1078195957Salfred break; 1079194676Sthompsa default: 1080195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1081195957Salfred break; 1082194676Sthompsa } 1083195957Salfred} 1084194676Sthompsa 1085195957Salfred/* This function must be called locked */ 1086195957Salfred 1087195957Salfredstatic void 1088195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) 1089195957Salfred{ 1090195957Salfred struct libusb_super_transfer *sxfer; 1091195957Salfred struct libusb_transfer *uxfer; 1092195957Salfred uint32_t max_bulk; 1093195957Salfred uint32_t actlen; 1094195957Salfred uint8_t status; 1095195957Salfred uint8_t flags; 1096195957Salfred 1097195957Salfred status = libusb20_tr_get_status(pxfer); 1098195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1099195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1100195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1101195957Salfred 1102195957Salfred if (sxfer == NULL) 1103195957Salfred return; /* cancelled - nothing to do */ 1104195957Salfred 1105195957Salfred uxfer = (struct libusb_transfer *)( 1106195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1107195957Salfred 1108195957Salfred flags = uxfer->flags; 1109195957Salfred 1110194676Sthompsa switch (status) { 1111194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1112195957Salfred 1113195957Salfred uxfer->actual_length += actlen; 1114195957Salfred 1115195957Salfred /* check for short packet */ 1116195957Salfred if (sxfer->last_len != actlen) { 1117195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1118195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1119195957Salfred } else { 1120195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1121195957Salfred } 1122195957Salfred break; 1123195957Salfred } 1124195957Salfred /* check for end of data */ 1125195957Salfred if (sxfer->rem_len == 0) { 1126195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1127195957Salfred break; 1128195957Salfred } 1129195957Salfred /* FALLTHROUGH */ 1130195957Salfred 1131195957Salfred case LIBUSB20_TRANSFER_START: 1132195957Salfred if (max_bulk > sxfer->rem_len) { 1133195957Salfred max_bulk = sxfer->rem_len; 1134195957Salfred } 1135195957Salfred /* setup new BULK or INTERRUPT transaction */ 1136195957Salfred libusb20_tr_setup_bulk(pxfer, 1137195957Salfred sxfer->curr_data, max_bulk, uxfer->timeout); 1138195957Salfred 1139195957Salfred /* update counters */ 1140195957Salfred sxfer->last_len = max_bulk; 1141195957Salfred sxfer->curr_data += max_bulk; 1142195957Salfred sxfer->rem_len -= max_bulk; 1143195957Salfred 1144195957Salfred libusb20_tr_submit(pxfer); 1145195957Salfred 1146195957Salfred /* check if we can fork another USB transfer */ 1147195957Salfred if (sxfer->rem_len == 0) 1148195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1149195957Salfred break; 1150195957Salfred 1151195957Salfred default: 1152195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1153195957Salfred break; 1154194676Sthompsa } 1155194676Sthompsa} 1156194676Sthompsa 1157195957Salfred/* This function must be called locked */ 1158195957Salfred 1159195957Salfredstatic void 1160195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer) 1161194676Sthompsa{ 1162195957Salfred struct libusb_super_transfer *sxfer; 1163195957Salfred struct libusb_transfer *uxfer; 1164195957Salfred uint32_t max_bulk; 1165195957Salfred uint32_t actlen; 1166195957Salfred uint8_t status; 1167195957Salfred uint8_t flags; 1168194676Sthompsa 1169195957Salfred status = libusb20_tr_get_status(pxfer); 1170195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1171195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1172195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1173194676Sthompsa 1174195957Salfred if (sxfer == NULL) 1175195957Salfred return; /* cancelled - nothing to do */ 1176194676Sthompsa 1177195957Salfred uxfer = (struct libusb_transfer *)( 1178195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1179194676Sthompsa 1180195957Salfred flags = uxfer->flags; 1181194676Sthompsa 1182195957Salfred switch (status) { 1183195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1184194676Sthompsa 1185195957Salfred uxfer->actual_length += actlen; 1186195957Salfred 1187195957Salfred /* subtract length of SETUP packet, if any */ 1188195957Salfred actlen -= libusb20_tr_get_length(pxfer, 0); 1189195957Salfred 1190195957Salfred /* check for short packet */ 1191195957Salfred if (sxfer->last_len != actlen) { 1192195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1193195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1194195957Salfred } else { 1195195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1196195957Salfred } 1197195957Salfred break; 1198194676Sthompsa } 1199195957Salfred /* check for end of data */ 1200195957Salfred if (sxfer->rem_len == 0) { 1201195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1202195957Salfred break; 1203195957Salfred } 1204195957Salfred /* FALLTHROUGH */ 1205194676Sthompsa 1206195957Salfred case LIBUSB20_TRANSFER_START: 1207195957Salfred if (max_bulk > sxfer->rem_len) { 1208195957Salfred max_bulk = sxfer->rem_len; 1209195957Salfred } 1210195957Salfred /* setup new CONTROL transaction */ 1211195957Salfred if (status == LIBUSB20_TRANSFER_COMPLETED) { 1212195957Salfred /* next fragment - don't send SETUP packet */ 1213195957Salfred libusb20_tr_set_length(pxfer, 0, 0); 1214195957Salfred } else { 1215195957Salfred /* first fragment - send SETUP packet */ 1216195957Salfred libusb20_tr_set_length(pxfer, 8, 0); 1217195957Salfred libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0); 1218195957Salfred } 1219195957Salfred 1220195957Salfred if (max_bulk != 0) { 1221195957Salfred libusb20_tr_set_length(pxfer, max_bulk, 1); 1222195957Salfred libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1); 1223195957Salfred libusb20_tr_set_total_frames(pxfer, 2); 1224195957Salfred } else { 1225195957Salfred libusb20_tr_set_total_frames(pxfer, 1); 1226195957Salfred } 1227195957Salfred 1228195957Salfred /* update counters */ 1229195957Salfred sxfer->last_len = max_bulk; 1230195957Salfred sxfer->curr_data += max_bulk; 1231195957Salfred sxfer->rem_len -= max_bulk; 1232195957Salfred 1233195957Salfred libusb20_tr_submit(pxfer); 1234195957Salfred 1235195957Salfred /* check if we can fork another USB transfer */ 1236195957Salfred if (sxfer->rem_len == 0) 1237195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1238195957Salfred break; 1239195957Salfred 1240195957Salfred default: 1241195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1242195957Salfred break; 1243194676Sthompsa } 1244195957Salfred} 1245195957Salfred 1246195957Salfred/* The following function must be called locked */ 1247195957Salfred 1248195957Salfredstatic void 1249195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint) 1250195957Salfred{ 1251195957Salfred struct libusb20_transfer *pxfer0; 1252195957Salfred struct libusb20_transfer *pxfer1; 1253195957Salfred struct libusb_super_transfer *sxfer; 1254195957Salfred struct libusb_transfer *uxfer; 1255195957Salfred struct libusb_device *dev; 1256195957Salfred int err; 1257195957Salfred int buffsize; 1258195957Salfred int maxframe; 1259195957Salfred int temp; 1260195957Salfred uint8_t dummy; 1261195957Salfred 1262195957Salfred dev = libusb_get_device(pdev); 1263195957Salfred 1264195957Salfred pxfer0 = libusb10_get_transfer(pdev, endpoint, 0); 1265195957Salfred pxfer1 = libusb10_get_transfer(pdev, endpoint, 1); 1266195957Salfred 1267195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) 1268195957Salfred return; /* shouldn't happen */ 1269195957Salfred 1270195957Salfred temp = 0; 1271195957Salfred if (libusb20_tr_pending(pxfer0)) 1272195957Salfred temp |= 1; 1273195957Salfred if (libusb20_tr_pending(pxfer1)) 1274195957Salfred temp |= 2; 1275195957Salfred 1276195957Salfred switch (temp) { 1277195957Salfred case 3: 1278195957Salfred /* wait till one of the transfers complete */ 1279195957Salfred return; 1280195957Salfred case 2: 1281195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer1); 1282199575Sthompsa if (sxfer == NULL) 1283199575Sthompsa return; /* cancelling */ 1284195957Salfred if (sxfer->rem_len) 1285195957Salfred return; /* cannot queue another one */ 1286195957Salfred /* swap transfers */ 1287195957Salfred pxfer1 = pxfer0; 1288195957Salfred break; 1289195957Salfred case 1: 1290195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer0); 1291199575Sthompsa if (sxfer == NULL) 1292199575Sthompsa return; /* cancelling */ 1293195957Salfred if (sxfer->rem_len) 1294195957Salfred return; /* cannot queue another one */ 1295195957Salfred /* swap transfers */ 1296195957Salfred pxfer0 = pxfer1; 1297195957Salfred break; 1298195957Salfred default: 1299195957Salfred break; 1300194676Sthompsa } 1301195957Salfred 1302195957Salfred /* find next transfer on same endpoint */ 1303195957Salfred TAILQ_FOREACH(sxfer, &dev->tr_head, entry) { 1304195957Salfred 1305195957Salfred uxfer = (struct libusb_transfer *)( 1306195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1307195957Salfred 1308195957Salfred if (uxfer->endpoint == endpoint) { 1309195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1310195957Salfred sxfer->entry.tqe_prev = NULL; 1311195957Salfred goto found; 1312194676Sthompsa } 1313195957Salfred } 1314195957Salfred return; /* success */ 1315194676Sthompsa 1316195957Salfredfound: 1317194676Sthompsa 1318195957Salfred libusb20_tr_set_priv_sc0(pxfer0, pdev); 1319195957Salfred libusb20_tr_set_priv_sc1(pxfer0, sxfer); 1320194676Sthompsa 1321195957Salfred /* reset super transfer state */ 1322195957Salfred sxfer->rem_len = uxfer->length; 1323195957Salfred sxfer->curr_data = uxfer->buffer; 1324195957Salfred uxfer->actual_length = 0; 1325194676Sthompsa 1326195957Salfred switch (uxfer->type) { 1327195957Salfred case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1328195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); 1329195957Salfred break; 1330195957Salfred case LIBUSB_TRANSFER_TYPE_BULK: 1331195957Salfred case LIBUSB_TRANSFER_TYPE_INTERRUPT: 1332195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); 1333195957Salfred break; 1334195957Salfred case LIBUSB_TRANSFER_TYPE_CONTROL: 1335195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); 1336195957Salfred if (sxfer->rem_len < 8) 1337195957Salfred goto failure; 1338194676Sthompsa 1339195957Salfred /* remove SETUP packet from data */ 1340195957Salfred sxfer->rem_len -= 8; 1341195957Salfred sxfer->curr_data += 8; 1342195957Salfred break; 1343195957Salfred default: 1344195957Salfred goto failure; 1345195560Sthompsa } 1346195957Salfred 1347195957Salfred buffsize = libusb10_get_buffsize(pdev, uxfer); 1348195957Salfred maxframe = libusb10_get_maxframe(pdev, uxfer); 1349195957Salfred 1350195957Salfred /* make sure the transfer is opened */ 1351195957Salfred err = libusb20_tr_open(pxfer0, buffsize, maxframe, endpoint); 1352195957Salfred if (err && (err != LIBUSB20_ERROR_BUSY)) { 1353195957Salfred goto failure; 1354194676Sthompsa } 1355195957Salfred libusb20_tr_start(pxfer0); 1356195957Salfred return; 1357194676Sthompsa 1358195957Salfredfailure: 1359195957Salfred libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); 1360194676Sthompsa 1361195957Salfred /* make sure our event loop spins the done handler */ 1362195957Salfred dummy = 0; 1363248236Shselasky err = write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 1364195957Salfred} 1365194676Sthompsa 1366195957Salfred/* The following function must be called unlocked */ 1367194676Sthompsa 1368195957Salfredint 1369195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer) 1370195957Salfred{ 1371195957Salfred struct libusb20_transfer *pxfer0; 1372195957Salfred struct libusb20_transfer *pxfer1; 1373195957Salfred struct libusb_super_transfer *sxfer; 1374195957Salfred struct libusb_device *dev; 1375234684Shselasky uint8_t endpoint; 1376195957Salfred int err; 1377195957Salfred 1378195957Salfred if (uxfer == NULL) 1379195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1380195957Salfred 1381195957Salfred if (uxfer->dev_handle == NULL) 1382195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1383195957Salfred 1384195957Salfred endpoint = uxfer->endpoint; 1385195957Salfred 1386195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1387195957Salfred 1388195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); 1389195957Salfred 1390195957Salfred sxfer = (struct libusb_super_transfer *)( 1391195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1392195957Salfred 1393195957Salfred CTX_LOCK(dev->ctx); 1394195957Salfred 1395195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1396195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1397195957Salfred 1398195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) { 1399195957Salfred err = LIBUSB_ERROR_OTHER; 1400195957Salfred } else if ((sxfer->entry.tqe_prev != NULL) || 1401199575Sthompsa (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) || 1402195957Salfred (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) { 1403195957Salfred err = LIBUSB_ERROR_BUSY; 1404195957Salfred } else { 1405199575Sthompsa 1406199575Sthompsa /* set pending state */ 1407199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_PEND; 1408199575Sthompsa 1409199575Sthompsa /* insert transfer into transfer head list */ 1410195957Salfred TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry); 1411195957Salfred 1412199575Sthompsa /* start work transfers */ 1413195957Salfred libusb10_submit_transfer_sub( 1414195957Salfred uxfer->dev_handle, endpoint); 1415195957Salfred 1416195957Salfred err = 0; /* success */ 1417195957Salfred } 1418195957Salfred 1419195957Salfred CTX_UNLOCK(dev->ctx); 1420195957Salfred 1421195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); 1422195957Salfred 1423195957Salfred return (err); 1424194676Sthompsa} 1425194676Sthompsa 1426195957Salfred/* Asynchronous transfer cancel */ 1427195957Salfred 1428194676Sthompsaint 1429195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer) 1430194676Sthompsa{ 1431195957Salfred struct libusb20_transfer *pxfer0; 1432195957Salfred struct libusb20_transfer *pxfer1; 1433195957Salfred struct libusb_super_transfer *sxfer; 1434195957Salfred struct libusb_device *dev; 1435234684Shselasky uint8_t endpoint; 1436199575Sthompsa int retval; 1437194676Sthompsa 1438195957Salfred if (uxfer == NULL) 1439195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1440194676Sthompsa 1441199575Sthompsa /* check if not initialised */ 1442195957Salfred if (uxfer->dev_handle == NULL) 1443199575Sthompsa return (LIBUSB_ERROR_NOT_FOUND); 1444194676Sthompsa 1445195957Salfred endpoint = uxfer->endpoint; 1446194676Sthompsa 1447195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1448195957Salfred 1449195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); 1450195957Salfred 1451195957Salfred sxfer = (struct libusb_super_transfer *)( 1452195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1453195957Salfred 1454199575Sthompsa retval = 0; 1455199575Sthompsa 1456195957Salfred CTX_LOCK(dev->ctx); 1457195957Salfred 1458195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1459195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1460195957Salfred 1461199575Sthompsa if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { 1462199575Sthompsa /* only update the transfer status */ 1463199575Sthompsa uxfer->status = LIBUSB_TRANSFER_CANCELLED; 1464199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1465199575Sthompsa } else if (sxfer->entry.tqe_prev != NULL) { 1466195957Salfred /* we are lucky - transfer is on a queue */ 1467195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1468195957Salfred sxfer->entry.tqe_prev = NULL; 1469199575Sthompsa libusb10_complete_transfer(NULL, 1470199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1471195957Salfred } else if (pxfer0 == NULL || pxfer1 == NULL) { 1472195957Salfred /* not started */ 1473199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1474195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { 1475199575Sthompsa libusb10_complete_transfer(pxfer0, 1476199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1477195957Salfred libusb20_tr_stop(pxfer0); 1478195957Salfred /* make sure the queue doesn't stall */ 1479195957Salfred libusb10_submit_transfer_sub( 1480195957Salfred uxfer->dev_handle, endpoint); 1481195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { 1482199575Sthompsa libusb10_complete_transfer(pxfer1, 1483199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1484195957Salfred libusb20_tr_stop(pxfer1); 1485195957Salfred /* make sure the queue doesn't stall */ 1486195957Salfred libusb10_submit_transfer_sub( 1487195957Salfred uxfer->dev_handle, endpoint); 1488195957Salfred } else { 1489195957Salfred /* not started */ 1490199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1491195957Salfred } 1492195957Salfred 1493195957Salfred CTX_UNLOCK(dev->ctx); 1494195957Salfred 1495195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); 1496195957Salfred 1497199575Sthompsa return (retval); 1498194676Sthompsa} 1499194676Sthompsa 1500195957SalfredUNEXPORTED void 1501195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev) 1502195957Salfred{ 1503301842Shselasky struct libusb20_device *pdev = dev->os_priv; 1504301842Shselasky unsigned x; 1505301842Shselasky 1506301842Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1507301842Shselasky struct libusb20_transfer *xfer; 1508301842Shselasky 1509301842Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1510301842Shselasky if (xfer == NULL) 1511301842Shselasky continue; 1512301842Shselasky libusb20_tr_close(xfer); 1513301842Shselasky } 1514195957Salfred} 1515199055Sthompsa 1516199055Sthompsauint16_t 1517199055Sthompsalibusb_cpu_to_le16(uint16_t x) 1518199055Sthompsa{ 1519199055Sthompsa return (htole16(x)); 1520199055Sthompsa} 1521199055Sthompsa 1522199055Sthompsauint16_t 1523199055Sthompsalibusb_le16_to_cpu(uint16_t x) 1524199055Sthompsa{ 1525199055Sthompsa return (le16toh(x)); 1526199055Sthompsa} 1527199055Sthompsa 1528213853Shselaskyconst char * 1529213853Shselaskylibusb_strerror(int code) 1530213853Shselasky{ 1531225659Shselasky switch (code) { 1532225659Shselasky case LIBUSB_SUCCESS: 1533225659Shselasky return ("Success"); 1534225659Shselasky case LIBUSB_ERROR_IO: 1535225659Shselasky return ("I/O error"); 1536225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1537225659Shselasky return ("Invalid parameter"); 1538225659Shselasky case LIBUSB_ERROR_ACCESS: 1539225659Shselasky return ("Permissions error"); 1540225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1541225659Shselasky return ("No device"); 1542225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1543225659Shselasky return ("Not found"); 1544225659Shselasky case LIBUSB_ERROR_BUSY: 1545225659Shselasky return ("Device busy"); 1546225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1547225659Shselasky return ("Timeout"); 1548225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1549225659Shselasky return ("Overflow"); 1550225659Shselasky case LIBUSB_ERROR_PIPE: 1551225659Shselasky return ("Pipe error"); 1552225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1553225659Shselasky return ("Interrupted"); 1554225659Shselasky case LIBUSB_ERROR_NO_MEM: 1555225659Shselasky return ("Out of memory"); 1556225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1557225659Shselasky return ("Not supported"); 1558225659Shselasky case LIBUSB_ERROR_OTHER: 1559225659Shselasky return ("Other error"); 1560225659Shselasky default: 1561225659Shselasky return ("Unknown error"); 1562225659Shselasky } 1563213853Shselasky} 1564225659Shselasky 1565225659Shselaskyconst char * 1566225659Shselaskylibusb_error_name(int code) 1567225659Shselasky{ 1568225659Shselasky switch (code) { 1569225659Shselasky case LIBUSB_SUCCESS: 1570225659Shselasky return ("LIBUSB_SUCCESS"); 1571225659Shselasky case LIBUSB_ERROR_IO: 1572225659Shselasky return ("LIBUSB_ERROR_IO"); 1573225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1574225659Shselasky return ("LIBUSB_ERROR_INVALID_PARAM"); 1575225659Shselasky case LIBUSB_ERROR_ACCESS: 1576225659Shselasky return ("LIBUSB_ERROR_ACCESS"); 1577225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1578225659Shselasky return ("LIBUSB_ERROR_NO_DEVICE"); 1579225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1580225659Shselasky return ("LIBUSB_ERROR_NOT_FOUND"); 1581225659Shselasky case LIBUSB_ERROR_BUSY: 1582225659Shselasky return ("LIBUSB_ERROR_BUSY"); 1583225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1584225659Shselasky return ("LIBUSB_ERROR_TIMEOUT"); 1585225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1586225659Shselasky return ("LIBUSB_ERROR_OVERFLOW"); 1587225659Shselasky case LIBUSB_ERROR_PIPE: 1588225659Shselasky return ("LIBUSB_ERROR_PIPE"); 1589225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1590225659Shselasky return ("LIBUSB_ERROR_INTERRUPTED"); 1591225659Shselasky case LIBUSB_ERROR_NO_MEM: 1592225659Shselasky return ("LIBUSB_ERROR_NO_MEM"); 1593225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1594225659Shselasky return ("LIBUSB_ERROR_NOT_SUPPORTED"); 1595225659Shselasky case LIBUSB_ERROR_OTHER: 1596225659Shselasky return ("LIBUSB_ERROR_OTHER"); 1597225659Shselasky default: 1598225659Shselasky return ("LIBUSB_ERROR_UNKNOWN"); 1599225659Shselasky } 1600225659Shselasky} 1601