1194676Sthompsa/* $FreeBSD$ */ 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 54194676Sthompsastatic pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER; 55194676Sthompsastruct libusb_context *usbi_default_context = NULL; 56194676Sthompsa 57195957Salfred/* Prototypes */ 58195957Salfred 59195957Salfredstatic struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *, uint8_t, uint8_t); 60195957Salfredstatic int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *); 61195957Salfredstatic int libusb10_convert_error(uint8_t status); 62195957Salfredstatic void libusb10_complete_transfer(struct libusb20_transfer *, struct libusb_super_transfer *, int); 63195957Salfredstatic void libusb10_isoc_proxy(struct libusb20_transfer *); 64195957Salfredstatic void libusb10_bulk_intr_proxy(struct libusb20_transfer *); 65195957Salfredstatic void libusb10_ctrl_proxy(struct libusb20_transfer *); 66195957Salfredstatic void libusb10_submit_transfer_sub(struct libusb20_device *, uint8_t); 67195957Salfred 68194676Sthompsa/* Library initialisation / deinitialisation */ 69194676Sthompsa 70194676Sthompsavoid 71195957Salfredlibusb_set_debug(libusb_context *ctx, int level) 72194676Sthompsa{ 73195957Salfred ctx = GET_CONTEXT(ctx); 74194676Sthompsa if (ctx) 75194676Sthompsa ctx->debug = level; 76194676Sthompsa} 77194676Sthompsa 78213853Shselaskystatic void 79213853Shselaskylibusb_set_nonblocking(int f) 80213853Shselasky{ 81213853Shselasky int flags; 82213853Shselasky 83213853Shselasky /* 84213853Shselasky * We ignore any failures in this function, hence the 85213853Shselasky * non-blocking flag is not critical to the operation of 86213853Shselasky * libUSB. We use F_GETFL and F_SETFL to be compatible with 87213853Shselasky * Linux. 88213853Shselasky */ 89213853Shselasky 90213853Shselasky flags = fcntl(f, F_GETFL, NULL); 91213853Shselasky if (flags == -1) 92213853Shselasky return; 93213853Shselasky flags |= O_NONBLOCK; 94213853Shselasky fcntl(f, F_SETFL, flags); 95213853Shselasky} 96213853Shselasky 97194676Sthompsaint 98195957Salfredlibusb_init(libusb_context **context) 99194676Sthompsa{ 100194676Sthompsa struct libusb_context *ctx; 101236944Shselasky pthread_condattr_t attr; 102195957Salfred char *debug; 103194676Sthompsa int ret; 104194676Sthompsa 105194676Sthompsa ctx = malloc(sizeof(*ctx)); 106194676Sthompsa if (!ctx) 107194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 108194676Sthompsa 109194676Sthompsa memset(ctx, 0, sizeof(*ctx)); 110194676Sthompsa 111194676Sthompsa debug = getenv("LIBUSB_DEBUG"); 112194676Sthompsa if (debug != NULL) { 113194676Sthompsa ctx->debug = atoi(debug); 114194676Sthompsa if (ctx->debug != 0) 115194676Sthompsa ctx->debug_fixed = 1; 116194676Sthompsa } 117195957Salfred TAILQ_INIT(&ctx->pollfds); 118195957Salfred TAILQ_INIT(&ctx->tr_done); 119194676Sthompsa 120236944Shselasky if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) { 121236944Shselasky free(ctx); 122236944Shselasky return (LIBUSB_ERROR_NO_MEM); 123236944Shselasky } 124236944Shselasky if (pthread_condattr_init(&attr) != 0) { 125236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 126236944Shselasky free(ctx); 127236944Shselasky return (LIBUSB_ERROR_NO_MEM); 128236944Shselasky } 129236944Shselasky if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) { 130236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 131236944Shselasky pthread_condattr_destroy(&attr); 132236944Shselasky free(ctx); 133236944Shselasky return (LIBUSB_ERROR_OTHER); 134236944Shselasky } 135236944Shselasky if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) { 136236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 137236944Shselasky pthread_condattr_destroy(&attr); 138236944Shselasky free(ctx); 139236944Shselasky return (LIBUSB_ERROR_NO_MEM); 140236944Shselasky } 141236944Shselasky pthread_condattr_destroy(&attr); 142194676Sthompsa 143195957Salfred ctx->ctx_handler = NO_THREAD; 144194676Sthompsa 145194676Sthompsa ret = pipe(ctx->ctrl_pipe); 146194676Sthompsa if (ret < 0) { 147195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 148195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 149194676Sthompsa free(ctx); 150194676Sthompsa return (LIBUSB_ERROR_OTHER); 151194676Sthompsa } 152195957Salfred /* set non-blocking mode on the control pipe to avoid deadlock */ 153213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[0]); 154213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[1]); 155194676Sthompsa 156195957Salfred libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); 157194676Sthompsa 158194676Sthompsa pthread_mutex_lock(&default_context_lock); 159194676Sthompsa if (usbi_default_context == NULL) { 160194676Sthompsa usbi_default_context = ctx; 161194676Sthompsa } 162194676Sthompsa pthread_mutex_unlock(&default_context_lock); 163194676Sthompsa 164194676Sthompsa if (context) 165194676Sthompsa *context = ctx; 166194676Sthompsa 167195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); 168195957Salfred 169194676Sthompsa return (0); 170194676Sthompsa} 171194676Sthompsa 172194676Sthompsavoid 173195957Salfredlibusb_exit(libusb_context *ctx) 174194676Sthompsa{ 175195957Salfred ctx = GET_CONTEXT(ctx); 176194676Sthompsa 177195957Salfred if (ctx == NULL) 178195957Salfred return; 179195957Salfred 180195957Salfred /* XXX cleanup devices */ 181195957Salfred 182195957Salfred libusb10_remove_pollfd(ctx, &ctx->ctx_poll); 183194676Sthompsa close(ctx->ctrl_pipe[0]); 184194676Sthompsa close(ctx->ctrl_pipe[1]); 185195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 186195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 187194676Sthompsa 188194676Sthompsa pthread_mutex_lock(&default_context_lock); 189194676Sthompsa if (ctx == usbi_default_context) { 190194676Sthompsa usbi_default_context = NULL; 191194676Sthompsa } 192194676Sthompsa pthread_mutex_unlock(&default_context_lock); 193194676Sthompsa 194194676Sthompsa free(ctx); 195194676Sthompsa} 196194676Sthompsa 197194676Sthompsa/* Device handling and initialisation. */ 198194676Sthompsa 199194676Sthompsassize_t 200195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list) 201194676Sthompsa{ 202195957Salfred struct libusb20_backend *usb_backend; 203194676Sthompsa struct libusb20_device *pdev; 204194676Sthompsa struct libusb_device *dev; 205194676Sthompsa int i; 206194676Sthompsa 207195957Salfred ctx = GET_CONTEXT(ctx); 208194676Sthompsa 209195957Salfred if (ctx == NULL) 210195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 211195957Salfred 212195957Salfred if (list == NULL) 213195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 214195957Salfred 215194676Sthompsa usb_backend = libusb20_be_alloc_default(); 216194676Sthompsa if (usb_backend == NULL) 217195957Salfred return (LIBUSB_ERROR_NO_MEM); 218194676Sthompsa 219195957Salfred /* figure out how many USB devices are present */ 220194676Sthompsa pdev = NULL; 221194676Sthompsa i = 0; 222194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) 223194676Sthompsa i++; 224194676Sthompsa 225195957Salfred /* allocate device pointer list */ 226194676Sthompsa *list = malloc((i + 1) * sizeof(void *)); 227194676Sthompsa if (*list == NULL) { 228194676Sthompsa libusb20_be_free(usb_backend); 229194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 230194676Sthompsa } 231195957Salfred /* create libusb v1.0 compliant devices */ 232194676Sthompsa i = 0; 233194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 234194676Sthompsa 235194676Sthompsa dev = malloc(sizeof(*dev)); 236194676Sthompsa if (dev == NULL) { 237195560Sthompsa while (i != 0) { 238195560Sthompsa libusb_unref_device((*list)[i - 1]); 239195560Sthompsa i--; 240195560Sthompsa } 241194676Sthompsa free(*list); 242195957Salfred *list = NULL; 243194676Sthompsa libusb20_be_free(usb_backend); 244194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 245194676Sthompsa } 246199055Sthompsa /* get device into libUSB v1.0 list */ 247199055Sthompsa libusb20_be_dequeue_device(usb_backend, pdev); 248199055Sthompsa 249194676Sthompsa memset(dev, 0, sizeof(*dev)); 250194676Sthompsa 251195957Salfred /* init transfer queues */ 252195957Salfred TAILQ_INIT(&dev->tr_head); 253195957Salfred 254195957Salfred /* set context we belong to */ 255194676Sthompsa dev->ctx = ctx; 256194676Sthompsa 257194676Sthompsa /* link together the two structures */ 258194676Sthompsa dev->os_priv = pdev; 259195957Salfred pdev->privLuData = dev; 260194676Sthompsa 261194676Sthompsa (*list)[i] = libusb_ref_device(dev); 262194676Sthompsa i++; 263194676Sthompsa } 264194676Sthompsa (*list)[i] = NULL; 265194676Sthompsa 266194676Sthompsa libusb20_be_free(usb_backend); 267194676Sthompsa return (i); 268194676Sthompsa} 269194676Sthompsa 270194676Sthompsavoid 271194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices) 272194676Sthompsa{ 273194676Sthompsa int i; 274194676Sthompsa 275194676Sthompsa if (list == NULL) 276195957Salfred return; /* be NULL safe */ 277194676Sthompsa 278194676Sthompsa if (unref_devices) { 279194676Sthompsa for (i = 0; list[i] != NULL; i++) 280194676Sthompsa libusb_unref_device(list[i]); 281194676Sthompsa } 282194676Sthompsa free(list); 283194676Sthompsa} 284194676Sthompsa 285194676Sthompsauint8_t 286195957Salfredlibusb_get_bus_number(libusb_device *dev) 287194676Sthompsa{ 288194676Sthompsa if (dev == NULL) 289195957Salfred return (0); /* should not happen */ 290195957Salfred return (libusb20_dev_get_bus_number(dev->os_priv)); 291194676Sthompsa} 292194676Sthompsa 293250342Semasteint 294251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) 295251495Semaste{ 296251495Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 297251495Semaste} 298251495Semaste 299251495Semasteint 300250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, 301250342Semaste uint8_t bufsize) 302250342Semaste{ 303250342Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 304250342Semaste} 305250342Semaste 306194676Sthompsauint8_t 307195957Salfredlibusb_get_device_address(libusb_device *dev) 308194676Sthompsa{ 309194676Sthompsa if (dev == NULL) 310195957Salfred return (0); /* should not happen */ 311195957Salfred return (libusb20_dev_get_address(dev->os_priv)); 312194676Sthompsa} 313194676Sthompsa 314224903Shselaskyenum libusb_speed 315224903Shselaskylibusb_get_device_speed(libusb_device *dev) 316224903Shselasky{ 317224903Shselasky if (dev == NULL) 318225035Shselasky return (LIBUSB_SPEED_UNKNOWN); /* should not happen */ 319224903Shselasky 320224903Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 321224903Shselasky case LIBUSB20_SPEED_LOW: 322224903Shselasky return (LIBUSB_SPEED_LOW); 323224903Shselasky case LIBUSB20_SPEED_FULL: 324224903Shselasky return (LIBUSB_SPEED_FULL); 325224903Shselasky case LIBUSB20_SPEED_HIGH: 326224903Shselasky return (LIBUSB_SPEED_HIGH); 327224903Shselasky case LIBUSB20_SPEED_SUPER: 328224903Shselasky return (LIBUSB_SPEED_SUPER); 329224903Shselasky default: 330224903Shselasky break; 331224903Shselasky } 332224903Shselasky return (LIBUSB_SPEED_UNKNOWN); 333224903Shselasky} 334224903Shselasky 335194676Sthompsaint 336195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint) 337194676Sthompsa{ 338194676Sthompsa struct libusb_config_descriptor *pdconf; 339194676Sthompsa struct libusb_interface *pinf; 340194676Sthompsa struct libusb_interface_descriptor *pdinf; 341194676Sthompsa struct libusb_endpoint_descriptor *pdend; 342195957Salfred int i; 343195957Salfred int j; 344195957Salfred int k; 345195957Salfred int ret; 346194676Sthompsa 347194676Sthompsa if (dev == NULL) 348194676Sthompsa return (LIBUSB_ERROR_NO_DEVICE); 349194676Sthompsa 350195957Salfred ret = libusb_get_active_config_descriptor(dev, &pdconf); 351195957Salfred if (ret < 0) 352195957Salfred return (ret); 353195957Salfred 354194676Sthompsa ret = LIBUSB_ERROR_NOT_FOUND; 355195957Salfred for (i = 0; i < pdconf->bNumInterfaces; i++) { 356194676Sthompsa pinf = &pdconf->interface[i]; 357195957Salfred for (j = 0; j < pinf->num_altsetting; j++) { 358194676Sthompsa pdinf = &pinf->altsetting[j]; 359195957Salfred for (k = 0; k < pdinf->bNumEndpoints; k++) { 360194676Sthompsa pdend = &pdinf->endpoint[k]; 361194676Sthompsa if (pdend->bEndpointAddress == endpoint) { 362194676Sthompsa ret = pdend->wMaxPacketSize; 363194676Sthompsa goto out; 364194676Sthompsa } 365194676Sthompsa } 366194676Sthompsa } 367194676Sthompsa } 368194676Sthompsa 369194676Sthompsaout: 370194676Sthompsa libusb_free_config_descriptor(pdconf); 371194676Sthompsa return (ret); 372194676Sthompsa} 373194676Sthompsa 374234193Shselaskyint 375234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint) 376234193Shselasky{ 377234193Shselasky int multiplier; 378234193Shselasky int ret; 379234193Shselasky 380234193Shselasky ret = libusb_get_max_packet_size(dev, endpoint); 381234193Shselasky 382234193Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 383234193Shselasky case LIBUSB20_SPEED_LOW: 384234193Shselasky case LIBUSB20_SPEED_FULL: 385234193Shselasky break; 386234193Shselasky default: 387234193Shselasky if (ret > -1) { 388234193Shselasky multiplier = (1 + ((ret >> 11) & 3)); 389234193Shselasky if (multiplier > 3) 390234193Shselasky multiplier = 3; 391234193Shselasky ret = (ret & 0x7FF) * multiplier; 392234193Shselasky } 393234193Shselasky break; 394234193Shselasky } 395234193Shselasky return (ret); 396234193Shselasky} 397234193Shselasky 398194676Sthompsalibusb_device * 399195957Salfredlibusb_ref_device(libusb_device *dev) 400194676Sthompsa{ 401194676Sthompsa if (dev == NULL) 402195957Salfred return (NULL); /* be NULL safe */ 403194676Sthompsa 404195957Salfred CTX_LOCK(dev->ctx); 405194676Sthompsa dev->refcnt++; 406195957Salfred CTX_UNLOCK(dev->ctx); 407194676Sthompsa 408194676Sthompsa return (dev); 409194676Sthompsa} 410194676Sthompsa 411194676Sthompsavoid 412195957Salfredlibusb_unref_device(libusb_device *dev) 413194676Sthompsa{ 414194676Sthompsa if (dev == NULL) 415195957Salfred return; /* be NULL safe */ 416194676Sthompsa 417195957Salfred CTX_LOCK(dev->ctx); 418194676Sthompsa dev->refcnt--; 419195957Salfred CTX_UNLOCK(dev->ctx); 420194676Sthompsa 421194676Sthompsa if (dev->refcnt == 0) { 422194676Sthompsa libusb20_dev_free(dev->os_priv); 423194676Sthompsa free(dev); 424194676Sthompsa } 425194676Sthompsa} 426194676Sthompsa 427194676Sthompsaint 428195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh) 429194676Sthompsa{ 430194676Sthompsa libusb_context *ctx = dev->ctx; 431194676Sthompsa struct libusb20_device *pdev = dev->os_priv; 432195957Salfred uint8_t dummy; 433194676Sthompsa int err; 434194676Sthompsa 435194676Sthompsa if (devh == NULL) 436194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 437194676Sthompsa 438195957Salfred /* set default device handle value */ 439195957Salfred *devh = NULL; 440194676Sthompsa 441195957Salfred dev = libusb_ref_device(dev); 442195957Salfred if (dev == NULL) 443195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 444195957Salfred 445194676Sthompsa err = libusb20_dev_open(pdev, 16 * 4 /* number of endpoints */ ); 446194676Sthompsa if (err) { 447195957Salfred libusb_unref_device(dev); 448194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 449194676Sthompsa } 450195957Salfred libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 451194676Sthompsa POLLOUT | POLLRDNORM | POLLWRNORM); 452194676Sthompsa 453195957Salfred /* make sure our event loop detects the new device */ 454195957Salfred dummy = 0; 455194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 456213853Shselasky if (err < (int)sizeof(dummy)) { 457195957Salfred /* ignore error, if any */ 458195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!"); 459194676Sthompsa } 460195957Salfred *devh = pdev; 461194676Sthompsa 462194676Sthompsa return (0); 463194676Sthompsa} 464194676Sthompsa 465194676Sthompsalibusb_device_handle * 466195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, 467194676Sthompsa uint16_t product_id) 468194676Sthompsa{ 469194676Sthompsa struct libusb_device **devs; 470194676Sthompsa struct libusb20_device *pdev; 471194676Sthompsa struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 472195957Salfred int i; 473195957Salfred int j; 474194676Sthompsa 475195957Salfred ctx = GET_CONTEXT(ctx); 476195957Salfred if (ctx == NULL) 477195957Salfred return (NULL); /* be NULL safe */ 478195957Salfred 479195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter"); 480194676Sthompsa 481194676Sthompsa if ((i = libusb_get_device_list(ctx, &devs)) < 0) 482194676Sthompsa return (NULL); 483194676Sthompsa 484228236Shselasky pdev = NULL; 485194676Sthompsa for (j = 0; j < i; j++) { 486228236Shselasky struct libusb20_device *tdev; 487228236Shselasky 488228236Shselasky tdev = devs[j]->os_priv; 489228236Shselasky pdesc = libusb20_dev_get_device_desc(tdev); 490195957Salfred /* 491195957Salfred * NOTE: The USB library will automatically swap the 492195957Salfred * fields in the device descriptor to be of host 493195957Salfred * endian type! 494195957Salfred */ 495194676Sthompsa if (pdesc->idVendor == vendor_id && 496195560Sthompsa pdesc->idProduct == product_id) { 497228235Shselasky libusb_open(devs[j], &pdev); 498195957Salfred break; 499195560Sthompsa } 500194676Sthompsa } 501194676Sthompsa 502194676Sthompsa libusb_free_device_list(devs, 1); 503195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave"); 504195957Salfred return (pdev); 505194676Sthompsa} 506194676Sthompsa 507194676Sthompsavoid 508195957Salfredlibusb_close(struct libusb20_device *pdev) 509194676Sthompsa{ 510194676Sthompsa libusb_context *ctx; 511195957Salfred struct libusb_device *dev; 512195957Salfred uint8_t dummy; 513194676Sthompsa int err; 514194676Sthompsa 515195957Salfred if (pdev == NULL) 516195957Salfred return; /* be NULL safe */ 517194676Sthompsa 518195957Salfred dev = libusb_get_device(pdev); 519195957Salfred ctx = dev->ctx; 520194676Sthompsa 521195957Salfred libusb10_remove_pollfd(ctx, &dev->dev_poll); 522194676Sthompsa 523195957Salfred libusb20_dev_close(pdev); 524199055Sthompsa 525199055Sthompsa /* unref will free the "pdev" when the refcount reaches zero */ 526195957Salfred libusb_unref_device(dev); 527194676Sthompsa 528195957Salfred /* make sure our event loop detects the closed device */ 529195957Salfred dummy = 0; 530194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 531213853Shselasky if (err < (int)sizeof(dummy)) { 532195957Salfred /* ignore error, if any */ 533195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!"); 534194676Sthompsa } 535194676Sthompsa} 536194676Sthompsa 537194676Sthompsalibusb_device * 538195957Salfredlibusb_get_device(struct libusb20_device *pdev) 539194676Sthompsa{ 540195957Salfred if (pdev == NULL) 541194676Sthompsa return (NULL); 542195957Salfred return ((libusb_device *)pdev->privLuData); 543194676Sthompsa} 544194676Sthompsa 545194676Sthompsaint 546195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config) 547194676Sthompsa{ 548195957Salfred struct libusb20_config *pconf; 549194676Sthompsa 550195957Salfred if (pdev == NULL || config == NULL) 551194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 552194676Sthompsa 553195957Salfred pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); 554195957Salfred if (pconf == NULL) 555195957Salfred return (LIBUSB_ERROR_NO_MEM); 556194676Sthompsa 557195957Salfred *config = pconf->desc.bConfigurationValue; 558195957Salfred 559195957Salfred free(pconf); 560195957Salfred 561194676Sthompsa return (0); 562194676Sthompsa} 563194676Sthompsa 564194676Sthompsaint 565195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration) 566194676Sthompsa{ 567195957Salfred struct libusb20_config *pconf; 568195957Salfred struct libusb_device *dev; 569195957Salfred int err; 570195957Salfred uint8_t i; 571194676Sthompsa 572195957Salfred dev = libusb_get_device(pdev); 573195957Salfred if (dev == NULL) 574194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 575194676Sthompsa 576195957Salfred if (configuration < 1) { 577195957Salfred /* unconfigure */ 578195957Salfred i = 255; 579195957Salfred } else { 580195957Salfred for (i = 0; i != 255; i++) { 581195957Salfred uint8_t found; 582194676Sthompsa 583195957Salfred pconf = libusb20_dev_alloc_config(pdev, i); 584195957Salfred if (pconf == NULL) 585195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 586195957Salfred found = (pconf->desc.bConfigurationValue 587195957Salfred == configuration); 588195957Salfred free(pconf); 589195957Salfred 590195957Salfred if (found) 591195957Salfred goto set_config; 592195957Salfred } 593195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 594195957Salfred } 595195957Salfred 596195957Salfredset_config: 597195957Salfred 598195957Salfred libusb10_cancel_all_transfer(dev); 599195957Salfred 600195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 601195957Salfred 602195957Salfred err = libusb20_dev_set_config_index(pdev, i); 603195957Salfred 604195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 605195957Salfred POLLOUT | POLLRDNORM | POLLWRNORM); 606195957Salfred 607195957Salfred return (err ? LIBUSB_ERROR_INVALID_PARAM : 0); 608194676Sthompsa} 609194676Sthompsa 610194676Sthompsaint 611195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number) 612194676Sthompsa{ 613195957Salfred libusb_device *dev; 614194676Sthompsa 615195957Salfred dev = libusb_get_device(pdev); 616194676Sthompsa if (dev == NULL) 617194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 618194676Sthompsa 619195957Salfred if (interface_number < 0 || interface_number > 31) 620194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 621194676Sthompsa 622195957Salfred CTX_LOCK(dev->ctx); 623261475Shselasky dev->claimed_interfaces |= (1 << interface_number); 624261475Shselasky CTX_UNLOCK(dev->ctx); 625194676Sthompsa 626261475Shselasky return (0); 627194676Sthompsa} 628194676Sthompsa 629194676Sthompsaint 630195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number) 631194676Sthompsa{ 632195957Salfred libusb_device *dev; 633195957Salfred int err = 0; 634194676Sthompsa 635195957Salfred dev = libusb_get_device(pdev); 636194676Sthompsa if (dev == NULL) 637194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 638194676Sthompsa 639195957Salfred if (interface_number < 0 || interface_number > 31) 640194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 641194676Sthompsa 642195957Salfred CTX_LOCK(dev->ctx); 643194676Sthompsa if (!(dev->claimed_interfaces & (1 << interface_number))) 644195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 645194676Sthompsa 646195957Salfred if (!err) 647194676Sthompsa dev->claimed_interfaces &= ~(1 << interface_number); 648195957Salfred CTX_UNLOCK(dev->ctx); 649195957Salfred return (err); 650194676Sthompsa} 651194676Sthompsa 652194676Sthompsaint 653195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev, 654194676Sthompsa int interface_number, int alternate_setting) 655194676Sthompsa{ 656195957Salfred libusb_device *dev; 657195957Salfred int err = 0; 658194676Sthompsa 659195957Salfred dev = libusb_get_device(pdev); 660194676Sthompsa if (dev == NULL) 661194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 662194676Sthompsa 663195957Salfred if (interface_number < 0 || interface_number > 31) 664194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 665194676Sthompsa 666195957Salfred CTX_LOCK(dev->ctx); 667195957Salfred if (!(dev->claimed_interfaces & (1 << interface_number))) 668195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 669195957Salfred CTX_UNLOCK(dev->ctx); 670194676Sthompsa 671195957Salfred if (err) 672195957Salfred return (err); 673195957Salfred 674195957Salfred libusb10_cancel_all_transfer(dev); 675195957Salfred 676195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 677195957Salfred 678195957Salfred err = libusb20_dev_set_alt_index(pdev, 679195957Salfred interface_number, alternate_setting); 680195957Salfred 681195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 682195957Salfred pdev, libusb20_dev_get_fd(pdev), 683195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 684195957Salfred 685195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 686194676Sthompsa} 687194676Sthompsa 688195957Salfredstatic struct libusb20_transfer * 689195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev, 690234491Shselasky uint8_t endpoint, uint8_t xfer_index) 691195957Salfred{ 692234491Shselasky xfer_index &= 1; /* double buffering */ 693195957Salfred 694234491Shselasky xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4; 695195957Salfred 696195957Salfred if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) { 697195957Salfred /* this is an IN endpoint */ 698234491Shselasky xfer_index |= 2; 699195957Salfred } 700234491Shselasky return (libusb20_tr_get_pointer(pdev, xfer_index)); 701195957Salfred} 702195957Salfred 703194676Sthompsaint 704195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint) 705194676Sthompsa{ 706194676Sthompsa struct libusb20_transfer *xfer; 707195957Salfred struct libusb_device *dev; 708195957Salfred int err; 709194676Sthompsa 710195957Salfred xfer = libusb10_get_transfer(pdev, endpoint, 0); 711195560Sthompsa if (xfer == NULL) 712195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 713194676Sthompsa 714195957Salfred dev = libusb_get_device(pdev); 715213853Shselasky if (dev == NULL) 716213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 717195957Salfred 718195957Salfred CTX_LOCK(dev->ctx); 719223642Shselasky err = libusb20_tr_open(xfer, 0, 1, endpoint); 720195957Salfred CTX_UNLOCK(dev->ctx); 721195957Salfred 722195957Salfred if (err != 0 && err != LIBUSB20_ERROR_BUSY) 723194676Sthompsa return (LIBUSB_ERROR_OTHER); 724194676Sthompsa 725194676Sthompsa libusb20_tr_clear_stall_sync(xfer); 726195957Salfred 727195957Salfred /* check if we opened the transfer */ 728195957Salfred if (err == 0) { 729195957Salfred CTX_LOCK(dev->ctx); 730194676Sthompsa libusb20_tr_close(xfer); 731195957Salfred CTX_UNLOCK(dev->ctx); 732195957Salfred } 733195957Salfred return (0); /* success */ 734194676Sthompsa} 735194676Sthompsa 736194676Sthompsaint 737195957Salfredlibusb_reset_device(struct libusb20_device *pdev) 738194676Sthompsa{ 739195957Salfred libusb_device *dev; 740195957Salfred int err; 741194676Sthompsa 742195957Salfred dev = libusb_get_device(pdev); 743194676Sthompsa if (dev == NULL) 744213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 745194676Sthompsa 746195957Salfred libusb10_cancel_all_transfer(dev); 747195957Salfred 748195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 749195957Salfred 750195957Salfred err = libusb20_dev_reset(pdev); 751195957Salfred 752195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 753195957Salfred pdev, libusb20_dev_get_fd(pdev), 754195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 755195957Salfred 756195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 757194676Sthompsa} 758194676Sthompsa 759194676Sthompsaint 760213848Shselaskylibusb_check_connected(struct libusb20_device *pdev) 761213848Shselasky{ 762213848Shselasky libusb_device *dev; 763213848Shselasky int err; 764213848Shselasky 765213848Shselasky dev = libusb_get_device(pdev); 766213848Shselasky if (dev == NULL) 767213848Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 768213848Shselasky 769213848Shselasky err = libusb20_dev_check_connected(pdev); 770213848Shselasky 771213848Shselasky return (err ? LIBUSB_ERROR_NO_DEVICE : 0); 772213848Shselasky} 773213848Shselasky 774213848Shselaskyint 775195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface) 776194676Sthompsa{ 777195957Salfred if (pdev == NULL) 778194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 779194676Sthompsa 780226220Shselasky if (libusb20_dev_kernel_driver_active(pdev, interface)) 781226220Shselasky return (0); /* no kernel driver is active */ 782226220Shselasky else 783226220Shselasky return (1); /* kernel driver is active */ 784194676Sthompsa} 785194676Sthompsa 786194676Sthompsaint 787213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface, 788213853Shselasky char *name, int namelen) 789213853Shselasky{ 790213853Shselasky return (libusb_get_driver(pdev, interface, name, namelen)); 791213853Shselasky} 792213853Shselasky 793213853Shselaskyint 794213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface, 795213853Shselasky char *name, int namelen) 796213853Shselasky{ 797213853Shselasky char *ptr; 798213853Shselasky int err; 799213853Shselasky 800213853Shselasky if (pdev == NULL) 801213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 802213853Shselasky if (namelen < 1) 803213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 804224085Shselasky if (namelen > 255) 805224085Shselasky namelen = 255; 806213853Shselasky 807213853Shselasky err = libusb20_dev_get_iface_desc( 808213853Shselasky pdev, interface, name, namelen); 809213853Shselasky 810213853Shselasky if (err != 0) 811213853Shselasky return (LIBUSB_ERROR_OTHER); 812213853Shselasky 813213853Shselasky /* we only want the driver name */ 814213853Shselasky ptr = strstr(name, ":"); 815213853Shselasky if (ptr != NULL) 816213853Shselasky *ptr = 0; 817213853Shselasky 818213853Shselasky return (0); 819213853Shselasky} 820213853Shselasky 821213853Shselaskyint 822213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface) 823213853Shselasky{ 824213853Shselasky return (libusb_detach_kernel_driver(pdev, interface)); 825213853Shselasky} 826213853Shselasky 827213853Shselaskyint 828195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface) 829194676Sthompsa{ 830195957Salfred int err; 831194676Sthompsa 832195957Salfred if (pdev == NULL) 833194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 834194676Sthompsa 835195957Salfred err = libusb20_dev_detach_kernel_driver( 836195957Salfred pdev, interface); 837194676Sthompsa 838213853Shselasky return (err ? LIBUSB_ERROR_OTHER : 0); 839194676Sthompsa} 840194676Sthompsa 841194676Sthompsaint 842195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface) 843194676Sthompsa{ 844195957Salfred if (pdev == NULL) 845194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 846195957Salfred /* stub - currently not supported by libusb20 */ 847194676Sthompsa return (0); 848194676Sthompsa} 849194676Sthompsa 850194676Sthompsa/* Asynchronous device I/O */ 851194676Sthompsa 852194676Sthompsastruct libusb_transfer * 853194676Sthompsalibusb_alloc_transfer(int iso_packets) 854194676Sthompsa{ 855195957Salfred struct libusb_transfer *uxfer; 856195957Salfred struct libusb_super_transfer *sxfer; 857194676Sthompsa int len; 858194676Sthompsa 859194676Sthompsa len = sizeof(struct libusb_transfer) + 860195957Salfred sizeof(struct libusb_super_transfer) + 861194676Sthompsa (iso_packets * sizeof(libusb_iso_packet_descriptor)); 862194676Sthompsa 863195957Salfred sxfer = malloc(len); 864195957Salfred if (sxfer == NULL) 865194676Sthompsa return (NULL); 866194676Sthompsa 867195957Salfred memset(sxfer, 0, len); 868194676Sthompsa 869195957Salfred uxfer = (struct libusb_transfer *)( 870195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 871194676Sthompsa 872195957Salfred /* set default value */ 873195957Salfred uxfer->num_iso_packets = iso_packets; 874195957Salfred 875195957Salfred return (uxfer); 876194676Sthompsa} 877194676Sthompsa 878194676Sthompsavoid 879195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer) 880194676Sthompsa{ 881195957Salfred struct libusb_super_transfer *sxfer; 882194676Sthompsa 883195957Salfred if (uxfer == NULL) 884195957Salfred return; /* be NULL safe */ 885194676Sthompsa 886215253Shselasky /* check if we should free the transfer buffer */ 887215253Shselasky if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 888215253Shselasky free(uxfer->buffer); 889215253Shselasky 890195957Salfred sxfer = (struct libusb_super_transfer *)( 891195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 892194676Sthompsa 893195957Salfred free(sxfer); 894194676Sthompsa} 895194676Sthompsa 896219100Shselaskystatic uint32_t 897195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 898195560Sthompsa{ 899219100Shselasky uint32_t ret; 900195560Sthompsa 901195560Sthompsa switch (xfer->type) { 902195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 903219100Shselasky ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE; /* 60ms */ 904195957Salfred break; 905195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 906195560Sthompsa ret = 2; 907195957Salfred break; 908195560Sthompsa default: 909195560Sthompsa ret = 1; 910195957Salfred break; 911195560Sthompsa } 912195957Salfred return (ret); 913195560Sthompsa} 914195560Sthompsa 915195560Sthompsastatic int 916195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 917195560Sthompsa{ 918195560Sthompsa int ret; 919195560Sthompsa int usb_speed; 920195560Sthompsa 921195560Sthompsa usb_speed = libusb20_dev_get_speed(pdev); 922195560Sthompsa 923195560Sthompsa switch (xfer->type) { 924195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 925195957Salfred ret = 0; /* kernel will auto-select */ 926195957Salfred break; 927195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 928195957Salfred ret = 1024; 929195957Salfred break; 930195957Salfred default: 931195560Sthompsa switch (usb_speed) { 932195957Salfred case LIBUSB20_SPEED_LOW: 933195957Salfred ret = 256; 934195957Salfred break; 935195957Salfred case LIBUSB20_SPEED_FULL: 936195957Salfred ret = 4096; 937195957Salfred break; 938264641Shselasky case LIBUSB20_SPEED_SUPER: 939264641Shselasky ret = 65536; 940264641Shselasky break; 941195957Salfred default: 942195957Salfred ret = 16384; 943195957Salfred break; 944195560Sthompsa } 945195957Salfred break; 946195560Sthompsa } 947195957Salfred return (ret); 948195560Sthompsa} 949195560Sthompsa 950195957Salfredstatic int 951195957Salfredlibusb10_convert_error(uint8_t status) 952195957Salfred{ 953195957Salfred ; /* indent fix */ 954195957Salfred 955195957Salfred switch (status) { 956195957Salfred case LIBUSB20_TRANSFER_START: 957195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 958195957Salfred return (LIBUSB_TRANSFER_COMPLETED); 959195957Salfred case LIBUSB20_TRANSFER_OVERFLOW: 960195957Salfred return (LIBUSB_TRANSFER_OVERFLOW); 961195957Salfred case LIBUSB20_TRANSFER_NO_DEVICE: 962195957Salfred return (LIBUSB_TRANSFER_NO_DEVICE); 963195957Salfred case LIBUSB20_TRANSFER_STALL: 964195957Salfred return (LIBUSB_TRANSFER_STALL); 965195957Salfred case LIBUSB20_TRANSFER_CANCELLED: 966195957Salfred return (LIBUSB_TRANSFER_CANCELLED); 967195957Salfred case LIBUSB20_TRANSFER_TIMED_OUT: 968195957Salfred return (LIBUSB_TRANSFER_TIMED_OUT); 969195957Salfred default: 970195957Salfred return (LIBUSB_TRANSFER_ERROR); 971195957Salfred } 972195957Salfred} 973195957Salfred 974195957Salfred/* This function must be called locked */ 975195957Salfred 976194676Sthompsastatic void 977195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer, 978195957Salfred struct libusb_super_transfer *sxfer, int status) 979194676Sthompsa{ 980195957Salfred struct libusb_transfer *uxfer; 981195957Salfred struct libusb_device *dev; 982195957Salfred 983195957Salfred uxfer = (struct libusb_transfer *)( 984195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 985195957Salfred 986195957Salfred if (pxfer != NULL) 987195957Salfred libusb20_tr_set_priv_sc1(pxfer, NULL); 988195957Salfred 989199575Sthompsa /* set transfer status */ 990195957Salfred uxfer->status = status; 991195957Salfred 992199575Sthompsa /* update super transfer state */ 993199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_NONE; 994199575Sthompsa 995195957Salfred dev = libusb_get_device(uxfer->dev_handle); 996195957Salfred 997195957Salfred TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); 998195957Salfred} 999195957Salfred 1000195957Salfred/* This function must be called locked */ 1001195957Salfred 1002195957Salfredstatic void 1003195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer) 1004195957Salfred{ 1005195957Salfred struct libusb_super_transfer *sxfer; 1006195957Salfred struct libusb_transfer *uxfer; 1007195957Salfred uint32_t actlen; 1008195957Salfred uint16_t iso_packets; 1009195957Salfred uint16_t i; 1010194676Sthompsa uint8_t status; 1011195957Salfred uint8_t flags; 1012194676Sthompsa 1013195957Salfred status = libusb20_tr_get_status(pxfer); 1014195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1015195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1016195957Salfred iso_packets = libusb20_tr_get_max_frames(pxfer); 1017194676Sthompsa 1018195957Salfred if (sxfer == NULL) 1019195957Salfred return; /* cancelled - nothing to do */ 1020195957Salfred 1021195957Salfred uxfer = (struct libusb_transfer *)( 1022195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1023195957Salfred 1024195957Salfred if (iso_packets > uxfer->num_iso_packets) 1025195957Salfred iso_packets = uxfer->num_iso_packets; 1026195957Salfred 1027195957Salfred if (iso_packets == 0) 1028195957Salfred return; /* nothing to do */ 1029195957Salfred 1030195957Salfred /* make sure that the number of ISOCHRONOUS packets is valid */ 1031195957Salfred uxfer->num_iso_packets = iso_packets; 1032195957Salfred 1033195957Salfred flags = uxfer->flags; 1034195957Salfred 1035194676Sthompsa switch (status) { 1036194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1037195560Sthompsa 1038195957Salfred /* update actual length */ 1039195957Salfred uxfer->actual_length = actlen; 1040195957Salfred for (i = 0; i != iso_packets; i++) { 1041195957Salfred uxfer->iso_packet_desc[i].actual_length = 1042195957Salfred libusb20_tr_get_length(pxfer, i); 1043195957Salfred } 1044195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1045195957Salfred break; 1046195560Sthompsa 1047194676Sthompsa case LIBUSB20_TRANSFER_START: 1048195957Salfred 1049195957Salfred /* setup length(s) */ 1050195957Salfred actlen = 0; 1051195957Salfred for (i = 0; i != iso_packets; i++) { 1052195957Salfred libusb20_tr_setup_isoc(pxfer, 1053195957Salfred &uxfer->buffer[actlen], 1054195957Salfred uxfer->iso_packet_desc[i].length, i); 1055195957Salfred actlen += uxfer->iso_packet_desc[i].length; 1056194676Sthompsa } 1057195957Salfred 1058195957Salfred /* no remainder */ 1059195957Salfred sxfer->rem_len = 0; 1060195957Salfred 1061195957Salfred libusb20_tr_set_total_frames(pxfer, iso_packets); 1062195957Salfred libusb20_tr_submit(pxfer); 1063195957Salfred 1064195957Salfred /* fork another USB transfer, if any */ 1065195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1066195957Salfred break; 1067195957Salfred 1068194676Sthompsa default: 1069195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1070195957Salfred break; 1071194676Sthompsa } 1072195957Salfred} 1073194676Sthompsa 1074195957Salfred/* This function must be called locked */ 1075195957Salfred 1076195957Salfredstatic void 1077195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) 1078195957Salfred{ 1079195957Salfred struct libusb_super_transfer *sxfer; 1080195957Salfred struct libusb_transfer *uxfer; 1081195957Salfred uint32_t max_bulk; 1082195957Salfred uint32_t actlen; 1083195957Salfred uint8_t status; 1084195957Salfred uint8_t flags; 1085195957Salfred 1086195957Salfred status = libusb20_tr_get_status(pxfer); 1087195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1088195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1089195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1090195957Salfred 1091195957Salfred if (sxfer == NULL) 1092195957Salfred return; /* cancelled - nothing to do */ 1093195957Salfred 1094195957Salfred uxfer = (struct libusb_transfer *)( 1095195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1096195957Salfred 1097195957Salfred flags = uxfer->flags; 1098195957Salfred 1099194676Sthompsa switch (status) { 1100194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1101195957Salfred 1102195957Salfred uxfer->actual_length += actlen; 1103195957Salfred 1104195957Salfred /* check for short packet */ 1105195957Salfred if (sxfer->last_len != actlen) { 1106195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1107195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1108195957Salfred } else { 1109195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1110195957Salfred } 1111195957Salfred break; 1112195957Salfred } 1113195957Salfred /* check for end of data */ 1114195957Salfred if (sxfer->rem_len == 0) { 1115195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1116195957Salfred break; 1117195957Salfred } 1118195957Salfred /* FALLTHROUGH */ 1119195957Salfred 1120195957Salfred case LIBUSB20_TRANSFER_START: 1121195957Salfred if (max_bulk > sxfer->rem_len) { 1122195957Salfred max_bulk = sxfer->rem_len; 1123195957Salfred } 1124195957Salfred /* setup new BULK or INTERRUPT transaction */ 1125195957Salfred libusb20_tr_setup_bulk(pxfer, 1126195957Salfred sxfer->curr_data, max_bulk, uxfer->timeout); 1127195957Salfred 1128195957Salfred /* update counters */ 1129195957Salfred sxfer->last_len = max_bulk; 1130195957Salfred sxfer->curr_data += max_bulk; 1131195957Salfred sxfer->rem_len -= max_bulk; 1132195957Salfred 1133195957Salfred libusb20_tr_submit(pxfer); 1134195957Salfred 1135195957Salfred /* check if we can fork another USB transfer */ 1136195957Salfred if (sxfer->rem_len == 0) 1137195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1138195957Salfred break; 1139195957Salfred 1140195957Salfred default: 1141195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1142195957Salfred break; 1143194676Sthompsa } 1144194676Sthompsa} 1145194676Sthompsa 1146195957Salfred/* This function must be called locked */ 1147195957Salfred 1148195957Salfredstatic void 1149195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer) 1150194676Sthompsa{ 1151195957Salfred struct libusb_super_transfer *sxfer; 1152195957Salfred struct libusb_transfer *uxfer; 1153195957Salfred uint32_t max_bulk; 1154195957Salfred uint32_t actlen; 1155195957Salfred uint8_t status; 1156195957Salfred uint8_t flags; 1157194676Sthompsa 1158195957Salfred status = libusb20_tr_get_status(pxfer); 1159195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1160195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1161195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1162194676Sthompsa 1163195957Salfred if (sxfer == NULL) 1164195957Salfred return; /* cancelled - nothing to do */ 1165194676Sthompsa 1166195957Salfred uxfer = (struct libusb_transfer *)( 1167195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1168194676Sthompsa 1169195957Salfred flags = uxfer->flags; 1170194676Sthompsa 1171195957Salfred switch (status) { 1172195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1173194676Sthompsa 1174195957Salfred uxfer->actual_length += actlen; 1175195957Salfred 1176195957Salfred /* subtract length of SETUP packet, if any */ 1177195957Salfred actlen -= libusb20_tr_get_length(pxfer, 0); 1178195957Salfred 1179195957Salfred /* check for short packet */ 1180195957Salfred if (sxfer->last_len != actlen) { 1181195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1182195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1183195957Salfred } else { 1184195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1185195957Salfred } 1186195957Salfred break; 1187194676Sthompsa } 1188195957Salfred /* check for end of data */ 1189195957Salfred if (sxfer->rem_len == 0) { 1190195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1191195957Salfred break; 1192195957Salfred } 1193195957Salfred /* FALLTHROUGH */ 1194194676Sthompsa 1195195957Salfred case LIBUSB20_TRANSFER_START: 1196195957Salfred if (max_bulk > sxfer->rem_len) { 1197195957Salfred max_bulk = sxfer->rem_len; 1198195957Salfred } 1199195957Salfred /* setup new CONTROL transaction */ 1200195957Salfred if (status == LIBUSB20_TRANSFER_COMPLETED) { 1201195957Salfred /* next fragment - don't send SETUP packet */ 1202195957Salfred libusb20_tr_set_length(pxfer, 0, 0); 1203195957Salfred } else { 1204195957Salfred /* first fragment - send SETUP packet */ 1205195957Salfred libusb20_tr_set_length(pxfer, 8, 0); 1206195957Salfred libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0); 1207195957Salfred } 1208195957Salfred 1209195957Salfred if (max_bulk != 0) { 1210195957Salfred libusb20_tr_set_length(pxfer, max_bulk, 1); 1211195957Salfred libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1); 1212195957Salfred libusb20_tr_set_total_frames(pxfer, 2); 1213195957Salfred } else { 1214195957Salfred libusb20_tr_set_total_frames(pxfer, 1); 1215195957Salfred } 1216195957Salfred 1217195957Salfred /* update counters */ 1218195957Salfred sxfer->last_len = max_bulk; 1219195957Salfred sxfer->curr_data += max_bulk; 1220195957Salfred sxfer->rem_len -= max_bulk; 1221195957Salfred 1222195957Salfred libusb20_tr_submit(pxfer); 1223195957Salfred 1224195957Salfred /* check if we can fork another USB transfer */ 1225195957Salfred if (sxfer->rem_len == 0) 1226195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1227195957Salfred break; 1228195957Salfred 1229195957Salfred default: 1230195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1231195957Salfred break; 1232194676Sthompsa } 1233195957Salfred} 1234195957Salfred 1235195957Salfred/* The following function must be called locked */ 1236195957Salfred 1237195957Salfredstatic void 1238195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint) 1239195957Salfred{ 1240195957Salfred struct libusb20_transfer *pxfer0; 1241195957Salfred struct libusb20_transfer *pxfer1; 1242195957Salfred struct libusb_super_transfer *sxfer; 1243195957Salfred struct libusb_transfer *uxfer; 1244195957Salfred struct libusb_device *dev; 1245195957Salfred int err; 1246195957Salfred int buffsize; 1247195957Salfred int maxframe; 1248195957Salfred int temp; 1249195957Salfred uint8_t dummy; 1250195957Salfred 1251195957Salfred dev = libusb_get_device(pdev); 1252195957Salfred 1253195957Salfred pxfer0 = libusb10_get_transfer(pdev, endpoint, 0); 1254195957Salfred pxfer1 = libusb10_get_transfer(pdev, endpoint, 1); 1255195957Salfred 1256195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) 1257195957Salfred return; /* shouldn't happen */ 1258195957Salfred 1259195957Salfred temp = 0; 1260195957Salfred if (libusb20_tr_pending(pxfer0)) 1261195957Salfred temp |= 1; 1262195957Salfred if (libusb20_tr_pending(pxfer1)) 1263195957Salfred temp |= 2; 1264195957Salfred 1265195957Salfred switch (temp) { 1266195957Salfred case 3: 1267195957Salfred /* wait till one of the transfers complete */ 1268195957Salfred return; 1269195957Salfred case 2: 1270195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer1); 1271199575Sthompsa if (sxfer == NULL) 1272199575Sthompsa return; /* cancelling */ 1273195957Salfred if (sxfer->rem_len) 1274195957Salfred return; /* cannot queue another one */ 1275195957Salfred /* swap transfers */ 1276195957Salfred pxfer1 = pxfer0; 1277195957Salfred break; 1278195957Salfred case 1: 1279195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer0); 1280199575Sthompsa if (sxfer == NULL) 1281199575Sthompsa return; /* cancelling */ 1282195957Salfred if (sxfer->rem_len) 1283195957Salfred return; /* cannot queue another one */ 1284195957Salfred /* swap transfers */ 1285195957Salfred pxfer0 = pxfer1; 1286195957Salfred break; 1287195957Salfred default: 1288195957Salfred break; 1289194676Sthompsa } 1290195957Salfred 1291195957Salfred /* find next transfer on same endpoint */ 1292195957Salfred TAILQ_FOREACH(sxfer, &dev->tr_head, entry) { 1293195957Salfred 1294195957Salfred uxfer = (struct libusb_transfer *)( 1295195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1296195957Salfred 1297195957Salfred if (uxfer->endpoint == endpoint) { 1298195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1299195957Salfred sxfer->entry.tqe_prev = NULL; 1300195957Salfred goto found; 1301194676Sthompsa } 1302195957Salfred } 1303195957Salfred return; /* success */ 1304194676Sthompsa 1305195957Salfredfound: 1306194676Sthompsa 1307195957Salfred libusb20_tr_set_priv_sc0(pxfer0, pdev); 1308195957Salfred libusb20_tr_set_priv_sc1(pxfer0, sxfer); 1309194676Sthompsa 1310195957Salfred /* reset super transfer state */ 1311195957Salfred sxfer->rem_len = uxfer->length; 1312195957Salfred sxfer->curr_data = uxfer->buffer; 1313195957Salfred uxfer->actual_length = 0; 1314194676Sthompsa 1315195957Salfred switch (uxfer->type) { 1316195957Salfred case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1317195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); 1318195957Salfred break; 1319195957Salfred case LIBUSB_TRANSFER_TYPE_BULK: 1320195957Salfred case LIBUSB_TRANSFER_TYPE_INTERRUPT: 1321195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); 1322195957Salfred break; 1323195957Salfred case LIBUSB_TRANSFER_TYPE_CONTROL: 1324195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); 1325195957Salfred if (sxfer->rem_len < 8) 1326195957Salfred goto failure; 1327194676Sthompsa 1328195957Salfred /* remove SETUP packet from data */ 1329195957Salfred sxfer->rem_len -= 8; 1330195957Salfred sxfer->curr_data += 8; 1331195957Salfred break; 1332195957Salfred default: 1333195957Salfred goto failure; 1334195560Sthompsa } 1335195957Salfred 1336195957Salfred buffsize = libusb10_get_buffsize(pdev, uxfer); 1337195957Salfred maxframe = libusb10_get_maxframe(pdev, uxfer); 1338195957Salfred 1339195957Salfred /* make sure the transfer is opened */ 1340195957Salfred err = libusb20_tr_open(pxfer0, buffsize, maxframe, endpoint); 1341195957Salfred if (err && (err != LIBUSB20_ERROR_BUSY)) { 1342195957Salfred goto failure; 1343194676Sthompsa } 1344195957Salfred libusb20_tr_start(pxfer0); 1345195957Salfred return; 1346194676Sthompsa 1347195957Salfredfailure: 1348195957Salfred libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); 1349194676Sthompsa 1350195957Salfred /* make sure our event loop spins the done handler */ 1351195957Salfred dummy = 0; 1352248236Shselasky err = write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 1353195957Salfred} 1354194676Sthompsa 1355195957Salfred/* The following function must be called unlocked */ 1356194676Sthompsa 1357195957Salfredint 1358195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer) 1359195957Salfred{ 1360195957Salfred struct libusb20_transfer *pxfer0; 1361195957Salfred struct libusb20_transfer *pxfer1; 1362195957Salfred struct libusb_super_transfer *sxfer; 1363195957Salfred struct libusb_device *dev; 1364234684Shselasky uint8_t endpoint; 1365195957Salfred int err; 1366195957Salfred 1367195957Salfred if (uxfer == NULL) 1368195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1369195957Salfred 1370195957Salfred if (uxfer->dev_handle == NULL) 1371195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1372195957Salfred 1373195957Salfred endpoint = uxfer->endpoint; 1374195957Salfred 1375195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1376195957Salfred 1377195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); 1378195957Salfred 1379195957Salfred sxfer = (struct libusb_super_transfer *)( 1380195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1381195957Salfred 1382195957Salfred CTX_LOCK(dev->ctx); 1383195957Salfred 1384195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1385195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1386195957Salfred 1387195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) { 1388195957Salfred err = LIBUSB_ERROR_OTHER; 1389195957Salfred } else if ((sxfer->entry.tqe_prev != NULL) || 1390199575Sthompsa (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) || 1391195957Salfred (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) { 1392195957Salfred err = LIBUSB_ERROR_BUSY; 1393195957Salfred } else { 1394199575Sthompsa 1395199575Sthompsa /* set pending state */ 1396199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_PEND; 1397199575Sthompsa 1398199575Sthompsa /* insert transfer into transfer head list */ 1399195957Salfred TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry); 1400195957Salfred 1401199575Sthompsa /* start work transfers */ 1402195957Salfred libusb10_submit_transfer_sub( 1403195957Salfred uxfer->dev_handle, endpoint); 1404195957Salfred 1405195957Salfred err = 0; /* success */ 1406195957Salfred } 1407195957Salfred 1408195957Salfred CTX_UNLOCK(dev->ctx); 1409195957Salfred 1410195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); 1411195957Salfred 1412195957Salfred return (err); 1413194676Sthompsa} 1414194676Sthompsa 1415195957Salfred/* Asynchronous transfer cancel */ 1416195957Salfred 1417194676Sthompsaint 1418195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer) 1419194676Sthompsa{ 1420195957Salfred struct libusb20_transfer *pxfer0; 1421195957Salfred struct libusb20_transfer *pxfer1; 1422195957Salfred struct libusb_super_transfer *sxfer; 1423195957Salfred struct libusb_device *dev; 1424234684Shselasky uint8_t endpoint; 1425199575Sthompsa int retval; 1426194676Sthompsa 1427195957Salfred if (uxfer == NULL) 1428195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1429194676Sthompsa 1430199575Sthompsa /* check if not initialised */ 1431195957Salfred if (uxfer->dev_handle == NULL) 1432199575Sthompsa return (LIBUSB_ERROR_NOT_FOUND); 1433194676Sthompsa 1434195957Salfred endpoint = uxfer->endpoint; 1435194676Sthompsa 1436195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1437195957Salfred 1438195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); 1439195957Salfred 1440195957Salfred sxfer = (struct libusb_super_transfer *)( 1441195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1442195957Salfred 1443199575Sthompsa retval = 0; 1444199575Sthompsa 1445195957Salfred CTX_LOCK(dev->ctx); 1446195957Salfred 1447195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1448195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1449195957Salfred 1450199575Sthompsa if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { 1451199575Sthompsa /* only update the transfer status */ 1452199575Sthompsa uxfer->status = LIBUSB_TRANSFER_CANCELLED; 1453199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1454199575Sthompsa } else if (sxfer->entry.tqe_prev != NULL) { 1455195957Salfred /* we are lucky - transfer is on a queue */ 1456195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1457195957Salfred sxfer->entry.tqe_prev = NULL; 1458199575Sthompsa libusb10_complete_transfer(NULL, 1459199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1460195957Salfred } else if (pxfer0 == NULL || pxfer1 == NULL) { 1461195957Salfred /* not started */ 1462199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1463195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { 1464199575Sthompsa libusb10_complete_transfer(pxfer0, 1465199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1466195957Salfred libusb20_tr_stop(pxfer0); 1467195957Salfred /* make sure the queue doesn't stall */ 1468195957Salfred libusb10_submit_transfer_sub( 1469195957Salfred uxfer->dev_handle, endpoint); 1470195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { 1471199575Sthompsa libusb10_complete_transfer(pxfer1, 1472199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1473195957Salfred libusb20_tr_stop(pxfer1); 1474195957Salfred /* make sure the queue doesn't stall */ 1475195957Salfred libusb10_submit_transfer_sub( 1476195957Salfred uxfer->dev_handle, endpoint); 1477195957Salfred } else { 1478195957Salfred /* not started */ 1479199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1480195957Salfred } 1481195957Salfred 1482195957Salfred CTX_UNLOCK(dev->ctx); 1483195957Salfred 1484195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); 1485195957Salfred 1486199575Sthompsa return (retval); 1487194676Sthompsa} 1488194676Sthompsa 1489195957SalfredUNEXPORTED void 1490195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev) 1491195957Salfred{ 1492195957Salfred /* TODO */ 1493195957Salfred} 1494199055Sthompsa 1495199055Sthompsauint16_t 1496199055Sthompsalibusb_cpu_to_le16(uint16_t x) 1497199055Sthompsa{ 1498199055Sthompsa return (htole16(x)); 1499199055Sthompsa} 1500199055Sthompsa 1501199055Sthompsauint16_t 1502199055Sthompsalibusb_le16_to_cpu(uint16_t x) 1503199055Sthompsa{ 1504199055Sthompsa return (le16toh(x)); 1505199055Sthompsa} 1506199055Sthompsa 1507213853Shselaskyconst char * 1508213853Shselaskylibusb_strerror(int code) 1509213853Shselasky{ 1510225659Shselasky switch (code) { 1511225659Shselasky case LIBUSB_SUCCESS: 1512225659Shselasky return ("Success"); 1513225659Shselasky case LIBUSB_ERROR_IO: 1514225659Shselasky return ("I/O error"); 1515225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1516225659Shselasky return ("Invalid parameter"); 1517225659Shselasky case LIBUSB_ERROR_ACCESS: 1518225659Shselasky return ("Permissions error"); 1519225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1520225659Shselasky return ("No device"); 1521225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1522225659Shselasky return ("Not found"); 1523225659Shselasky case LIBUSB_ERROR_BUSY: 1524225659Shselasky return ("Device busy"); 1525225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1526225659Shselasky return ("Timeout"); 1527225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1528225659Shselasky return ("Overflow"); 1529225659Shselasky case LIBUSB_ERROR_PIPE: 1530225659Shselasky return ("Pipe error"); 1531225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1532225659Shselasky return ("Interrupted"); 1533225659Shselasky case LIBUSB_ERROR_NO_MEM: 1534225659Shselasky return ("Out of memory"); 1535225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1536225659Shselasky return ("Not supported"); 1537225659Shselasky case LIBUSB_ERROR_OTHER: 1538225659Shselasky return ("Other error"); 1539225659Shselasky default: 1540225659Shselasky return ("Unknown error"); 1541225659Shselasky } 1542213853Shselasky} 1543225659Shselasky 1544225659Shselaskyconst char * 1545225659Shselaskylibusb_error_name(int code) 1546225659Shselasky{ 1547225659Shselasky switch (code) { 1548225659Shselasky case LIBUSB_SUCCESS: 1549225659Shselasky return ("LIBUSB_SUCCESS"); 1550225659Shselasky case LIBUSB_ERROR_IO: 1551225659Shselasky return ("LIBUSB_ERROR_IO"); 1552225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1553225659Shselasky return ("LIBUSB_ERROR_INVALID_PARAM"); 1554225659Shselasky case LIBUSB_ERROR_ACCESS: 1555225659Shselasky return ("LIBUSB_ERROR_ACCESS"); 1556225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1557225659Shselasky return ("LIBUSB_ERROR_NO_DEVICE"); 1558225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1559225659Shselasky return ("LIBUSB_ERROR_NOT_FOUND"); 1560225659Shselasky case LIBUSB_ERROR_BUSY: 1561225659Shselasky return ("LIBUSB_ERROR_BUSY"); 1562225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1563225659Shselasky return ("LIBUSB_ERROR_TIMEOUT"); 1564225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1565225659Shselasky return ("LIBUSB_ERROR_OVERFLOW"); 1566225659Shselasky case LIBUSB_ERROR_PIPE: 1567225659Shselasky return ("LIBUSB_ERROR_PIPE"); 1568225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1569225659Shselasky return ("LIBUSB_ERROR_INTERRUPTED"); 1570225659Shselasky case LIBUSB_ERROR_NO_MEM: 1571225659Shselasky return ("LIBUSB_ERROR_NO_MEM"); 1572225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1573225659Shselasky return ("LIBUSB_ERROR_NOT_SUPPORTED"); 1574225659Shselasky case LIBUSB_ERROR_OTHER: 1575225659Shselasky return ("LIBUSB_ERROR_OTHER"); 1576225659Shselasky default: 1577225659Shselasky return ("LIBUSB_ERROR_UNKNOWN"); 1578225659Shselasky } 1579225659Shselasky} 1580