libusb10.c revision 302080
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10.c 302080 2016-06-22 10:38:41Z 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); 137302080Shselasky TAILQ_INIT(&ctx->hotplug_cbh); 138302080Shselasky TAILQ_INIT(&ctx->hotplug_devs); 139194676Sthompsa 140236944Shselasky if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) { 141236944Shselasky free(ctx); 142236944Shselasky return (LIBUSB_ERROR_NO_MEM); 143236944Shselasky } 144302080Shselasky if (pthread_mutex_init(&ctx->hotplug_lock, NULL) != 0) { 145302080Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 146302080Shselasky free(ctx); 147302080Shselasky return (LIBUSB_ERROR_NO_MEM); 148302080Shselasky } 149236944Shselasky if (pthread_condattr_init(&attr) != 0) { 150236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 151302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 152236944Shselasky free(ctx); 153236944Shselasky return (LIBUSB_ERROR_NO_MEM); 154236944Shselasky } 155236944Shselasky if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) { 156236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 157302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 158236944Shselasky pthread_condattr_destroy(&attr); 159236944Shselasky free(ctx); 160236944Shselasky return (LIBUSB_ERROR_OTHER); 161236944Shselasky } 162236944Shselasky if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) { 163236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 164302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 165236944Shselasky pthread_condattr_destroy(&attr); 166236944Shselasky free(ctx); 167236944Shselasky return (LIBUSB_ERROR_NO_MEM); 168236944Shselasky } 169236944Shselasky pthread_condattr_destroy(&attr); 170194676Sthompsa 171195957Salfred ctx->ctx_handler = NO_THREAD; 172302080Shselasky ctx->hotplug_handler = NO_THREAD; 173194676Sthompsa 174194676Sthompsa ret = pipe(ctx->ctrl_pipe); 175194676Sthompsa if (ret < 0) { 176195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 177302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 178195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 179194676Sthompsa free(ctx); 180194676Sthompsa return (LIBUSB_ERROR_OTHER); 181194676Sthompsa } 182195957Salfred /* set non-blocking mode on the control pipe to avoid deadlock */ 183213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[0]); 184213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[1]); 185194676Sthompsa 186195957Salfred libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); 187194676Sthompsa 188194676Sthompsa pthread_mutex_lock(&default_context_lock); 189194676Sthompsa if (usbi_default_context == NULL) { 190194676Sthompsa usbi_default_context = ctx; 191194676Sthompsa } 192194676Sthompsa pthread_mutex_unlock(&default_context_lock); 193194676Sthompsa 194194676Sthompsa if (context) 195194676Sthompsa *context = ctx; 196194676Sthompsa 197195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); 198195957Salfred 199194676Sthompsa return (0); 200194676Sthompsa} 201194676Sthompsa 202194676Sthompsavoid 203195957Salfredlibusb_exit(libusb_context *ctx) 204194676Sthompsa{ 205195957Salfred ctx = GET_CONTEXT(ctx); 206194676Sthompsa 207195957Salfred if (ctx == NULL) 208195957Salfred return; 209195957Salfred 210302080Shselasky /* stop hotplug thread, if any */ 211302080Shselasky 212302080Shselasky if (ctx->hotplug_handler != NO_THREAD) { 213302080Shselasky pthread_t td; 214302080Shselasky void *ptr; 215302080Shselasky 216302080Shselasky HOTPLUG_LOCK(ctx); 217302080Shselasky td = ctx->hotplug_handler; 218302080Shselasky ctx->hotplug_handler = NO_THREAD; 219302080Shselasky HOTPLUG_UNLOCK(ctx); 220302080Shselasky 221302080Shselasky pthread_join(td, &ptr); 222302080Shselasky } 223302080Shselasky 224195957Salfred /* XXX cleanup devices */ 225195957Salfred 226195957Salfred libusb10_remove_pollfd(ctx, &ctx->ctx_poll); 227194676Sthompsa close(ctx->ctrl_pipe[0]); 228194676Sthompsa close(ctx->ctrl_pipe[1]); 229195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 230302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 231195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 232194676Sthompsa 233194676Sthompsa pthread_mutex_lock(&default_context_lock); 234194676Sthompsa if (ctx == usbi_default_context) { 235194676Sthompsa usbi_default_context = NULL; 236194676Sthompsa } 237194676Sthompsa pthread_mutex_unlock(&default_context_lock); 238194676Sthompsa 239194676Sthompsa free(ctx); 240194676Sthompsa} 241194676Sthompsa 242194676Sthompsa/* Device handling and initialisation. */ 243194676Sthompsa 244194676Sthompsassize_t 245195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list) 246194676Sthompsa{ 247195957Salfred struct libusb20_backend *usb_backend; 248194676Sthompsa struct libusb20_device *pdev; 249194676Sthompsa struct libusb_device *dev; 250194676Sthompsa int i; 251194676Sthompsa 252195957Salfred ctx = GET_CONTEXT(ctx); 253194676Sthompsa 254195957Salfred if (ctx == NULL) 255195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 256195957Salfred 257195957Salfred if (list == NULL) 258195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 259195957Salfred 260194676Sthompsa usb_backend = libusb20_be_alloc_default(); 261194676Sthompsa if (usb_backend == NULL) 262195957Salfred return (LIBUSB_ERROR_NO_MEM); 263194676Sthompsa 264195957Salfred /* figure out how many USB devices are present */ 265194676Sthompsa pdev = NULL; 266194676Sthompsa i = 0; 267194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) 268194676Sthompsa i++; 269194676Sthompsa 270195957Salfred /* allocate device pointer list */ 271194676Sthompsa *list = malloc((i + 1) * sizeof(void *)); 272194676Sthompsa if (*list == NULL) { 273194676Sthompsa libusb20_be_free(usb_backend); 274194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 275194676Sthompsa } 276195957Salfred /* create libusb v1.0 compliant devices */ 277194676Sthompsa i = 0; 278194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 279194676Sthompsa 280194676Sthompsa dev = malloc(sizeof(*dev)); 281194676Sthompsa if (dev == NULL) { 282195560Sthompsa while (i != 0) { 283195560Sthompsa libusb_unref_device((*list)[i - 1]); 284195560Sthompsa i--; 285195560Sthompsa } 286194676Sthompsa free(*list); 287195957Salfred *list = NULL; 288194676Sthompsa libusb20_be_free(usb_backend); 289194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 290194676Sthompsa } 291199055Sthompsa /* get device into libUSB v1.0 list */ 292199055Sthompsa libusb20_be_dequeue_device(usb_backend, pdev); 293199055Sthompsa 294194676Sthompsa memset(dev, 0, sizeof(*dev)); 295194676Sthompsa 296195957Salfred /* init transfer queues */ 297195957Salfred TAILQ_INIT(&dev->tr_head); 298195957Salfred 299195957Salfred /* set context we belong to */ 300194676Sthompsa dev->ctx = ctx; 301194676Sthompsa 302194676Sthompsa /* link together the two structures */ 303194676Sthompsa dev->os_priv = pdev; 304195957Salfred pdev->privLuData = dev; 305194676Sthompsa 306194676Sthompsa (*list)[i] = libusb_ref_device(dev); 307194676Sthompsa i++; 308194676Sthompsa } 309194676Sthompsa (*list)[i] = NULL; 310194676Sthompsa 311194676Sthompsa libusb20_be_free(usb_backend); 312194676Sthompsa return (i); 313194676Sthompsa} 314194676Sthompsa 315194676Sthompsavoid 316194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices) 317194676Sthompsa{ 318194676Sthompsa int i; 319194676Sthompsa 320194676Sthompsa if (list == NULL) 321195957Salfred return; /* be NULL safe */ 322194676Sthompsa 323194676Sthompsa if (unref_devices) { 324194676Sthompsa for (i = 0; list[i] != NULL; i++) 325194676Sthompsa libusb_unref_device(list[i]); 326194676Sthompsa } 327194676Sthompsa free(list); 328194676Sthompsa} 329194676Sthompsa 330194676Sthompsauint8_t 331195957Salfredlibusb_get_bus_number(libusb_device *dev) 332194676Sthompsa{ 333194676Sthompsa if (dev == NULL) 334195957Salfred return (0); /* should not happen */ 335195957Salfred return (libusb20_dev_get_bus_number(dev->os_priv)); 336194676Sthompsa} 337194676Sthompsa 338301964Shselaskyuint8_t 339301964Shselaskylibusb_get_port_number(libusb_device *dev) 340301964Shselasky{ 341301964Shselasky if (dev == NULL) 342301964Shselasky return (0); /* should not happen */ 343301964Shselasky return (libusb20_dev_get_parent_port(dev->os_priv)); 344301964Shselasky} 345301964Shselasky 346250342Semasteint 347251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) 348251495Semaste{ 349251495Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 350251495Semaste} 351251495Semaste 352251495Semasteint 353250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, 354250342Semaste uint8_t bufsize) 355250342Semaste{ 356250342Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 357250342Semaste} 358250342Semaste 359194676Sthompsauint8_t 360195957Salfredlibusb_get_device_address(libusb_device *dev) 361194676Sthompsa{ 362194676Sthompsa if (dev == NULL) 363195957Salfred return (0); /* should not happen */ 364195957Salfred return (libusb20_dev_get_address(dev->os_priv)); 365194676Sthompsa} 366194676Sthompsa 367224903Shselaskyenum libusb_speed 368224903Shselaskylibusb_get_device_speed(libusb_device *dev) 369224903Shselasky{ 370224903Shselasky if (dev == NULL) 371225035Shselasky return (LIBUSB_SPEED_UNKNOWN); /* should not happen */ 372224903Shselasky 373224903Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 374224903Shselasky case LIBUSB20_SPEED_LOW: 375224903Shselasky return (LIBUSB_SPEED_LOW); 376224903Shselasky case LIBUSB20_SPEED_FULL: 377224903Shselasky return (LIBUSB_SPEED_FULL); 378224903Shselasky case LIBUSB20_SPEED_HIGH: 379224903Shselasky return (LIBUSB_SPEED_HIGH); 380224903Shselasky case LIBUSB20_SPEED_SUPER: 381224903Shselasky return (LIBUSB_SPEED_SUPER); 382224903Shselasky default: 383224903Shselasky break; 384224903Shselasky } 385224903Shselasky return (LIBUSB_SPEED_UNKNOWN); 386224903Shselasky} 387224903Shselasky 388194676Sthompsaint 389195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint) 390194676Sthompsa{ 391194676Sthompsa struct libusb_config_descriptor *pdconf; 392194676Sthompsa struct libusb_interface *pinf; 393194676Sthompsa struct libusb_interface_descriptor *pdinf; 394194676Sthompsa struct libusb_endpoint_descriptor *pdend; 395195957Salfred int i; 396195957Salfred int j; 397195957Salfred int k; 398195957Salfred int ret; 399194676Sthompsa 400194676Sthompsa if (dev == NULL) 401194676Sthompsa return (LIBUSB_ERROR_NO_DEVICE); 402194676Sthompsa 403195957Salfred ret = libusb_get_active_config_descriptor(dev, &pdconf); 404195957Salfred if (ret < 0) 405195957Salfred return (ret); 406195957Salfred 407194676Sthompsa ret = LIBUSB_ERROR_NOT_FOUND; 408195957Salfred for (i = 0; i < pdconf->bNumInterfaces; i++) { 409194676Sthompsa pinf = &pdconf->interface[i]; 410195957Salfred for (j = 0; j < pinf->num_altsetting; j++) { 411194676Sthompsa pdinf = &pinf->altsetting[j]; 412195957Salfred for (k = 0; k < pdinf->bNumEndpoints; k++) { 413194676Sthompsa pdend = &pdinf->endpoint[k]; 414194676Sthompsa if (pdend->bEndpointAddress == endpoint) { 415194676Sthompsa ret = pdend->wMaxPacketSize; 416194676Sthompsa goto out; 417194676Sthompsa } 418194676Sthompsa } 419194676Sthompsa } 420194676Sthompsa } 421194676Sthompsa 422194676Sthompsaout: 423194676Sthompsa libusb_free_config_descriptor(pdconf); 424194676Sthompsa return (ret); 425194676Sthompsa} 426194676Sthompsa 427234193Shselaskyint 428234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint) 429234193Shselasky{ 430234193Shselasky int multiplier; 431234193Shselasky int ret; 432234193Shselasky 433234193Shselasky ret = libusb_get_max_packet_size(dev, endpoint); 434234193Shselasky 435234193Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 436234193Shselasky case LIBUSB20_SPEED_LOW: 437234193Shselasky case LIBUSB20_SPEED_FULL: 438234193Shselasky break; 439234193Shselasky default: 440234193Shselasky if (ret > -1) { 441234193Shselasky multiplier = (1 + ((ret >> 11) & 3)); 442234193Shselasky if (multiplier > 3) 443234193Shselasky multiplier = 3; 444234193Shselasky ret = (ret & 0x7FF) * multiplier; 445234193Shselasky } 446234193Shselasky break; 447234193Shselasky } 448234193Shselasky return (ret); 449234193Shselasky} 450234193Shselasky 451194676Sthompsalibusb_device * 452195957Salfredlibusb_ref_device(libusb_device *dev) 453194676Sthompsa{ 454194676Sthompsa if (dev == NULL) 455195957Salfred return (NULL); /* be NULL safe */ 456194676Sthompsa 457195957Salfred CTX_LOCK(dev->ctx); 458194676Sthompsa dev->refcnt++; 459195957Salfred CTX_UNLOCK(dev->ctx); 460194676Sthompsa 461194676Sthompsa return (dev); 462194676Sthompsa} 463194676Sthompsa 464194676Sthompsavoid 465195957Salfredlibusb_unref_device(libusb_device *dev) 466194676Sthompsa{ 467194676Sthompsa if (dev == NULL) 468195957Salfred return; /* be NULL safe */ 469194676Sthompsa 470195957Salfred CTX_LOCK(dev->ctx); 471194676Sthompsa dev->refcnt--; 472195957Salfred CTX_UNLOCK(dev->ctx); 473194676Sthompsa 474194676Sthompsa if (dev->refcnt == 0) { 475194676Sthompsa libusb20_dev_free(dev->os_priv); 476194676Sthompsa free(dev); 477194676Sthompsa } 478194676Sthompsa} 479194676Sthompsa 480194676Sthompsaint 481195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh) 482194676Sthompsa{ 483194676Sthompsa libusb_context *ctx = dev->ctx; 484194676Sthompsa struct libusb20_device *pdev = dev->os_priv; 485195957Salfred uint8_t dummy; 486194676Sthompsa int err; 487194676Sthompsa 488194676Sthompsa if (devh == NULL) 489194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 490194676Sthompsa 491195957Salfred /* set default device handle value */ 492195957Salfred *devh = NULL; 493194676Sthompsa 494195957Salfred dev = libusb_ref_device(dev); 495195957Salfred if (dev == NULL) 496195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 497195957Salfred 498301842Shselasky err = libusb20_dev_open(pdev, LIBUSB_NUM_SW_ENDPOINTS); 499194676Sthompsa if (err) { 500195957Salfred libusb_unref_device(dev); 501194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 502194676Sthompsa } 503195957Salfred libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 504194676Sthompsa POLLOUT | POLLRDNORM | POLLWRNORM); 505194676Sthompsa 506195957Salfred /* make sure our event loop detects the new device */ 507195957Salfred dummy = 0; 508194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 509213853Shselasky if (err < (int)sizeof(dummy)) { 510195957Salfred /* ignore error, if any */ 511195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!"); 512194676Sthompsa } 513195957Salfred *devh = pdev; 514194676Sthompsa 515194676Sthompsa return (0); 516194676Sthompsa} 517194676Sthompsa 518194676Sthompsalibusb_device_handle * 519195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, 520194676Sthompsa uint16_t product_id) 521194676Sthompsa{ 522194676Sthompsa struct libusb_device **devs; 523194676Sthompsa struct libusb20_device *pdev; 524194676Sthompsa struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 525195957Salfred int i; 526195957Salfred int j; 527194676Sthompsa 528195957Salfred ctx = GET_CONTEXT(ctx); 529195957Salfred if (ctx == NULL) 530195957Salfred return (NULL); /* be NULL safe */ 531195957Salfred 532195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter"); 533194676Sthompsa 534194676Sthompsa if ((i = libusb_get_device_list(ctx, &devs)) < 0) 535194676Sthompsa return (NULL); 536194676Sthompsa 537228236Shselasky pdev = NULL; 538194676Sthompsa for (j = 0; j < i; j++) { 539228236Shselasky struct libusb20_device *tdev; 540228236Shselasky 541228236Shselasky tdev = devs[j]->os_priv; 542228236Shselasky pdesc = libusb20_dev_get_device_desc(tdev); 543195957Salfred /* 544195957Salfred * NOTE: The USB library will automatically swap the 545195957Salfred * fields in the device descriptor to be of host 546195957Salfred * endian type! 547195957Salfred */ 548194676Sthompsa if (pdesc->idVendor == vendor_id && 549195560Sthompsa pdesc->idProduct == product_id) { 550228235Shselasky libusb_open(devs[j], &pdev); 551195957Salfred break; 552195560Sthompsa } 553194676Sthompsa } 554194676Sthompsa 555194676Sthompsa libusb_free_device_list(devs, 1); 556195560Sthompsa DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave"); 557195957Salfred return (pdev); 558194676Sthompsa} 559194676Sthompsa 560194676Sthompsavoid 561195957Salfredlibusb_close(struct libusb20_device *pdev) 562194676Sthompsa{ 563194676Sthompsa libusb_context *ctx; 564195957Salfred struct libusb_device *dev; 565195957Salfred uint8_t dummy; 566194676Sthompsa int err; 567194676Sthompsa 568195957Salfred if (pdev == NULL) 569195957Salfred return; /* be NULL safe */ 570194676Sthompsa 571195957Salfred dev = libusb_get_device(pdev); 572195957Salfred ctx = dev->ctx; 573194676Sthompsa 574195957Salfred libusb10_remove_pollfd(ctx, &dev->dev_poll); 575194676Sthompsa 576195957Salfred libusb20_dev_close(pdev); 577199055Sthompsa 578199055Sthompsa /* unref will free the "pdev" when the refcount reaches zero */ 579195957Salfred libusb_unref_device(dev); 580194676Sthompsa 581195957Salfred /* make sure our event loop detects the closed device */ 582195957Salfred dummy = 0; 583194676Sthompsa err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 584213853Shselasky if (err < (int)sizeof(dummy)) { 585195957Salfred /* ignore error, if any */ 586195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!"); 587194676Sthompsa } 588194676Sthompsa} 589194676Sthompsa 590194676Sthompsalibusb_device * 591195957Salfredlibusb_get_device(struct libusb20_device *pdev) 592194676Sthompsa{ 593195957Salfred if (pdev == NULL) 594194676Sthompsa return (NULL); 595195957Salfred return ((libusb_device *)pdev->privLuData); 596194676Sthompsa} 597194676Sthompsa 598194676Sthompsaint 599195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config) 600194676Sthompsa{ 601195957Salfred struct libusb20_config *pconf; 602194676Sthompsa 603195957Salfred if (pdev == NULL || config == NULL) 604194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 605194676Sthompsa 606195957Salfred pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); 607195957Salfred if (pconf == NULL) 608195957Salfred return (LIBUSB_ERROR_NO_MEM); 609194676Sthompsa 610195957Salfred *config = pconf->desc.bConfigurationValue; 611195957Salfred 612195957Salfred free(pconf); 613195957Salfred 614194676Sthompsa return (0); 615194676Sthompsa} 616194676Sthompsa 617194676Sthompsaint 618195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration) 619194676Sthompsa{ 620195957Salfred struct libusb20_config *pconf; 621195957Salfred struct libusb_device *dev; 622195957Salfred int err; 623195957Salfred uint8_t i; 624194676Sthompsa 625195957Salfred dev = libusb_get_device(pdev); 626195957Salfred if (dev == NULL) 627194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 628194676Sthompsa 629195957Salfred if (configuration < 1) { 630195957Salfred /* unconfigure */ 631195957Salfred i = 255; 632195957Salfred } else { 633195957Salfred for (i = 0; i != 255; i++) { 634195957Salfred uint8_t found; 635194676Sthompsa 636195957Salfred pconf = libusb20_dev_alloc_config(pdev, i); 637195957Salfred if (pconf == NULL) 638195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 639195957Salfred found = (pconf->desc.bConfigurationValue 640195957Salfred == configuration); 641195957Salfred free(pconf); 642195957Salfred 643195957Salfred if (found) 644195957Salfred goto set_config; 645195957Salfred } 646195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 647195957Salfred } 648195957Salfred 649195957Salfredset_config: 650195957Salfred 651195957Salfred libusb10_cancel_all_transfer(dev); 652195957Salfred 653195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 654195957Salfred 655195957Salfred err = libusb20_dev_set_config_index(pdev, i); 656195957Salfred 657195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 658195957Salfred POLLOUT | POLLRDNORM | POLLWRNORM); 659195957Salfred 660195957Salfred return (err ? LIBUSB_ERROR_INVALID_PARAM : 0); 661194676Sthompsa} 662194676Sthompsa 663194676Sthompsaint 664195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number) 665194676Sthompsa{ 666195957Salfred libusb_device *dev; 667301966Shselasky int err = 0; 668194676Sthompsa 669195957Salfred dev = libusb_get_device(pdev); 670194676Sthompsa if (dev == NULL) 671194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 672194676Sthompsa 673195957Salfred if (interface_number < 0 || interface_number > 31) 674194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 675194676Sthompsa 676301966Shselasky if (pdev->auto_detach != 0) { 677301966Shselasky err = libusb_detach_kernel_driver(pdev, interface_number); 678301966Shselasky if (err != 0) 679301966Shselasky goto done; 680301966Shselasky } 681301966Shselasky 682195957Salfred CTX_LOCK(dev->ctx); 683261224Shselasky dev->claimed_interfaces |= (1 << interface_number); 684261224Shselasky CTX_UNLOCK(dev->ctx); 685301966Shselaskydone: 686301966Shselasky return (err); 687194676Sthompsa} 688194676Sthompsa 689194676Sthompsaint 690195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number) 691194676Sthompsa{ 692195957Salfred libusb_device *dev; 693195957Salfred int err = 0; 694194676Sthompsa 695195957Salfred dev = libusb_get_device(pdev); 696194676Sthompsa if (dev == NULL) 697194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 698194676Sthompsa 699195957Salfred if (interface_number < 0 || interface_number > 31) 700194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 701194676Sthompsa 702301966Shselasky if (pdev->auto_detach != 0) { 703301966Shselasky err = libusb_attach_kernel_driver(pdev, interface_number); 704301966Shselasky if (err != 0) 705301966Shselasky goto done; 706301966Shselasky } 707301966Shselasky 708195957Salfred CTX_LOCK(dev->ctx); 709194676Sthompsa if (!(dev->claimed_interfaces & (1 << interface_number))) 710195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 711301966Shselasky else 712194676Sthompsa dev->claimed_interfaces &= ~(1 << interface_number); 713195957Salfred CTX_UNLOCK(dev->ctx); 714301966Shselaskydone: 715195957Salfred return (err); 716194676Sthompsa} 717194676Sthompsa 718194676Sthompsaint 719195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev, 720194676Sthompsa int interface_number, int alternate_setting) 721194676Sthompsa{ 722195957Salfred libusb_device *dev; 723195957Salfred int err = 0; 724194676Sthompsa 725195957Salfred dev = libusb_get_device(pdev); 726194676Sthompsa if (dev == NULL) 727194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 728194676Sthompsa 729195957Salfred if (interface_number < 0 || interface_number > 31) 730194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 731194676Sthompsa 732195957Salfred CTX_LOCK(dev->ctx); 733195957Salfred if (!(dev->claimed_interfaces & (1 << interface_number))) 734195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 735195957Salfred CTX_UNLOCK(dev->ctx); 736194676Sthompsa 737195957Salfred if (err) 738195957Salfred return (err); 739195957Salfred 740195957Salfred libusb10_cancel_all_transfer(dev); 741195957Salfred 742195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 743195957Salfred 744195957Salfred err = libusb20_dev_set_alt_index(pdev, 745195957Salfred interface_number, alternate_setting); 746195957Salfred 747195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 748195957Salfred pdev, libusb20_dev_get_fd(pdev), 749195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 750195957Salfred 751195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 752194676Sthompsa} 753194676Sthompsa 754195957Salfredstatic struct libusb20_transfer * 755195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev, 756234491Shselasky uint8_t endpoint, uint8_t xfer_index) 757195957Salfred{ 758234491Shselasky xfer_index &= 1; /* double buffering */ 759195957Salfred 760234491Shselasky xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4; 761195957Salfred 762195957Salfred if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) { 763195957Salfred /* this is an IN endpoint */ 764234491Shselasky xfer_index |= 2; 765195957Salfred } 766234491Shselasky return (libusb20_tr_get_pointer(pdev, xfer_index)); 767195957Salfred} 768195957Salfred 769194676Sthompsaint 770195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint) 771194676Sthompsa{ 772194676Sthompsa struct libusb20_transfer *xfer; 773195957Salfred struct libusb_device *dev; 774195957Salfred int err; 775194676Sthompsa 776195957Salfred xfer = libusb10_get_transfer(pdev, endpoint, 0); 777195560Sthompsa if (xfer == NULL) 778195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 779194676Sthompsa 780195957Salfred dev = libusb_get_device(pdev); 781213853Shselasky if (dev == NULL) 782213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 783195957Salfred 784195957Salfred CTX_LOCK(dev->ctx); 785223642Shselasky err = libusb20_tr_open(xfer, 0, 1, endpoint); 786195957Salfred CTX_UNLOCK(dev->ctx); 787195957Salfred 788195957Salfred if (err != 0 && err != LIBUSB20_ERROR_BUSY) 789194676Sthompsa return (LIBUSB_ERROR_OTHER); 790194676Sthompsa 791194676Sthompsa libusb20_tr_clear_stall_sync(xfer); 792195957Salfred 793195957Salfred /* check if we opened the transfer */ 794195957Salfred if (err == 0) { 795195957Salfred CTX_LOCK(dev->ctx); 796194676Sthompsa libusb20_tr_close(xfer); 797195957Salfred CTX_UNLOCK(dev->ctx); 798195957Salfred } 799195957Salfred return (0); /* success */ 800194676Sthompsa} 801194676Sthompsa 802194676Sthompsaint 803195957Salfredlibusb_reset_device(struct libusb20_device *pdev) 804194676Sthompsa{ 805195957Salfred libusb_device *dev; 806195957Salfred int err; 807194676Sthompsa 808195957Salfred dev = libusb_get_device(pdev); 809194676Sthompsa if (dev == NULL) 810213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 811194676Sthompsa 812195957Salfred libusb10_cancel_all_transfer(dev); 813195957Salfred 814195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 815195957Salfred 816195957Salfred err = libusb20_dev_reset(pdev); 817195957Salfred 818195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 819195957Salfred pdev, libusb20_dev_get_fd(pdev), 820195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 821195957Salfred 822195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 823194676Sthompsa} 824194676Sthompsa 825194676Sthompsaint 826213848Shselaskylibusb_check_connected(struct libusb20_device *pdev) 827213848Shselasky{ 828213848Shselasky libusb_device *dev; 829213848Shselasky int err; 830213848Shselasky 831213848Shselasky dev = libusb_get_device(pdev); 832213848Shselasky if (dev == NULL) 833213848Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 834213848Shselasky 835213848Shselasky err = libusb20_dev_check_connected(pdev); 836213848Shselasky 837213848Shselasky return (err ? LIBUSB_ERROR_NO_DEVICE : 0); 838213848Shselasky} 839213848Shselasky 840213848Shselaskyint 841195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface) 842194676Sthompsa{ 843195957Salfred if (pdev == NULL) 844194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 845194676Sthompsa 846226220Shselasky if (libusb20_dev_kernel_driver_active(pdev, interface)) 847226220Shselasky return (0); /* no kernel driver is active */ 848226220Shselasky else 849226220Shselasky return (1); /* kernel driver is active */ 850194676Sthompsa} 851194676Sthompsa 852194676Sthompsaint 853213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface, 854213853Shselasky char *name, int namelen) 855213853Shselasky{ 856213853Shselasky return (libusb_get_driver(pdev, interface, name, namelen)); 857213853Shselasky} 858213853Shselasky 859213853Shselaskyint 860213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface, 861213853Shselasky char *name, int namelen) 862213853Shselasky{ 863213853Shselasky char *ptr; 864213853Shselasky int err; 865213853Shselasky 866213853Shselasky if (pdev == NULL) 867213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 868213853Shselasky if (namelen < 1) 869213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 870224085Shselasky if (namelen > 255) 871224085Shselasky namelen = 255; 872213853Shselasky 873213853Shselasky err = libusb20_dev_get_iface_desc( 874213853Shselasky pdev, interface, name, namelen); 875213853Shselasky 876213853Shselasky if (err != 0) 877213853Shselasky return (LIBUSB_ERROR_OTHER); 878213853Shselasky 879213853Shselasky /* we only want the driver name */ 880213853Shselasky ptr = strstr(name, ":"); 881213853Shselasky if (ptr != NULL) 882213853Shselasky *ptr = 0; 883213853Shselasky 884213853Shselasky return (0); 885213853Shselasky} 886213853Shselasky 887213853Shselaskyint 888213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface) 889213853Shselasky{ 890213853Shselasky return (libusb_detach_kernel_driver(pdev, interface)); 891213853Shselasky} 892213853Shselasky 893213853Shselaskyint 894195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface) 895194676Sthompsa{ 896195957Salfred int err; 897194676Sthompsa 898195957Salfred if (pdev == NULL) 899194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 900194676Sthompsa 901195957Salfred err = libusb20_dev_detach_kernel_driver( 902195957Salfred pdev, interface); 903194676Sthompsa 904213853Shselasky return (err ? LIBUSB_ERROR_OTHER : 0); 905194676Sthompsa} 906194676Sthompsa 907194676Sthompsaint 908195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface) 909194676Sthompsa{ 910195957Salfred if (pdev == NULL) 911194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 912195957Salfred /* stub - currently not supported by libusb20 */ 913194676Sthompsa return (0); 914194676Sthompsa} 915194676Sthompsa 916301966Shselaskyint 917301966Shselaskylibusb_set_auto_detach_kernel_driver(libusb_device_handle *dev, int enable) 918301966Shselasky{ 919301966Shselasky dev->auto_detach = (enable ? 1 : 0); 920301969Shselasky return (0); 921301966Shselasky} 922301966Shselasky 923194676Sthompsa/* Asynchronous device I/O */ 924194676Sthompsa 925194676Sthompsastruct libusb_transfer * 926194676Sthompsalibusb_alloc_transfer(int iso_packets) 927194676Sthompsa{ 928195957Salfred struct libusb_transfer *uxfer; 929195957Salfred struct libusb_super_transfer *sxfer; 930194676Sthompsa int len; 931194676Sthompsa 932194676Sthompsa len = sizeof(struct libusb_transfer) + 933195957Salfred sizeof(struct libusb_super_transfer) + 934194676Sthompsa (iso_packets * sizeof(libusb_iso_packet_descriptor)); 935194676Sthompsa 936195957Salfred sxfer = malloc(len); 937195957Salfred if (sxfer == NULL) 938194676Sthompsa return (NULL); 939194676Sthompsa 940195957Salfred memset(sxfer, 0, len); 941194676Sthompsa 942195957Salfred uxfer = (struct libusb_transfer *)( 943195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 944194676Sthompsa 945195957Salfred /* set default value */ 946195957Salfred uxfer->num_iso_packets = iso_packets; 947195957Salfred 948195957Salfred return (uxfer); 949194676Sthompsa} 950194676Sthompsa 951194676Sthompsavoid 952195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer) 953194676Sthompsa{ 954195957Salfred struct libusb_super_transfer *sxfer; 955194676Sthompsa 956195957Salfred if (uxfer == NULL) 957195957Salfred return; /* be NULL safe */ 958194676Sthompsa 959215253Shselasky /* check if we should free the transfer buffer */ 960215253Shselasky if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 961215253Shselasky free(uxfer->buffer); 962215253Shselasky 963195957Salfred sxfer = (struct libusb_super_transfer *)( 964195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 965194676Sthompsa 966195957Salfred free(sxfer); 967194676Sthompsa} 968194676Sthompsa 969219100Shselaskystatic uint32_t 970195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 971195560Sthompsa{ 972219100Shselasky uint32_t ret; 973195560Sthompsa 974195560Sthompsa switch (xfer->type) { 975195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 976219100Shselasky ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE; /* 60ms */ 977195957Salfred break; 978195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 979195560Sthompsa ret = 2; 980195957Salfred break; 981195560Sthompsa default: 982195560Sthompsa ret = 1; 983195957Salfred break; 984195560Sthompsa } 985195957Salfred return (ret); 986195560Sthompsa} 987195560Sthompsa 988195560Sthompsastatic int 989195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 990195560Sthompsa{ 991195560Sthompsa int ret; 992195560Sthompsa int usb_speed; 993195560Sthompsa 994195560Sthompsa usb_speed = libusb20_dev_get_speed(pdev); 995195560Sthompsa 996195560Sthompsa switch (xfer->type) { 997195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 998195957Salfred ret = 0; /* kernel will auto-select */ 999195957Salfred break; 1000195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 1001195957Salfred ret = 1024; 1002195957Salfred break; 1003195957Salfred default: 1004195560Sthompsa switch (usb_speed) { 1005195957Salfred case LIBUSB20_SPEED_LOW: 1006195957Salfred ret = 256; 1007195957Salfred break; 1008195957Salfred case LIBUSB20_SPEED_FULL: 1009195957Salfred ret = 4096; 1010195957Salfred break; 1011264344Shselasky case LIBUSB20_SPEED_SUPER: 1012264344Shselasky ret = 65536; 1013264344Shselasky break; 1014195957Salfred default: 1015195957Salfred ret = 16384; 1016195957Salfred break; 1017195560Sthompsa } 1018195957Salfred break; 1019195560Sthompsa } 1020195957Salfred return (ret); 1021195560Sthompsa} 1022195560Sthompsa 1023195957Salfredstatic int 1024195957Salfredlibusb10_convert_error(uint8_t status) 1025195957Salfred{ 1026195957Salfred ; /* indent fix */ 1027195957Salfred 1028195957Salfred switch (status) { 1029195957Salfred case LIBUSB20_TRANSFER_START: 1030195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1031195957Salfred return (LIBUSB_TRANSFER_COMPLETED); 1032195957Salfred case LIBUSB20_TRANSFER_OVERFLOW: 1033195957Salfred return (LIBUSB_TRANSFER_OVERFLOW); 1034195957Salfred case LIBUSB20_TRANSFER_NO_DEVICE: 1035195957Salfred return (LIBUSB_TRANSFER_NO_DEVICE); 1036195957Salfred case LIBUSB20_TRANSFER_STALL: 1037195957Salfred return (LIBUSB_TRANSFER_STALL); 1038195957Salfred case LIBUSB20_TRANSFER_CANCELLED: 1039195957Salfred return (LIBUSB_TRANSFER_CANCELLED); 1040195957Salfred case LIBUSB20_TRANSFER_TIMED_OUT: 1041195957Salfred return (LIBUSB_TRANSFER_TIMED_OUT); 1042195957Salfred default: 1043195957Salfred return (LIBUSB_TRANSFER_ERROR); 1044195957Salfred } 1045195957Salfred} 1046195957Salfred 1047195957Salfred/* This function must be called locked */ 1048195957Salfred 1049194676Sthompsastatic void 1050195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer, 1051195957Salfred struct libusb_super_transfer *sxfer, int status) 1052194676Sthompsa{ 1053195957Salfred struct libusb_transfer *uxfer; 1054195957Salfred struct libusb_device *dev; 1055195957Salfred 1056195957Salfred uxfer = (struct libusb_transfer *)( 1057195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1058195957Salfred 1059195957Salfred if (pxfer != NULL) 1060195957Salfred libusb20_tr_set_priv_sc1(pxfer, NULL); 1061195957Salfred 1062199575Sthompsa /* set transfer status */ 1063195957Salfred uxfer->status = status; 1064195957Salfred 1065199575Sthompsa /* update super transfer state */ 1066199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_NONE; 1067199575Sthompsa 1068195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1069195957Salfred 1070195957Salfred TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); 1071195957Salfred} 1072195957Salfred 1073195957Salfred/* This function must be called locked */ 1074195957Salfred 1075195957Salfredstatic void 1076195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer) 1077195957Salfred{ 1078195957Salfred struct libusb_super_transfer *sxfer; 1079195957Salfred struct libusb_transfer *uxfer; 1080195957Salfred uint32_t actlen; 1081195957Salfred uint16_t iso_packets; 1082195957Salfred uint16_t i; 1083194676Sthompsa uint8_t status; 1084194676Sthompsa 1085195957Salfred status = libusb20_tr_get_status(pxfer); 1086195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1087195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1088195957Salfred iso_packets = libusb20_tr_get_max_frames(pxfer); 1089194676Sthompsa 1090195957Salfred if (sxfer == NULL) 1091284744Saraujo return; /* cancelled - nothing to do */ 1092195957Salfred 1093195957Salfred uxfer = (struct libusb_transfer *)( 1094195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1095195957Salfred 1096195957Salfred if (iso_packets > uxfer->num_iso_packets) 1097195957Salfred iso_packets = uxfer->num_iso_packets; 1098195957Salfred 1099195957Salfred if (iso_packets == 0) 1100284744Saraujo return; /* nothing to do */ 1101195957Salfred 1102195957Salfred /* make sure that the number of ISOCHRONOUS packets is valid */ 1103195957Salfred uxfer->num_iso_packets = iso_packets; 1104195957Salfred 1105194676Sthompsa switch (status) { 1106194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1107195957Salfred /* update actual length */ 1108195957Salfred uxfer->actual_length = actlen; 1109195957Salfred for (i = 0; i != iso_packets; i++) { 1110195957Salfred uxfer->iso_packet_desc[i].actual_length = 1111195957Salfred libusb20_tr_get_length(pxfer, i); 1112195957Salfred } 1113195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1114195957Salfred break; 1115194676Sthompsa case LIBUSB20_TRANSFER_START: 1116195957Salfred /* setup length(s) */ 1117195957Salfred actlen = 0; 1118195957Salfred for (i = 0; i != iso_packets; i++) { 1119195957Salfred libusb20_tr_setup_isoc(pxfer, 1120195957Salfred &uxfer->buffer[actlen], 1121195957Salfred uxfer->iso_packet_desc[i].length, i); 1122195957Salfred actlen += uxfer->iso_packet_desc[i].length; 1123194676Sthompsa } 1124195957Salfred 1125195957Salfred /* no remainder */ 1126195957Salfred sxfer->rem_len = 0; 1127195957Salfred 1128195957Salfred libusb20_tr_set_total_frames(pxfer, iso_packets); 1129195957Salfred libusb20_tr_submit(pxfer); 1130195957Salfred 1131195957Salfred /* fork another USB transfer, if any */ 1132195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1133195957Salfred break; 1134194676Sthompsa default: 1135195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1136195957Salfred break; 1137194676Sthompsa } 1138195957Salfred} 1139194676Sthompsa 1140195957Salfred/* This function must be called locked */ 1141195957Salfred 1142195957Salfredstatic void 1143195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) 1144195957Salfred{ 1145195957Salfred struct libusb_super_transfer *sxfer; 1146195957Salfred struct libusb_transfer *uxfer; 1147195957Salfred uint32_t max_bulk; 1148195957Salfred uint32_t actlen; 1149195957Salfred uint8_t status; 1150195957Salfred uint8_t flags; 1151195957Salfred 1152195957Salfred status = libusb20_tr_get_status(pxfer); 1153195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1154195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1155195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1156195957Salfred 1157195957Salfred if (sxfer == NULL) 1158195957Salfred return; /* cancelled - nothing to do */ 1159195957Salfred 1160195957Salfred uxfer = (struct libusb_transfer *)( 1161195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1162195957Salfred 1163195957Salfred flags = uxfer->flags; 1164195957Salfred 1165194676Sthompsa switch (status) { 1166194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1167195957Salfred 1168195957Salfred uxfer->actual_length += actlen; 1169195957Salfred 1170195957Salfred /* check for short packet */ 1171195957Salfred if (sxfer->last_len != actlen) { 1172195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1173195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1174195957Salfred } else { 1175195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1176195957Salfred } 1177195957Salfred break; 1178195957Salfred } 1179195957Salfred /* check for end of data */ 1180195957Salfred if (sxfer->rem_len == 0) { 1181195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1182195957Salfred break; 1183195957Salfred } 1184195957Salfred /* FALLTHROUGH */ 1185195957Salfred 1186195957Salfred case LIBUSB20_TRANSFER_START: 1187195957Salfred if (max_bulk > sxfer->rem_len) { 1188195957Salfred max_bulk = sxfer->rem_len; 1189195957Salfred } 1190195957Salfred /* setup new BULK or INTERRUPT transaction */ 1191195957Salfred libusb20_tr_setup_bulk(pxfer, 1192195957Salfred sxfer->curr_data, max_bulk, uxfer->timeout); 1193195957Salfred 1194195957Salfred /* update counters */ 1195195957Salfred sxfer->last_len = max_bulk; 1196195957Salfred sxfer->curr_data += max_bulk; 1197195957Salfred sxfer->rem_len -= max_bulk; 1198195957Salfred 1199195957Salfred libusb20_tr_submit(pxfer); 1200195957Salfred 1201195957Salfred /* check if we can fork another USB transfer */ 1202195957Salfred if (sxfer->rem_len == 0) 1203195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1204195957Salfred break; 1205195957Salfred 1206195957Salfred default: 1207195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1208195957Salfred break; 1209194676Sthompsa } 1210194676Sthompsa} 1211194676Sthompsa 1212195957Salfred/* This function must be called locked */ 1213195957Salfred 1214195957Salfredstatic void 1215195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer) 1216194676Sthompsa{ 1217195957Salfred struct libusb_super_transfer *sxfer; 1218195957Salfred struct libusb_transfer *uxfer; 1219195957Salfred uint32_t max_bulk; 1220195957Salfred uint32_t actlen; 1221195957Salfred uint8_t status; 1222195957Salfred uint8_t flags; 1223194676Sthompsa 1224195957Salfred status = libusb20_tr_get_status(pxfer); 1225195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1226195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1227195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1228194676Sthompsa 1229195957Salfred if (sxfer == NULL) 1230195957Salfred return; /* cancelled - nothing to do */ 1231194676Sthompsa 1232195957Salfred uxfer = (struct libusb_transfer *)( 1233195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1234194676Sthompsa 1235195957Salfred flags = uxfer->flags; 1236194676Sthompsa 1237195957Salfred switch (status) { 1238195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1239194676Sthompsa 1240195957Salfred uxfer->actual_length += actlen; 1241195957Salfred 1242195957Salfred /* subtract length of SETUP packet, if any */ 1243195957Salfred actlen -= libusb20_tr_get_length(pxfer, 0); 1244195957Salfred 1245195957Salfred /* check for short packet */ 1246195957Salfred if (sxfer->last_len != actlen) { 1247195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1248195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1249195957Salfred } else { 1250195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1251195957Salfred } 1252195957Salfred break; 1253194676Sthompsa } 1254195957Salfred /* check for end of data */ 1255195957Salfred if (sxfer->rem_len == 0) { 1256195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1257195957Salfred break; 1258195957Salfred } 1259195957Salfred /* FALLTHROUGH */ 1260194676Sthompsa 1261195957Salfred case LIBUSB20_TRANSFER_START: 1262195957Salfred if (max_bulk > sxfer->rem_len) { 1263195957Salfred max_bulk = sxfer->rem_len; 1264195957Salfred } 1265195957Salfred /* setup new CONTROL transaction */ 1266195957Salfred if (status == LIBUSB20_TRANSFER_COMPLETED) { 1267195957Salfred /* next fragment - don't send SETUP packet */ 1268195957Salfred libusb20_tr_set_length(pxfer, 0, 0); 1269195957Salfred } else { 1270195957Salfred /* first fragment - send SETUP packet */ 1271195957Salfred libusb20_tr_set_length(pxfer, 8, 0); 1272195957Salfred libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0); 1273195957Salfred } 1274195957Salfred 1275195957Salfred if (max_bulk != 0) { 1276195957Salfred libusb20_tr_set_length(pxfer, max_bulk, 1); 1277195957Salfred libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1); 1278195957Salfred libusb20_tr_set_total_frames(pxfer, 2); 1279195957Salfred } else { 1280195957Salfred libusb20_tr_set_total_frames(pxfer, 1); 1281195957Salfred } 1282195957Salfred 1283195957Salfred /* update counters */ 1284195957Salfred sxfer->last_len = max_bulk; 1285195957Salfred sxfer->curr_data += max_bulk; 1286195957Salfred sxfer->rem_len -= max_bulk; 1287195957Salfred 1288195957Salfred libusb20_tr_submit(pxfer); 1289195957Salfred 1290195957Salfred /* check if we can fork another USB transfer */ 1291195957Salfred if (sxfer->rem_len == 0) 1292195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1293195957Salfred break; 1294195957Salfred 1295195957Salfred default: 1296195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1297195957Salfred break; 1298194676Sthompsa } 1299195957Salfred} 1300195957Salfred 1301195957Salfred/* The following function must be called locked */ 1302195957Salfred 1303195957Salfredstatic void 1304195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint) 1305195957Salfred{ 1306195957Salfred struct libusb20_transfer *pxfer0; 1307195957Salfred struct libusb20_transfer *pxfer1; 1308195957Salfred struct libusb_super_transfer *sxfer; 1309195957Salfred struct libusb_transfer *uxfer; 1310195957Salfred struct libusb_device *dev; 1311195957Salfred int err; 1312195957Salfred int buffsize; 1313195957Salfred int maxframe; 1314195957Salfred int temp; 1315195957Salfred uint8_t dummy; 1316195957Salfred 1317195957Salfred dev = libusb_get_device(pdev); 1318195957Salfred 1319195957Salfred pxfer0 = libusb10_get_transfer(pdev, endpoint, 0); 1320195957Salfred pxfer1 = libusb10_get_transfer(pdev, endpoint, 1); 1321195957Salfred 1322195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) 1323195957Salfred return; /* shouldn't happen */ 1324195957Salfred 1325195957Salfred temp = 0; 1326195957Salfred if (libusb20_tr_pending(pxfer0)) 1327195957Salfred temp |= 1; 1328195957Salfred if (libusb20_tr_pending(pxfer1)) 1329195957Salfred temp |= 2; 1330195957Salfred 1331195957Salfred switch (temp) { 1332195957Salfred case 3: 1333195957Salfred /* wait till one of the transfers complete */ 1334195957Salfred return; 1335195957Salfred case 2: 1336195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer1); 1337199575Sthompsa if (sxfer == NULL) 1338199575Sthompsa return; /* cancelling */ 1339195957Salfred if (sxfer->rem_len) 1340195957Salfred return; /* cannot queue another one */ 1341195957Salfred /* swap transfers */ 1342195957Salfred pxfer1 = pxfer0; 1343195957Salfred break; 1344195957Salfred case 1: 1345195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer0); 1346199575Sthompsa if (sxfer == NULL) 1347199575Sthompsa return; /* cancelling */ 1348195957Salfred if (sxfer->rem_len) 1349195957Salfred return; /* cannot queue another one */ 1350195957Salfred /* swap transfers */ 1351195957Salfred pxfer0 = pxfer1; 1352195957Salfred break; 1353195957Salfred default: 1354195957Salfred break; 1355194676Sthompsa } 1356195957Salfred 1357195957Salfred /* find next transfer on same endpoint */ 1358195957Salfred TAILQ_FOREACH(sxfer, &dev->tr_head, entry) { 1359195957Salfred 1360195957Salfred uxfer = (struct libusb_transfer *)( 1361195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1362195957Salfred 1363195957Salfred if (uxfer->endpoint == endpoint) { 1364195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1365195957Salfred sxfer->entry.tqe_prev = NULL; 1366195957Salfred goto found; 1367194676Sthompsa } 1368195957Salfred } 1369195957Salfred return; /* success */ 1370194676Sthompsa 1371195957Salfredfound: 1372194676Sthompsa 1373195957Salfred libusb20_tr_set_priv_sc0(pxfer0, pdev); 1374195957Salfred libusb20_tr_set_priv_sc1(pxfer0, sxfer); 1375194676Sthompsa 1376195957Salfred /* reset super transfer state */ 1377195957Salfred sxfer->rem_len = uxfer->length; 1378195957Salfred sxfer->curr_data = uxfer->buffer; 1379195957Salfred uxfer->actual_length = 0; 1380194676Sthompsa 1381195957Salfred switch (uxfer->type) { 1382195957Salfred case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1383195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); 1384195957Salfred break; 1385195957Salfred case LIBUSB_TRANSFER_TYPE_BULK: 1386195957Salfred case LIBUSB_TRANSFER_TYPE_INTERRUPT: 1387195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); 1388195957Salfred break; 1389195957Salfred case LIBUSB_TRANSFER_TYPE_CONTROL: 1390195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); 1391195957Salfred if (sxfer->rem_len < 8) 1392195957Salfred goto failure; 1393194676Sthompsa 1394195957Salfred /* remove SETUP packet from data */ 1395195957Salfred sxfer->rem_len -= 8; 1396195957Salfred sxfer->curr_data += 8; 1397195957Salfred break; 1398195957Salfred default: 1399195957Salfred goto failure; 1400195560Sthompsa } 1401195957Salfred 1402195957Salfred buffsize = libusb10_get_buffsize(pdev, uxfer); 1403195957Salfred maxframe = libusb10_get_maxframe(pdev, uxfer); 1404195957Salfred 1405195957Salfred /* make sure the transfer is opened */ 1406195957Salfred err = libusb20_tr_open(pxfer0, buffsize, maxframe, endpoint); 1407195957Salfred if (err && (err != LIBUSB20_ERROR_BUSY)) { 1408195957Salfred goto failure; 1409194676Sthompsa } 1410195957Salfred libusb20_tr_start(pxfer0); 1411195957Salfred return; 1412194676Sthompsa 1413195957Salfredfailure: 1414195957Salfred libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); 1415194676Sthompsa 1416195957Salfred /* make sure our event loop spins the done handler */ 1417195957Salfred dummy = 0; 1418248236Shselasky err = write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 1419195957Salfred} 1420194676Sthompsa 1421195957Salfred/* The following function must be called unlocked */ 1422194676Sthompsa 1423195957Salfredint 1424195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer) 1425195957Salfred{ 1426195957Salfred struct libusb20_transfer *pxfer0; 1427195957Salfred struct libusb20_transfer *pxfer1; 1428195957Salfred struct libusb_super_transfer *sxfer; 1429195957Salfred struct libusb_device *dev; 1430234684Shselasky uint8_t endpoint; 1431195957Salfred int err; 1432195957Salfred 1433195957Salfred if (uxfer == NULL) 1434195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1435195957Salfred 1436195957Salfred if (uxfer->dev_handle == NULL) 1437195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1438195957Salfred 1439195957Salfred endpoint = uxfer->endpoint; 1440195957Salfred 1441195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1442195957Salfred 1443195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); 1444195957Salfred 1445195957Salfred sxfer = (struct libusb_super_transfer *)( 1446195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1447195957Salfred 1448195957Salfred CTX_LOCK(dev->ctx); 1449195957Salfred 1450195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1451195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1452195957Salfred 1453195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) { 1454195957Salfred err = LIBUSB_ERROR_OTHER; 1455195957Salfred } else if ((sxfer->entry.tqe_prev != NULL) || 1456199575Sthompsa (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) || 1457195957Salfred (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) { 1458195957Salfred err = LIBUSB_ERROR_BUSY; 1459195957Salfred } else { 1460199575Sthompsa 1461199575Sthompsa /* set pending state */ 1462199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_PEND; 1463199575Sthompsa 1464199575Sthompsa /* insert transfer into transfer head list */ 1465195957Salfred TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry); 1466195957Salfred 1467199575Sthompsa /* start work transfers */ 1468195957Salfred libusb10_submit_transfer_sub( 1469195957Salfred uxfer->dev_handle, endpoint); 1470195957Salfred 1471195957Salfred err = 0; /* success */ 1472195957Salfred } 1473195957Salfred 1474195957Salfred CTX_UNLOCK(dev->ctx); 1475195957Salfred 1476195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); 1477195957Salfred 1478195957Salfred return (err); 1479194676Sthompsa} 1480194676Sthompsa 1481195957Salfred/* Asynchronous transfer cancel */ 1482195957Salfred 1483194676Sthompsaint 1484195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer) 1485194676Sthompsa{ 1486195957Salfred struct libusb20_transfer *pxfer0; 1487195957Salfred struct libusb20_transfer *pxfer1; 1488195957Salfred struct libusb_super_transfer *sxfer; 1489195957Salfred struct libusb_device *dev; 1490234684Shselasky uint8_t endpoint; 1491199575Sthompsa int retval; 1492194676Sthompsa 1493195957Salfred if (uxfer == NULL) 1494195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1495194676Sthompsa 1496199575Sthompsa /* check if not initialised */ 1497195957Salfred if (uxfer->dev_handle == NULL) 1498199575Sthompsa return (LIBUSB_ERROR_NOT_FOUND); 1499194676Sthompsa 1500195957Salfred endpoint = uxfer->endpoint; 1501194676Sthompsa 1502195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1503195957Salfred 1504195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); 1505195957Salfred 1506195957Salfred sxfer = (struct libusb_super_transfer *)( 1507195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1508195957Salfred 1509199575Sthompsa retval = 0; 1510199575Sthompsa 1511195957Salfred CTX_LOCK(dev->ctx); 1512195957Salfred 1513195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1514195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1515195957Salfred 1516199575Sthompsa if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { 1517199575Sthompsa /* only update the transfer status */ 1518199575Sthompsa uxfer->status = LIBUSB_TRANSFER_CANCELLED; 1519199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1520199575Sthompsa } else if (sxfer->entry.tqe_prev != NULL) { 1521195957Salfred /* we are lucky - transfer is on a queue */ 1522195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1523195957Salfred sxfer->entry.tqe_prev = NULL; 1524199575Sthompsa libusb10_complete_transfer(NULL, 1525199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1526195957Salfred } else if (pxfer0 == NULL || pxfer1 == NULL) { 1527195957Salfred /* not started */ 1528199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1529195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { 1530199575Sthompsa libusb10_complete_transfer(pxfer0, 1531199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1532195957Salfred libusb20_tr_stop(pxfer0); 1533195957Salfred /* make sure the queue doesn't stall */ 1534195957Salfred libusb10_submit_transfer_sub( 1535195957Salfred uxfer->dev_handle, endpoint); 1536195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { 1537199575Sthompsa libusb10_complete_transfer(pxfer1, 1538199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1539195957Salfred libusb20_tr_stop(pxfer1); 1540195957Salfred /* make sure the queue doesn't stall */ 1541195957Salfred libusb10_submit_transfer_sub( 1542195957Salfred uxfer->dev_handle, endpoint); 1543195957Salfred } else { 1544195957Salfred /* not started */ 1545199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1546195957Salfred } 1547195957Salfred 1548195957Salfred CTX_UNLOCK(dev->ctx); 1549195957Salfred 1550195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); 1551195957Salfred 1552199575Sthompsa return (retval); 1553194676Sthompsa} 1554194676Sthompsa 1555195957SalfredUNEXPORTED void 1556195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev) 1557195957Salfred{ 1558301842Shselasky struct libusb20_device *pdev = dev->os_priv; 1559301842Shselasky unsigned x; 1560301842Shselasky 1561301842Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1562301842Shselasky struct libusb20_transfer *xfer; 1563301842Shselasky 1564301842Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1565301842Shselasky if (xfer == NULL) 1566301842Shselasky continue; 1567301842Shselasky libusb20_tr_close(xfer); 1568301842Shselasky } 1569195957Salfred} 1570199055Sthompsa 1571199055Sthompsauint16_t 1572199055Sthompsalibusb_cpu_to_le16(uint16_t x) 1573199055Sthompsa{ 1574199055Sthompsa return (htole16(x)); 1575199055Sthompsa} 1576199055Sthompsa 1577199055Sthompsauint16_t 1578199055Sthompsalibusb_le16_to_cpu(uint16_t x) 1579199055Sthompsa{ 1580199055Sthompsa return (le16toh(x)); 1581199055Sthompsa} 1582199055Sthompsa 1583213853Shselaskyconst char * 1584213853Shselaskylibusb_strerror(int code) 1585213853Shselasky{ 1586225659Shselasky switch (code) { 1587225659Shselasky case LIBUSB_SUCCESS: 1588225659Shselasky return ("Success"); 1589225659Shselasky case LIBUSB_ERROR_IO: 1590225659Shselasky return ("I/O error"); 1591225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1592225659Shselasky return ("Invalid parameter"); 1593225659Shselasky case LIBUSB_ERROR_ACCESS: 1594225659Shselasky return ("Permissions error"); 1595225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1596225659Shselasky return ("No device"); 1597225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1598225659Shselasky return ("Not found"); 1599225659Shselasky case LIBUSB_ERROR_BUSY: 1600225659Shselasky return ("Device busy"); 1601225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1602225659Shselasky return ("Timeout"); 1603225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1604225659Shselasky return ("Overflow"); 1605225659Shselasky case LIBUSB_ERROR_PIPE: 1606225659Shselasky return ("Pipe error"); 1607225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1608225659Shselasky return ("Interrupted"); 1609225659Shselasky case LIBUSB_ERROR_NO_MEM: 1610225659Shselasky return ("Out of memory"); 1611225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1612225659Shselasky return ("Not supported"); 1613225659Shselasky case LIBUSB_ERROR_OTHER: 1614225659Shselasky return ("Other error"); 1615225659Shselasky default: 1616225659Shselasky return ("Unknown error"); 1617225659Shselasky } 1618213853Shselasky} 1619225659Shselasky 1620225659Shselaskyconst char * 1621225659Shselaskylibusb_error_name(int code) 1622225659Shselasky{ 1623225659Shselasky switch (code) { 1624225659Shselasky case LIBUSB_SUCCESS: 1625225659Shselasky return ("LIBUSB_SUCCESS"); 1626225659Shselasky case LIBUSB_ERROR_IO: 1627225659Shselasky return ("LIBUSB_ERROR_IO"); 1628225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1629225659Shselasky return ("LIBUSB_ERROR_INVALID_PARAM"); 1630225659Shselasky case LIBUSB_ERROR_ACCESS: 1631225659Shselasky return ("LIBUSB_ERROR_ACCESS"); 1632225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1633225659Shselasky return ("LIBUSB_ERROR_NO_DEVICE"); 1634225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1635225659Shselasky return ("LIBUSB_ERROR_NOT_FOUND"); 1636225659Shselasky case LIBUSB_ERROR_BUSY: 1637225659Shselasky return ("LIBUSB_ERROR_BUSY"); 1638225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1639225659Shselasky return ("LIBUSB_ERROR_TIMEOUT"); 1640225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1641225659Shselasky return ("LIBUSB_ERROR_OVERFLOW"); 1642225659Shselasky case LIBUSB_ERROR_PIPE: 1643225659Shselasky return ("LIBUSB_ERROR_PIPE"); 1644225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1645225659Shselasky return ("LIBUSB_ERROR_INTERRUPTED"); 1646225659Shselasky case LIBUSB_ERROR_NO_MEM: 1647225659Shselasky return ("LIBUSB_ERROR_NO_MEM"); 1648225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1649225659Shselasky return ("LIBUSB_ERROR_NOT_SUPPORTED"); 1650225659Shselasky case LIBUSB_ERROR_OTHER: 1651225659Shselasky return ("LIBUSB_ERROR_OTHER"); 1652225659Shselasky default: 1653225659Shselasky return ("LIBUSB_ERROR_UNKNOWN"); 1654225659Shselasky } 1655225659Shselasky} 1656