1194676Sthompsa/* $FreeBSD: stable/11/lib/libusb/libusb10.c 362224 2020-06-16 12:21:55Z kevans $ */ 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); 92353135Skevans /* debug_fixed is set when the environment overrides libusb_set_debug */ 93353135Skevans if (ctx && ctx->debug_fixed == 0) 94194676Sthompsa ctx->debug = level; 95194676Sthompsa} 96194676Sthompsa 97213853Shselaskystatic void 98213853Shselaskylibusb_set_nonblocking(int f) 99213853Shselasky{ 100213853Shselasky int flags; 101213853Shselasky 102213853Shselasky /* 103213853Shselasky * We ignore any failures in this function, hence the 104213853Shselasky * non-blocking flag is not critical to the operation of 105213853Shselasky * libUSB. We use F_GETFL and F_SETFL to be compatible with 106213853Shselasky * Linux. 107213853Shselasky */ 108213853Shselasky 109213853Shselasky flags = fcntl(f, F_GETFL, NULL); 110213853Shselasky if (flags == -1) 111213853Shselasky return; 112213853Shselasky flags |= O_NONBLOCK; 113213853Shselasky fcntl(f, F_SETFL, flags); 114213853Shselasky} 115213853Shselasky 116338788Shselaskystatic void 117338788Shselaskylibusb10_wakeup_event_loop(libusb_context *ctx) 118338788Shselasky{ 119338788Shselasky uint8_t dummy = 0; 120338788Shselasky int err; 121338788Shselasky 122338788Shselasky err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 123338788Shselasky if (err < (int)sizeof(dummy)) { 124338788Shselasky /* ignore error, if any */ 125338788Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "Waking up event loop failed!"); 126338788Shselasky } 127338788Shselasky} 128338788Shselasky 129194676Sthompsaint 130195957Salfredlibusb_init(libusb_context **context) 131194676Sthompsa{ 132194676Sthompsa struct libusb_context *ctx; 133236944Shselasky pthread_condattr_t attr; 134353135Skevans char *debug, *ep; 135194676Sthompsa int ret; 136194676Sthompsa 137194676Sthompsa ctx = malloc(sizeof(*ctx)); 138194676Sthompsa if (!ctx) 139194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 140194676Sthompsa 141194676Sthompsa memset(ctx, 0, sizeof(*ctx)); 142194676Sthompsa 143194676Sthompsa debug = getenv("LIBUSB_DEBUG"); 144194676Sthompsa if (debug != NULL) { 145353135Skevans /* 146353135Skevans * If LIBUSB_DEBUG is set, we'll honor that and use it to 147353135Skevans * override libusb_set_debug calls. 148353135Skevans */ 149353135Skevans errno = 0; 150353135Skevans ctx->debug = strtol(debug, &ep, 10); 151353135Skevans if (errno == 0 && *ep == '\0') { 152194676Sthompsa ctx->debug_fixed = 1; 153353135Skevans } else { 154353135Skevans /* 155353135Skevans * LIBUSB_DEBUG conversion failed for some reason, but 156353135Skevans * we don't care about the specifics all that much. We 157353135Skevans * can't use it either way. Force it to the default, 158353135Skevans * 0, in case we had a partial number. 159353135Skevans */ 160353135Skevans ctx->debug = 0; 161353135Skevans } 162194676Sthompsa } 163195957Salfred TAILQ_INIT(&ctx->pollfds); 164195957Salfred TAILQ_INIT(&ctx->tr_done); 165302080Shselasky TAILQ_INIT(&ctx->hotplug_cbh); 166302080Shselasky TAILQ_INIT(&ctx->hotplug_devs); 167194676Sthompsa 168236944Shselasky if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) { 169236944Shselasky free(ctx); 170236944Shselasky return (LIBUSB_ERROR_NO_MEM); 171236944Shselasky } 172302080Shselasky if (pthread_mutex_init(&ctx->hotplug_lock, NULL) != 0) { 173302080Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 174302080Shselasky free(ctx); 175302080Shselasky return (LIBUSB_ERROR_NO_MEM); 176302080Shselasky } 177236944Shselasky if (pthread_condattr_init(&attr) != 0) { 178236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 179302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 180236944Shselasky free(ctx); 181236944Shselasky return (LIBUSB_ERROR_NO_MEM); 182236944Shselasky } 183236944Shselasky if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) { 184236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 185302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 186236944Shselasky pthread_condattr_destroy(&attr); 187236944Shselasky free(ctx); 188236944Shselasky return (LIBUSB_ERROR_OTHER); 189236944Shselasky } 190236944Shselasky if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) { 191236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 192302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 193236944Shselasky pthread_condattr_destroy(&attr); 194236944Shselasky free(ctx); 195236944Shselasky return (LIBUSB_ERROR_NO_MEM); 196236944Shselasky } 197236944Shselasky pthread_condattr_destroy(&attr); 198194676Sthompsa 199195957Salfred ctx->ctx_handler = NO_THREAD; 200302080Shselasky ctx->hotplug_handler = NO_THREAD; 201194676Sthompsa 202194676Sthompsa ret = pipe(ctx->ctrl_pipe); 203194676Sthompsa if (ret < 0) { 204195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 205302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 206195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 207194676Sthompsa free(ctx); 208194676Sthompsa return (LIBUSB_ERROR_OTHER); 209194676Sthompsa } 210195957Salfred /* set non-blocking mode on the control pipe to avoid deadlock */ 211213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[0]); 212213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[1]); 213194676Sthompsa 214195957Salfred libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); 215194676Sthompsa 216194676Sthompsa pthread_mutex_lock(&default_context_lock); 217194676Sthompsa if (usbi_default_context == NULL) { 218194676Sthompsa usbi_default_context = ctx; 219194676Sthompsa } 220194676Sthompsa pthread_mutex_unlock(&default_context_lock); 221194676Sthompsa 222194676Sthompsa if (context) 223194676Sthompsa *context = ctx; 224194676Sthompsa 225195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); 226195957Salfred 227194676Sthompsa return (0); 228194676Sthompsa} 229194676Sthompsa 230194676Sthompsavoid 231195957Salfredlibusb_exit(libusb_context *ctx) 232194676Sthompsa{ 233195957Salfred ctx = GET_CONTEXT(ctx); 234194676Sthompsa 235195957Salfred if (ctx == NULL) 236195957Salfred return; 237195957Salfred 238302080Shselasky /* stop hotplug thread, if any */ 239302080Shselasky 240302080Shselasky if (ctx->hotplug_handler != NO_THREAD) { 241302080Shselasky pthread_t td; 242302080Shselasky void *ptr; 243302080Shselasky 244302080Shselasky HOTPLUG_LOCK(ctx); 245302080Shselasky td = ctx->hotplug_handler; 246302080Shselasky ctx->hotplug_handler = NO_THREAD; 247302080Shselasky HOTPLUG_UNLOCK(ctx); 248302080Shselasky 249302080Shselasky pthread_join(td, &ptr); 250302080Shselasky } 251302080Shselasky 252195957Salfred /* XXX cleanup devices */ 253195957Salfred 254195957Salfred libusb10_remove_pollfd(ctx, &ctx->ctx_poll); 255194676Sthompsa close(ctx->ctrl_pipe[0]); 256194676Sthompsa close(ctx->ctrl_pipe[1]); 257195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 258302080Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 259195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 260194676Sthompsa 261194676Sthompsa pthread_mutex_lock(&default_context_lock); 262194676Sthompsa if (ctx == usbi_default_context) { 263194676Sthompsa usbi_default_context = NULL; 264194676Sthompsa } 265194676Sthompsa pthread_mutex_unlock(&default_context_lock); 266194676Sthompsa 267194676Sthompsa free(ctx); 268194676Sthompsa} 269194676Sthompsa 270194676Sthompsa/* Device handling and initialisation. */ 271194676Sthompsa 272194676Sthompsassize_t 273195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list) 274194676Sthompsa{ 275195957Salfred struct libusb20_backend *usb_backend; 276194676Sthompsa struct libusb20_device *pdev; 277194676Sthompsa struct libusb_device *dev; 278194676Sthompsa int i; 279194676Sthompsa 280195957Salfred ctx = GET_CONTEXT(ctx); 281194676Sthompsa 282195957Salfred if (ctx == NULL) 283195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 284195957Salfred 285195957Salfred if (list == NULL) 286195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 287195957Salfred 288194676Sthompsa usb_backend = libusb20_be_alloc_default(); 289194676Sthompsa if (usb_backend == NULL) 290195957Salfred return (LIBUSB_ERROR_NO_MEM); 291194676Sthompsa 292195957Salfred /* figure out how many USB devices are present */ 293194676Sthompsa pdev = NULL; 294194676Sthompsa i = 0; 295194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) 296194676Sthompsa i++; 297194676Sthompsa 298195957Salfred /* allocate device pointer list */ 299194676Sthompsa *list = malloc((i + 1) * sizeof(void *)); 300194676Sthompsa if (*list == NULL) { 301194676Sthompsa libusb20_be_free(usb_backend); 302194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 303194676Sthompsa } 304195957Salfred /* create libusb v1.0 compliant devices */ 305194676Sthompsa i = 0; 306194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 307194676Sthompsa 308194676Sthompsa dev = malloc(sizeof(*dev)); 309194676Sthompsa if (dev == NULL) { 310195560Sthompsa while (i != 0) { 311195560Sthompsa libusb_unref_device((*list)[i - 1]); 312195560Sthompsa i--; 313195560Sthompsa } 314194676Sthompsa free(*list); 315195957Salfred *list = NULL; 316194676Sthompsa libusb20_be_free(usb_backend); 317194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 318194676Sthompsa } 319199055Sthompsa /* get device into libUSB v1.0 list */ 320199055Sthompsa libusb20_be_dequeue_device(usb_backend, pdev); 321199055Sthompsa 322194676Sthompsa memset(dev, 0, sizeof(*dev)); 323194676Sthompsa 324195957Salfred /* init transfer queues */ 325195957Salfred TAILQ_INIT(&dev->tr_head); 326195957Salfred 327195957Salfred /* set context we belong to */ 328194676Sthompsa dev->ctx = ctx; 329194676Sthompsa 330194676Sthompsa /* link together the two structures */ 331194676Sthompsa dev->os_priv = pdev; 332195957Salfred pdev->privLuData = dev; 333194676Sthompsa 334194676Sthompsa (*list)[i] = libusb_ref_device(dev); 335194676Sthompsa i++; 336194676Sthompsa } 337194676Sthompsa (*list)[i] = NULL; 338194676Sthompsa 339194676Sthompsa libusb20_be_free(usb_backend); 340194676Sthompsa return (i); 341194676Sthompsa} 342194676Sthompsa 343194676Sthompsavoid 344194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices) 345194676Sthompsa{ 346194676Sthompsa int i; 347194676Sthompsa 348194676Sthompsa if (list == NULL) 349195957Salfred return; /* be NULL safe */ 350194676Sthompsa 351194676Sthompsa if (unref_devices) { 352194676Sthompsa for (i = 0; list[i] != NULL; i++) 353194676Sthompsa libusb_unref_device(list[i]); 354194676Sthompsa } 355194676Sthompsa free(list); 356194676Sthompsa} 357194676Sthompsa 358194676Sthompsauint8_t 359195957Salfredlibusb_get_bus_number(libusb_device *dev) 360194676Sthompsa{ 361194676Sthompsa if (dev == NULL) 362195957Salfred return (0); /* should not happen */ 363195957Salfred return (libusb20_dev_get_bus_number(dev->os_priv)); 364194676Sthompsa} 365194676Sthompsa 366301964Shselaskyuint8_t 367301964Shselaskylibusb_get_port_number(libusb_device *dev) 368301964Shselasky{ 369301964Shselasky if (dev == NULL) 370301964Shselasky return (0); /* should not happen */ 371301964Shselasky return (libusb20_dev_get_parent_port(dev->os_priv)); 372301964Shselasky} 373301964Shselasky 374250342Semasteint 375251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) 376251495Semaste{ 377251495Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 378251495Semaste} 379251495Semaste 380251495Semasteint 381250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, 382250342Semaste uint8_t bufsize) 383250342Semaste{ 384250342Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 385250342Semaste} 386250342Semaste 387194676Sthompsauint8_t 388195957Salfredlibusb_get_device_address(libusb_device *dev) 389194676Sthompsa{ 390194676Sthompsa if (dev == NULL) 391195957Salfred return (0); /* should not happen */ 392195957Salfred return (libusb20_dev_get_address(dev->os_priv)); 393194676Sthompsa} 394194676Sthompsa 395224903Shselaskyenum libusb_speed 396224903Shselaskylibusb_get_device_speed(libusb_device *dev) 397224903Shselasky{ 398224903Shselasky if (dev == NULL) 399225035Shselasky return (LIBUSB_SPEED_UNKNOWN); /* should not happen */ 400224903Shselasky 401224903Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 402224903Shselasky case LIBUSB20_SPEED_LOW: 403224903Shselasky return (LIBUSB_SPEED_LOW); 404224903Shselasky case LIBUSB20_SPEED_FULL: 405224903Shselasky return (LIBUSB_SPEED_FULL); 406224903Shselasky case LIBUSB20_SPEED_HIGH: 407224903Shselasky return (LIBUSB_SPEED_HIGH); 408224903Shselasky case LIBUSB20_SPEED_SUPER: 409224903Shselasky return (LIBUSB_SPEED_SUPER); 410224903Shselasky default: 411224903Shselasky break; 412224903Shselasky } 413224903Shselasky return (LIBUSB_SPEED_UNKNOWN); 414224903Shselasky} 415224903Shselasky 416194676Sthompsaint 417195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint) 418194676Sthompsa{ 419194676Sthompsa struct libusb_config_descriptor *pdconf; 420194676Sthompsa struct libusb_interface *pinf; 421194676Sthompsa struct libusb_interface_descriptor *pdinf; 422194676Sthompsa struct libusb_endpoint_descriptor *pdend; 423195957Salfred int i; 424195957Salfred int j; 425195957Salfred int k; 426195957Salfred int ret; 427194676Sthompsa 428194676Sthompsa if (dev == NULL) 429194676Sthompsa return (LIBUSB_ERROR_NO_DEVICE); 430194676Sthompsa 431195957Salfred ret = libusb_get_active_config_descriptor(dev, &pdconf); 432195957Salfred if (ret < 0) 433195957Salfred return (ret); 434195957Salfred 435194676Sthompsa ret = LIBUSB_ERROR_NOT_FOUND; 436195957Salfred for (i = 0; i < pdconf->bNumInterfaces; i++) { 437194676Sthompsa pinf = &pdconf->interface[i]; 438195957Salfred for (j = 0; j < pinf->num_altsetting; j++) { 439194676Sthompsa pdinf = &pinf->altsetting[j]; 440195957Salfred for (k = 0; k < pdinf->bNumEndpoints; k++) { 441194676Sthompsa pdend = &pdinf->endpoint[k]; 442194676Sthompsa if (pdend->bEndpointAddress == endpoint) { 443194676Sthompsa ret = pdend->wMaxPacketSize; 444194676Sthompsa goto out; 445194676Sthompsa } 446194676Sthompsa } 447194676Sthompsa } 448194676Sthompsa } 449194676Sthompsa 450194676Sthompsaout: 451194676Sthompsa libusb_free_config_descriptor(pdconf); 452194676Sthompsa return (ret); 453194676Sthompsa} 454194676Sthompsa 455234193Shselaskyint 456234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint) 457234193Shselasky{ 458234193Shselasky int multiplier; 459234193Shselasky int ret; 460234193Shselasky 461234193Shselasky ret = libusb_get_max_packet_size(dev, endpoint); 462234193Shselasky 463234193Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 464234193Shselasky case LIBUSB20_SPEED_LOW: 465234193Shselasky case LIBUSB20_SPEED_FULL: 466234193Shselasky break; 467234193Shselasky default: 468234193Shselasky if (ret > -1) { 469234193Shselasky multiplier = (1 + ((ret >> 11) & 3)); 470234193Shselasky if (multiplier > 3) 471234193Shselasky multiplier = 3; 472234193Shselasky ret = (ret & 0x7FF) * multiplier; 473234193Shselasky } 474234193Shselasky break; 475234193Shselasky } 476234193Shselasky return (ret); 477234193Shselasky} 478234193Shselasky 479194676Sthompsalibusb_device * 480195957Salfredlibusb_ref_device(libusb_device *dev) 481194676Sthompsa{ 482194676Sthompsa if (dev == NULL) 483195957Salfred return (NULL); /* be NULL safe */ 484194676Sthompsa 485195957Salfred CTX_LOCK(dev->ctx); 486194676Sthompsa dev->refcnt++; 487195957Salfred CTX_UNLOCK(dev->ctx); 488194676Sthompsa 489194676Sthompsa return (dev); 490194676Sthompsa} 491194676Sthompsa 492194676Sthompsavoid 493195957Salfredlibusb_unref_device(libusb_device *dev) 494194676Sthompsa{ 495194676Sthompsa if (dev == NULL) 496195957Salfred return; /* be NULL safe */ 497194676Sthompsa 498195957Salfred CTX_LOCK(dev->ctx); 499194676Sthompsa dev->refcnt--; 500195957Salfred CTX_UNLOCK(dev->ctx); 501194676Sthompsa 502194676Sthompsa if (dev->refcnt == 0) { 503194676Sthompsa libusb20_dev_free(dev->os_priv); 504194676Sthompsa free(dev); 505194676Sthompsa } 506194676Sthompsa} 507194676Sthompsa 508194676Sthompsaint 509195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh) 510194676Sthompsa{ 511194676Sthompsa libusb_context *ctx = dev->ctx; 512194676Sthompsa struct libusb20_device *pdev = dev->os_priv; 513194676Sthompsa int err; 514194676Sthompsa 515194676Sthompsa if (devh == NULL) 516194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 517194676Sthompsa 518195957Salfred /* set default device handle value */ 519195957Salfred *devh = NULL; 520194676Sthompsa 521195957Salfred dev = libusb_ref_device(dev); 522195957Salfred if (dev == NULL) 523195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 524195957Salfred 525301842Shselasky err = libusb20_dev_open(pdev, LIBUSB_NUM_SW_ENDPOINTS); 526194676Sthompsa if (err) { 527195957Salfred libusb_unref_device(dev); 528194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 529194676Sthompsa } 530195957Salfred libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 531194676Sthompsa POLLOUT | POLLRDNORM | POLLWRNORM); 532194676Sthompsa 533195957Salfred /* make sure our event loop detects the new device */ 534338788Shselasky libusb10_wakeup_event_loop(ctx); 535338788Shselasky 536195957Salfred *devh = pdev; 537194676Sthompsa 538194676Sthompsa return (0); 539194676Sthompsa} 540194676Sthompsa 541194676Sthompsalibusb_device_handle * 542195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, 543194676Sthompsa uint16_t product_id) 544194676Sthompsa{ 545194676Sthompsa struct libusb_device **devs; 546194676Sthompsa struct libusb20_device *pdev; 547194676Sthompsa struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 548195957Salfred int i; 549195957Salfred int j; 550194676Sthompsa 551195957Salfred ctx = GET_CONTEXT(ctx); 552195957Salfred if (ctx == NULL) 553195957Salfred return (NULL); /* be NULL safe */ 554195957Salfred 555345540Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid enter"); 556194676Sthompsa 557194676Sthompsa if ((i = libusb_get_device_list(ctx, &devs)) < 0) 558194676Sthompsa return (NULL); 559194676Sthompsa 560228236Shselasky pdev = NULL; 561194676Sthompsa for (j = 0; j < i; j++) { 562228236Shselasky struct libusb20_device *tdev; 563228236Shselasky 564228236Shselasky tdev = devs[j]->os_priv; 565228236Shselasky pdesc = libusb20_dev_get_device_desc(tdev); 566195957Salfred /* 567195957Salfred * NOTE: The USB library will automatically swap the 568195957Salfred * fields in the device descriptor to be of host 569195957Salfred * endian type! 570195957Salfred */ 571194676Sthompsa if (pdesc->idVendor == vendor_id && 572195560Sthompsa pdesc->idProduct == product_id) { 573228235Shselasky libusb_open(devs[j], &pdev); 574195957Salfred break; 575195560Sthompsa } 576194676Sthompsa } 577194676Sthompsa 578194676Sthompsa libusb_free_device_list(devs, 1); 579345540Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid leave"); 580195957Salfred return (pdev); 581194676Sthompsa} 582194676Sthompsa 583194676Sthompsavoid 584195957Salfredlibusb_close(struct libusb20_device *pdev) 585194676Sthompsa{ 586194676Sthompsa libusb_context *ctx; 587195957Salfred struct libusb_device *dev; 588194676Sthompsa 589195957Salfred if (pdev == NULL) 590195957Salfred return; /* be NULL safe */ 591194676Sthompsa 592195957Salfred dev = libusb_get_device(pdev); 593195957Salfred ctx = dev->ctx; 594194676Sthompsa 595195957Salfred libusb10_remove_pollfd(ctx, &dev->dev_poll); 596194676Sthompsa 597195957Salfred libusb20_dev_close(pdev); 598199055Sthompsa 599199055Sthompsa /* unref will free the "pdev" when the refcount reaches zero */ 600195957Salfred libusb_unref_device(dev); 601194676Sthompsa 602195957Salfred /* make sure our event loop detects the closed device */ 603338788Shselasky libusb10_wakeup_event_loop(ctx); 604194676Sthompsa} 605194676Sthompsa 606194676Sthompsalibusb_device * 607195957Salfredlibusb_get_device(struct libusb20_device *pdev) 608194676Sthompsa{ 609195957Salfred if (pdev == NULL) 610194676Sthompsa return (NULL); 611195957Salfred return ((libusb_device *)pdev->privLuData); 612194676Sthompsa} 613194676Sthompsa 614194676Sthompsaint 615195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config) 616194676Sthompsa{ 617195957Salfred struct libusb20_config *pconf; 618194676Sthompsa 619195957Salfred if (pdev == NULL || config == NULL) 620194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 621194676Sthompsa 622195957Salfred pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); 623195957Salfred if (pconf == NULL) 624195957Salfred return (LIBUSB_ERROR_NO_MEM); 625194676Sthompsa 626195957Salfred *config = pconf->desc.bConfigurationValue; 627195957Salfred 628195957Salfred free(pconf); 629195957Salfred 630194676Sthompsa return (0); 631194676Sthompsa} 632194676Sthompsa 633194676Sthompsaint 634195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration) 635194676Sthompsa{ 636195957Salfred struct libusb20_config *pconf; 637195957Salfred struct libusb_device *dev; 638195957Salfred int err; 639195957Salfred uint8_t i; 640194676Sthompsa 641195957Salfred dev = libusb_get_device(pdev); 642195957Salfred if (dev == NULL) 643194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 644194676Sthompsa 645195957Salfred if (configuration < 1) { 646195957Salfred /* unconfigure */ 647195957Salfred i = 255; 648195957Salfred } else { 649195957Salfred for (i = 0; i != 255; i++) { 650195957Salfred uint8_t found; 651194676Sthompsa 652195957Salfred pconf = libusb20_dev_alloc_config(pdev, i); 653195957Salfred if (pconf == NULL) 654195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 655195957Salfred found = (pconf->desc.bConfigurationValue 656195957Salfred == configuration); 657195957Salfred free(pconf); 658195957Salfred 659195957Salfred if (found) 660195957Salfred goto set_config; 661195957Salfred } 662195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 663195957Salfred } 664195957Salfred 665195957Salfredset_config: 666195957Salfred 667195957Salfred libusb10_cancel_all_transfer(dev); 668195957Salfred 669195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 670195957Salfred 671195957Salfred err = libusb20_dev_set_config_index(pdev, i); 672195957Salfred 673195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 674195957Salfred POLLOUT | POLLRDNORM | POLLWRNORM); 675195957Salfred 676195957Salfred return (err ? LIBUSB_ERROR_INVALID_PARAM : 0); 677194676Sthompsa} 678194676Sthompsa 679194676Sthompsaint 680195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number) 681194676Sthompsa{ 682195957Salfred libusb_device *dev; 683301966Shselasky int err = 0; 684194676Sthompsa 685195957Salfred dev = libusb_get_device(pdev); 686194676Sthompsa if (dev == NULL) 687194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 688194676Sthompsa 689195957Salfred if (interface_number < 0 || interface_number > 31) 690194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 691194676Sthompsa 692301966Shselasky if (pdev->auto_detach != 0) { 693301966Shselasky err = libusb_detach_kernel_driver(pdev, interface_number); 694301966Shselasky if (err != 0) 695301966Shselasky goto done; 696301966Shselasky } 697301966Shselasky 698195957Salfred CTX_LOCK(dev->ctx); 699261224Shselasky dev->claimed_interfaces |= (1 << interface_number); 700261224Shselasky CTX_UNLOCK(dev->ctx); 701301966Shselaskydone: 702301966Shselasky return (err); 703194676Sthompsa} 704194676Sthompsa 705194676Sthompsaint 706195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number) 707194676Sthompsa{ 708195957Salfred libusb_device *dev; 709195957Salfred int err = 0; 710194676Sthompsa 711195957Salfred dev = libusb_get_device(pdev); 712194676Sthompsa if (dev == NULL) 713194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 714194676Sthompsa 715195957Salfred if (interface_number < 0 || interface_number > 31) 716194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 717194676Sthompsa 718301966Shselasky if (pdev->auto_detach != 0) { 719301966Shselasky err = libusb_attach_kernel_driver(pdev, interface_number); 720301966Shselasky if (err != 0) 721301966Shselasky goto done; 722301966Shselasky } 723301966Shselasky 724195957Salfred CTX_LOCK(dev->ctx); 725194676Sthompsa if (!(dev->claimed_interfaces & (1 << interface_number))) 726195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 727301966Shselasky else 728194676Sthompsa dev->claimed_interfaces &= ~(1 << interface_number); 729195957Salfred CTX_UNLOCK(dev->ctx); 730301966Shselaskydone: 731195957Salfred return (err); 732194676Sthompsa} 733194676Sthompsa 734194676Sthompsaint 735195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev, 736194676Sthompsa int interface_number, int alternate_setting) 737194676Sthompsa{ 738195957Salfred libusb_device *dev; 739195957Salfred int err = 0; 740194676Sthompsa 741195957Salfred dev = libusb_get_device(pdev); 742194676Sthompsa if (dev == NULL) 743194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 744194676Sthompsa 745195957Salfred if (interface_number < 0 || interface_number > 31) 746194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 747194676Sthompsa 748195957Salfred CTX_LOCK(dev->ctx); 749195957Salfred if (!(dev->claimed_interfaces & (1 << interface_number))) 750195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 751195957Salfred CTX_UNLOCK(dev->ctx); 752194676Sthompsa 753195957Salfred if (err) 754195957Salfred return (err); 755195957Salfred 756195957Salfred libusb10_cancel_all_transfer(dev); 757195957Salfred 758195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 759195957Salfred 760195957Salfred err = libusb20_dev_set_alt_index(pdev, 761195957Salfred interface_number, alternate_setting); 762195957Salfred 763195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 764195957Salfred pdev, libusb20_dev_get_fd(pdev), 765195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 766195957Salfred 767195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 768194676Sthompsa} 769194676Sthompsa 770195957Salfredstatic struct libusb20_transfer * 771195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev, 772234491Shselasky uint8_t endpoint, uint8_t xfer_index) 773195957Salfred{ 774234491Shselasky xfer_index &= 1; /* double buffering */ 775195957Salfred 776234491Shselasky xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4; 777195957Salfred 778195957Salfred if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) { 779195957Salfred /* this is an IN endpoint */ 780234491Shselasky xfer_index |= 2; 781195957Salfred } 782234491Shselasky return (libusb20_tr_get_pointer(pdev, xfer_index)); 783195957Salfred} 784195957Salfred 785194676Sthompsaint 786195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint) 787194676Sthompsa{ 788194676Sthompsa struct libusb20_transfer *xfer; 789195957Salfred struct libusb_device *dev; 790195957Salfred int err; 791194676Sthompsa 792195957Salfred xfer = libusb10_get_transfer(pdev, endpoint, 0); 793195560Sthompsa if (xfer == NULL) 794195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 795194676Sthompsa 796195957Salfred dev = libusb_get_device(pdev); 797213853Shselasky if (dev == NULL) 798213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 799195957Salfred 800195957Salfred CTX_LOCK(dev->ctx); 801223642Shselasky err = libusb20_tr_open(xfer, 0, 1, endpoint); 802195957Salfred CTX_UNLOCK(dev->ctx); 803195957Salfred 804195957Salfred if (err != 0 && err != LIBUSB20_ERROR_BUSY) 805194676Sthompsa return (LIBUSB_ERROR_OTHER); 806194676Sthompsa 807194676Sthompsa libusb20_tr_clear_stall_sync(xfer); 808195957Salfred 809195957Salfred /* check if we opened the transfer */ 810195957Salfred if (err == 0) { 811195957Salfred CTX_LOCK(dev->ctx); 812194676Sthompsa libusb20_tr_close(xfer); 813195957Salfred CTX_UNLOCK(dev->ctx); 814195957Salfred } 815195957Salfred return (0); /* success */ 816194676Sthompsa} 817194676Sthompsa 818194676Sthompsaint 819195957Salfredlibusb_reset_device(struct libusb20_device *pdev) 820194676Sthompsa{ 821195957Salfred libusb_device *dev; 822195957Salfred int err; 823194676Sthompsa 824195957Salfred dev = libusb_get_device(pdev); 825194676Sthompsa if (dev == NULL) 826213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 827194676Sthompsa 828195957Salfred libusb10_cancel_all_transfer(dev); 829195957Salfred 830195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 831195957Salfred 832195957Salfred err = libusb20_dev_reset(pdev); 833195957Salfred 834195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 835195957Salfred pdev, libusb20_dev_get_fd(pdev), 836195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 837195957Salfred 838195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 839194676Sthompsa} 840194676Sthompsa 841194676Sthompsaint 842213848Shselaskylibusb_check_connected(struct libusb20_device *pdev) 843213848Shselasky{ 844213848Shselasky libusb_device *dev; 845213848Shselasky int err; 846213848Shselasky 847213848Shselasky dev = libusb_get_device(pdev); 848213848Shselasky if (dev == NULL) 849213848Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 850213848Shselasky 851213848Shselasky err = libusb20_dev_check_connected(pdev); 852213848Shselasky 853213848Shselasky return (err ? LIBUSB_ERROR_NO_DEVICE : 0); 854213848Shselasky} 855213848Shselasky 856213848Shselaskyint 857195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface) 858194676Sthompsa{ 859195957Salfred if (pdev == NULL) 860194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 861194676Sthompsa 862226220Shselasky if (libusb20_dev_kernel_driver_active(pdev, interface)) 863226220Shselasky return (0); /* no kernel driver is active */ 864226220Shselasky else 865226220Shselasky return (1); /* kernel driver is active */ 866194676Sthompsa} 867194676Sthompsa 868194676Sthompsaint 869213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface, 870213853Shselasky char *name, int namelen) 871213853Shselasky{ 872213853Shselasky return (libusb_get_driver(pdev, interface, name, namelen)); 873213853Shselasky} 874213853Shselasky 875213853Shselaskyint 876213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface, 877213853Shselasky char *name, int namelen) 878213853Shselasky{ 879213853Shselasky char *ptr; 880213853Shselasky int err; 881213853Shselasky 882213853Shselasky if (pdev == NULL) 883213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 884213853Shselasky if (namelen < 1) 885213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 886224085Shselasky if (namelen > 255) 887224085Shselasky namelen = 255; 888213853Shselasky 889213853Shselasky err = libusb20_dev_get_iface_desc( 890213853Shselasky pdev, interface, name, namelen); 891213853Shselasky 892213853Shselasky if (err != 0) 893213853Shselasky return (LIBUSB_ERROR_OTHER); 894213853Shselasky 895213853Shselasky /* we only want the driver name */ 896213853Shselasky ptr = strstr(name, ":"); 897213853Shselasky if (ptr != NULL) 898213853Shselasky *ptr = 0; 899213853Shselasky 900213853Shselasky return (0); 901213853Shselasky} 902213853Shselasky 903213853Shselaskyint 904213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface) 905213853Shselasky{ 906213853Shselasky return (libusb_detach_kernel_driver(pdev, interface)); 907213853Shselasky} 908213853Shselasky 909213853Shselaskyint 910195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface) 911194676Sthompsa{ 912195957Salfred int err; 913194676Sthompsa 914195957Salfred if (pdev == NULL) 915194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 916194676Sthompsa 917195957Salfred err = libusb20_dev_detach_kernel_driver( 918195957Salfred pdev, interface); 919194676Sthompsa 920213853Shselasky return (err ? LIBUSB_ERROR_OTHER : 0); 921194676Sthompsa} 922194676Sthompsa 923194676Sthompsaint 924195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface) 925194676Sthompsa{ 926195957Salfred if (pdev == NULL) 927194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 928195957Salfred /* stub - currently not supported by libusb20 */ 929194676Sthompsa return (0); 930194676Sthompsa} 931194676Sthompsa 932301966Shselaskyint 933301966Shselaskylibusb_set_auto_detach_kernel_driver(libusb_device_handle *dev, int enable) 934301966Shselasky{ 935301966Shselasky dev->auto_detach = (enable ? 1 : 0); 936301969Shselasky return (0); 937301966Shselasky} 938301966Shselasky 939194676Sthompsa/* Asynchronous device I/O */ 940194676Sthompsa 941194676Sthompsastruct libusb_transfer * 942194676Sthompsalibusb_alloc_transfer(int iso_packets) 943194676Sthompsa{ 944195957Salfred struct libusb_transfer *uxfer; 945195957Salfred struct libusb_super_transfer *sxfer; 946194676Sthompsa int len; 947194676Sthompsa 948194676Sthompsa len = sizeof(struct libusb_transfer) + 949195957Salfred sizeof(struct libusb_super_transfer) + 950194676Sthompsa (iso_packets * sizeof(libusb_iso_packet_descriptor)); 951194676Sthompsa 952195957Salfred sxfer = malloc(len); 953195957Salfred if (sxfer == NULL) 954194676Sthompsa return (NULL); 955194676Sthompsa 956195957Salfred memset(sxfer, 0, len); 957194676Sthompsa 958195957Salfred uxfer = (struct libusb_transfer *)( 959195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 960194676Sthompsa 961195957Salfred /* set default value */ 962195957Salfred uxfer->num_iso_packets = iso_packets; 963195957Salfred 964195957Salfred return (uxfer); 965194676Sthompsa} 966194676Sthompsa 967194676Sthompsavoid 968195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer) 969194676Sthompsa{ 970195957Salfred struct libusb_super_transfer *sxfer; 971194676Sthompsa 972195957Salfred if (uxfer == NULL) 973195957Salfred return; /* be NULL safe */ 974194676Sthompsa 975215253Shselasky /* check if we should free the transfer buffer */ 976215253Shselasky if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 977215253Shselasky free(uxfer->buffer); 978215253Shselasky 979195957Salfred sxfer = (struct libusb_super_transfer *)( 980195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 981194676Sthompsa 982195957Salfred free(sxfer); 983194676Sthompsa} 984194676Sthompsa 985219100Shselaskystatic uint32_t 986195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 987195560Sthompsa{ 988219100Shselasky uint32_t ret; 989195560Sthompsa 990195560Sthompsa switch (xfer->type) { 991195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 992219100Shselasky ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE; /* 60ms */ 993195957Salfred break; 994195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 995195560Sthompsa ret = 2; 996195957Salfred break; 997195560Sthompsa default: 998195560Sthompsa ret = 1; 999195957Salfred break; 1000195560Sthompsa } 1001195957Salfred return (ret); 1002195560Sthompsa} 1003195560Sthompsa 1004195560Sthompsastatic int 1005195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 1006195560Sthompsa{ 1007195560Sthompsa int ret; 1008195560Sthompsa int usb_speed; 1009195560Sthompsa 1010195560Sthompsa usb_speed = libusb20_dev_get_speed(pdev); 1011195560Sthompsa 1012195560Sthompsa switch (xfer->type) { 1013195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1014195957Salfred ret = 0; /* kernel will auto-select */ 1015195957Salfred break; 1016195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 1017195957Salfred ret = 1024; 1018195957Salfred break; 1019195957Salfred default: 1020195560Sthompsa switch (usb_speed) { 1021195957Salfred case LIBUSB20_SPEED_LOW: 1022195957Salfred ret = 256; 1023195957Salfred break; 1024195957Salfred case LIBUSB20_SPEED_FULL: 1025195957Salfred ret = 4096; 1026195957Salfred break; 1027264344Shselasky case LIBUSB20_SPEED_SUPER: 1028264344Shselasky ret = 65536; 1029264344Shselasky break; 1030195957Salfred default: 1031195957Salfred ret = 16384; 1032195957Salfred break; 1033195560Sthompsa } 1034195957Salfred break; 1035195560Sthompsa } 1036195957Salfred return (ret); 1037195560Sthompsa} 1038195560Sthompsa 1039195957Salfredstatic int 1040195957Salfredlibusb10_convert_error(uint8_t status) 1041195957Salfred{ 1042195957Salfred ; /* indent fix */ 1043195957Salfred 1044195957Salfred switch (status) { 1045195957Salfred case LIBUSB20_TRANSFER_START: 1046195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1047195957Salfred return (LIBUSB_TRANSFER_COMPLETED); 1048195957Salfred case LIBUSB20_TRANSFER_OVERFLOW: 1049195957Salfred return (LIBUSB_TRANSFER_OVERFLOW); 1050195957Salfred case LIBUSB20_TRANSFER_NO_DEVICE: 1051195957Salfred return (LIBUSB_TRANSFER_NO_DEVICE); 1052195957Salfred case LIBUSB20_TRANSFER_STALL: 1053195957Salfred return (LIBUSB_TRANSFER_STALL); 1054195957Salfred case LIBUSB20_TRANSFER_CANCELLED: 1055195957Salfred return (LIBUSB_TRANSFER_CANCELLED); 1056195957Salfred case LIBUSB20_TRANSFER_TIMED_OUT: 1057195957Salfred return (LIBUSB_TRANSFER_TIMED_OUT); 1058195957Salfred default: 1059195957Salfred return (LIBUSB_TRANSFER_ERROR); 1060195957Salfred } 1061195957Salfred} 1062195957Salfred 1063195957Salfred/* This function must be called locked */ 1064195957Salfred 1065194676Sthompsastatic void 1066195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer, 1067195957Salfred struct libusb_super_transfer *sxfer, int status) 1068194676Sthompsa{ 1069195957Salfred struct libusb_transfer *uxfer; 1070195957Salfred struct libusb_device *dev; 1071195957Salfred 1072195957Salfred uxfer = (struct libusb_transfer *)( 1073195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1074195957Salfred 1075195957Salfred if (pxfer != NULL) 1076195957Salfred libusb20_tr_set_priv_sc1(pxfer, NULL); 1077195957Salfred 1078199575Sthompsa /* set transfer status */ 1079195957Salfred uxfer->status = status; 1080195957Salfred 1081199575Sthompsa /* update super transfer state */ 1082199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_NONE; 1083199575Sthompsa 1084195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1085195957Salfred 1086195957Salfred TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); 1087195957Salfred} 1088195957Salfred 1089195957Salfred/* This function must be called locked */ 1090195957Salfred 1091195957Salfredstatic void 1092195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer) 1093195957Salfred{ 1094195957Salfred struct libusb_super_transfer *sxfer; 1095195957Salfred struct libusb_transfer *uxfer; 1096195957Salfred uint32_t actlen; 1097195957Salfred uint16_t iso_packets; 1098195957Salfred uint16_t i; 1099194676Sthompsa uint8_t status; 1100194676Sthompsa 1101195957Salfred status = libusb20_tr_get_status(pxfer); 1102195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1103195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1104195957Salfred iso_packets = libusb20_tr_get_max_frames(pxfer); 1105194676Sthompsa 1106195957Salfred if (sxfer == NULL) 1107284744Saraujo return; /* cancelled - nothing to do */ 1108195957Salfred 1109195957Salfred uxfer = (struct libusb_transfer *)( 1110195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1111195957Salfred 1112195957Salfred if (iso_packets > uxfer->num_iso_packets) 1113195957Salfred iso_packets = uxfer->num_iso_packets; 1114195957Salfred 1115195957Salfred if (iso_packets == 0) 1116284744Saraujo return; /* nothing to do */ 1117195957Salfred 1118195957Salfred /* make sure that the number of ISOCHRONOUS packets is valid */ 1119195957Salfred uxfer->num_iso_packets = iso_packets; 1120195957Salfred 1121194676Sthompsa switch (status) { 1122194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1123195957Salfred /* update actual length */ 1124195957Salfred uxfer->actual_length = actlen; 1125195957Salfred for (i = 0; i != iso_packets; i++) { 1126195957Salfred uxfer->iso_packet_desc[i].actual_length = 1127195957Salfred libusb20_tr_get_length(pxfer, i); 1128195957Salfred } 1129195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1130195957Salfred break; 1131194676Sthompsa case LIBUSB20_TRANSFER_START: 1132195957Salfred /* setup length(s) */ 1133195957Salfred actlen = 0; 1134195957Salfred for (i = 0; i != iso_packets; i++) { 1135195957Salfred libusb20_tr_setup_isoc(pxfer, 1136195957Salfred &uxfer->buffer[actlen], 1137195957Salfred uxfer->iso_packet_desc[i].length, i); 1138195957Salfred actlen += uxfer->iso_packet_desc[i].length; 1139194676Sthompsa } 1140195957Salfred 1141195957Salfred /* no remainder */ 1142195957Salfred sxfer->rem_len = 0; 1143195957Salfred 1144195957Salfred libusb20_tr_set_total_frames(pxfer, iso_packets); 1145195957Salfred libusb20_tr_submit(pxfer); 1146195957Salfred 1147195957Salfred /* fork another USB transfer, if any */ 1148195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1149195957Salfred break; 1150194676Sthompsa default: 1151195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1152195957Salfred break; 1153194676Sthompsa } 1154195957Salfred} 1155194676Sthompsa 1156195957Salfred/* This function must be called locked */ 1157195957Salfred 1158195957Salfredstatic void 1159195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) 1160195957Salfred{ 1161195957Salfred struct libusb_super_transfer *sxfer; 1162195957Salfred struct libusb_transfer *uxfer; 1163195957Salfred uint32_t max_bulk; 1164195957Salfred uint32_t actlen; 1165195957Salfred uint8_t status; 1166195957Salfred uint8_t flags; 1167195957Salfred 1168195957Salfred status = libusb20_tr_get_status(pxfer); 1169195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1170195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1171195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1172195957Salfred 1173195957Salfred if (sxfer == NULL) 1174195957Salfred return; /* cancelled - nothing to do */ 1175195957Salfred 1176195957Salfred uxfer = (struct libusb_transfer *)( 1177195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1178195957Salfred 1179195957Salfred flags = uxfer->flags; 1180195957Salfred 1181194676Sthompsa switch (status) { 1182194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1183195957Salfred 1184195957Salfred uxfer->actual_length += actlen; 1185195957Salfred 1186195957Salfred /* check for short packet */ 1187195957Salfred if (sxfer->last_len != actlen) { 1188195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1189195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1190195957Salfred } else { 1191195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1192195957Salfred } 1193195957Salfred break; 1194195957Salfred } 1195195957Salfred /* check for end of data */ 1196195957Salfred if (sxfer->rem_len == 0) { 1197195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1198195957Salfred break; 1199195957Salfred } 1200195957Salfred /* FALLTHROUGH */ 1201195957Salfred 1202195957Salfred case LIBUSB20_TRANSFER_START: 1203195957Salfred if (max_bulk > sxfer->rem_len) { 1204195957Salfred max_bulk = sxfer->rem_len; 1205195957Salfred } 1206195957Salfred /* setup new BULK or INTERRUPT transaction */ 1207195957Salfred libusb20_tr_setup_bulk(pxfer, 1208195957Salfred sxfer->curr_data, max_bulk, uxfer->timeout); 1209195957Salfred 1210195957Salfred /* update counters */ 1211195957Salfred sxfer->last_len = max_bulk; 1212195957Salfred sxfer->curr_data += max_bulk; 1213195957Salfred sxfer->rem_len -= max_bulk; 1214195957Salfred 1215195957Salfred libusb20_tr_submit(pxfer); 1216195957Salfred 1217195957Salfred /* check if we can fork another USB transfer */ 1218195957Salfred if (sxfer->rem_len == 0) 1219195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1220195957Salfred break; 1221195957Salfred 1222195957Salfred default: 1223195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1224195957Salfred break; 1225194676Sthompsa } 1226194676Sthompsa} 1227194676Sthompsa 1228195957Salfred/* This function must be called locked */ 1229195957Salfred 1230195957Salfredstatic void 1231195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer) 1232194676Sthompsa{ 1233195957Salfred struct libusb_super_transfer *sxfer; 1234195957Salfred struct libusb_transfer *uxfer; 1235195957Salfred uint32_t max_bulk; 1236195957Salfred uint32_t actlen; 1237195957Salfred uint8_t status; 1238195957Salfred uint8_t flags; 1239194676Sthompsa 1240195957Salfred status = libusb20_tr_get_status(pxfer); 1241195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1242195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1243195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1244194676Sthompsa 1245195957Salfred if (sxfer == NULL) 1246195957Salfred return; /* cancelled - nothing to do */ 1247194676Sthompsa 1248195957Salfred uxfer = (struct libusb_transfer *)( 1249195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1250194676Sthompsa 1251195957Salfred flags = uxfer->flags; 1252194676Sthompsa 1253195957Salfred switch (status) { 1254195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1255194676Sthompsa 1256195957Salfred uxfer->actual_length += actlen; 1257195957Salfred 1258195957Salfred /* subtract length of SETUP packet, if any */ 1259195957Salfred actlen -= libusb20_tr_get_length(pxfer, 0); 1260195957Salfred 1261195957Salfred /* check for short packet */ 1262195957Salfred if (sxfer->last_len != actlen) { 1263195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1264195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1265195957Salfred } else { 1266195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1267195957Salfred } 1268195957Salfred break; 1269194676Sthompsa } 1270195957Salfred /* check for end of data */ 1271195957Salfred if (sxfer->rem_len == 0) { 1272195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1273195957Salfred break; 1274195957Salfred } 1275195957Salfred /* FALLTHROUGH */ 1276194676Sthompsa 1277195957Salfred case LIBUSB20_TRANSFER_START: 1278195957Salfred if (max_bulk > sxfer->rem_len) { 1279195957Salfred max_bulk = sxfer->rem_len; 1280195957Salfred } 1281195957Salfred /* setup new CONTROL transaction */ 1282195957Salfred if (status == LIBUSB20_TRANSFER_COMPLETED) { 1283195957Salfred /* next fragment - don't send SETUP packet */ 1284195957Salfred libusb20_tr_set_length(pxfer, 0, 0); 1285195957Salfred } else { 1286195957Salfred /* first fragment - send SETUP packet */ 1287195957Salfred libusb20_tr_set_length(pxfer, 8, 0); 1288195957Salfred libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0); 1289195957Salfred } 1290195957Salfred 1291195957Salfred if (max_bulk != 0) { 1292195957Salfred libusb20_tr_set_length(pxfer, max_bulk, 1); 1293195957Salfred libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1); 1294195957Salfred libusb20_tr_set_total_frames(pxfer, 2); 1295195957Salfred } else { 1296195957Salfred libusb20_tr_set_total_frames(pxfer, 1); 1297195957Salfred } 1298195957Salfred 1299195957Salfred /* update counters */ 1300195957Salfred sxfer->last_len = max_bulk; 1301195957Salfred sxfer->curr_data += max_bulk; 1302195957Salfred sxfer->rem_len -= max_bulk; 1303195957Salfred 1304195957Salfred libusb20_tr_submit(pxfer); 1305195957Salfred 1306195957Salfred /* check if we can fork another USB transfer */ 1307195957Salfred if (sxfer->rem_len == 0) 1308195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1309195957Salfred break; 1310195957Salfred 1311195957Salfred default: 1312195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1313195957Salfred break; 1314194676Sthompsa } 1315195957Salfred} 1316195957Salfred 1317195957Salfred/* The following function must be called locked */ 1318195957Salfred 1319195957Salfredstatic void 1320195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint) 1321195957Salfred{ 1322195957Salfred struct libusb20_transfer *pxfer0; 1323195957Salfred struct libusb20_transfer *pxfer1; 1324195957Salfred struct libusb_super_transfer *sxfer; 1325195957Salfred struct libusb_transfer *uxfer; 1326195957Salfred struct libusb_device *dev; 1327195957Salfred int err; 1328195957Salfred int buffsize; 1329195957Salfred int maxframe; 1330195957Salfred int temp; 1331195957Salfred 1332195957Salfred dev = libusb_get_device(pdev); 1333195957Salfred 1334195957Salfred pxfer0 = libusb10_get_transfer(pdev, endpoint, 0); 1335195957Salfred pxfer1 = libusb10_get_transfer(pdev, endpoint, 1); 1336195957Salfred 1337195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) 1338195957Salfred return; /* shouldn't happen */ 1339195957Salfred 1340195957Salfred temp = 0; 1341195957Salfred if (libusb20_tr_pending(pxfer0)) 1342195957Salfred temp |= 1; 1343195957Salfred if (libusb20_tr_pending(pxfer1)) 1344195957Salfred temp |= 2; 1345195957Salfred 1346195957Salfred switch (temp) { 1347195957Salfred case 3: 1348195957Salfred /* wait till one of the transfers complete */ 1349195957Salfred return; 1350195957Salfred case 2: 1351195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer1); 1352199575Sthompsa if (sxfer == NULL) 1353199575Sthompsa return; /* cancelling */ 1354195957Salfred if (sxfer->rem_len) 1355195957Salfred return; /* cannot queue another one */ 1356195957Salfred /* swap transfers */ 1357195957Salfred pxfer1 = pxfer0; 1358195957Salfred break; 1359195957Salfred case 1: 1360195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer0); 1361199575Sthompsa if (sxfer == NULL) 1362199575Sthompsa return; /* cancelling */ 1363195957Salfred if (sxfer->rem_len) 1364195957Salfred return; /* cannot queue another one */ 1365195957Salfred /* swap transfers */ 1366195957Salfred pxfer0 = pxfer1; 1367195957Salfred break; 1368195957Salfred default: 1369195957Salfred break; 1370194676Sthompsa } 1371195957Salfred 1372195957Salfred /* find next transfer on same endpoint */ 1373195957Salfred TAILQ_FOREACH(sxfer, &dev->tr_head, entry) { 1374195957Salfred 1375195957Salfred uxfer = (struct libusb_transfer *)( 1376195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1377195957Salfred 1378195957Salfred if (uxfer->endpoint == endpoint) { 1379195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1380195957Salfred sxfer->entry.tqe_prev = NULL; 1381195957Salfred goto found; 1382194676Sthompsa } 1383195957Salfred } 1384195957Salfred return; /* success */ 1385194676Sthompsa 1386195957Salfredfound: 1387194676Sthompsa 1388195957Salfred libusb20_tr_set_priv_sc0(pxfer0, pdev); 1389195957Salfred libusb20_tr_set_priv_sc1(pxfer0, sxfer); 1390194676Sthompsa 1391195957Salfred /* reset super transfer state */ 1392195957Salfred sxfer->rem_len = uxfer->length; 1393195957Salfred sxfer->curr_data = uxfer->buffer; 1394195957Salfred uxfer->actual_length = 0; 1395194676Sthompsa 1396195957Salfred switch (uxfer->type) { 1397195957Salfred case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1398195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); 1399195957Salfred break; 1400195957Salfred case LIBUSB_TRANSFER_TYPE_BULK: 1401195957Salfred case LIBUSB_TRANSFER_TYPE_INTERRUPT: 1402195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); 1403195957Salfred break; 1404195957Salfred case LIBUSB_TRANSFER_TYPE_CONTROL: 1405195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); 1406195957Salfred if (sxfer->rem_len < 8) 1407195957Salfred goto failure; 1408194676Sthompsa 1409195957Salfred /* remove SETUP packet from data */ 1410195957Salfred sxfer->rem_len -= 8; 1411195957Salfred sxfer->curr_data += 8; 1412195957Salfred break; 1413195957Salfred default: 1414195957Salfred goto failure; 1415195560Sthompsa } 1416195957Salfred 1417195957Salfred buffsize = libusb10_get_buffsize(pdev, uxfer); 1418195957Salfred maxframe = libusb10_get_maxframe(pdev, uxfer); 1419195957Salfred 1420195957Salfred /* make sure the transfer is opened */ 1421302125Shselasky err = libusb20_tr_open_stream(pxfer0, buffsize, maxframe, 1422302125Shselasky endpoint, sxfer->stream_id); 1423195957Salfred if (err && (err != LIBUSB20_ERROR_BUSY)) { 1424195957Salfred goto failure; 1425194676Sthompsa } 1426195957Salfred libusb20_tr_start(pxfer0); 1427195957Salfred return; 1428194676Sthompsa 1429195957Salfredfailure: 1430195957Salfred libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); 1431195957Salfred /* make sure our event loop spins the done handler */ 1432338788Shselasky libusb10_wakeup_event_loop(dev->ctx); 1433195957Salfred} 1434194676Sthompsa 1435195957Salfred/* The following function must be called unlocked */ 1436194676Sthompsa 1437195957Salfredint 1438195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer) 1439195957Salfred{ 1440195957Salfred struct libusb20_transfer *pxfer0; 1441195957Salfred struct libusb20_transfer *pxfer1; 1442195957Salfred struct libusb_super_transfer *sxfer; 1443195957Salfred struct libusb_device *dev; 1444234684Shselasky uint8_t endpoint; 1445195957Salfred int err; 1446195957Salfred 1447195957Salfred if (uxfer == NULL) 1448195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1449195957Salfred 1450195957Salfred if (uxfer->dev_handle == NULL) 1451195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1452195957Salfred 1453195957Salfred endpoint = uxfer->endpoint; 1454195957Salfred 1455195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1456195957Salfred 1457195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); 1458195957Salfred 1459195957Salfred sxfer = (struct libusb_super_transfer *)( 1460195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1461195957Salfred 1462195957Salfred CTX_LOCK(dev->ctx); 1463195957Salfred 1464195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1465195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1466195957Salfred 1467195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) { 1468195957Salfred err = LIBUSB_ERROR_OTHER; 1469195957Salfred } else if ((sxfer->entry.tqe_prev != NULL) || 1470199575Sthompsa (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) || 1471195957Salfred (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) { 1472195957Salfred err = LIBUSB_ERROR_BUSY; 1473338788Shselasky } else if (dev->device_is_gone != 0) { 1474338788Shselasky err = LIBUSB_ERROR_NO_DEVICE; 1475195957Salfred } else { 1476199575Sthompsa 1477199575Sthompsa /* set pending state */ 1478199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_PEND; 1479199575Sthompsa 1480199575Sthompsa /* insert transfer into transfer head list */ 1481195957Salfred TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry); 1482195957Salfred 1483199575Sthompsa /* start work transfers */ 1484195957Salfred libusb10_submit_transfer_sub( 1485195957Salfred uxfer->dev_handle, endpoint); 1486195957Salfred 1487195957Salfred err = 0; /* success */ 1488195957Salfred } 1489195957Salfred 1490195957Salfred CTX_UNLOCK(dev->ctx); 1491195957Salfred 1492195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); 1493195957Salfred 1494195957Salfred return (err); 1495194676Sthompsa} 1496194676Sthompsa 1497195957Salfred/* Asynchronous transfer cancel */ 1498195957Salfred 1499194676Sthompsaint 1500195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer) 1501194676Sthompsa{ 1502195957Salfred struct libusb20_transfer *pxfer0; 1503195957Salfred struct libusb20_transfer *pxfer1; 1504195957Salfred struct libusb_super_transfer *sxfer; 1505195957Salfred struct libusb_device *dev; 1506338788Shselasky struct libusb_device_handle *devh; 1507234684Shselasky uint8_t endpoint; 1508199575Sthompsa int retval; 1509194676Sthompsa 1510195957Salfred if (uxfer == NULL) 1511195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1512194676Sthompsa 1513199575Sthompsa /* check if not initialised */ 1514338788Shselasky if ((devh = uxfer->dev_handle) == NULL) 1515199575Sthompsa return (LIBUSB_ERROR_NOT_FOUND); 1516194676Sthompsa 1517195957Salfred endpoint = uxfer->endpoint; 1518194676Sthompsa 1519338788Shselasky dev = libusb_get_device(devh); 1520195957Salfred 1521195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); 1522195957Salfred 1523195957Salfred sxfer = (struct libusb_super_transfer *)( 1524195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1525195957Salfred 1526199575Sthompsa retval = 0; 1527199575Sthompsa 1528195957Salfred CTX_LOCK(dev->ctx); 1529195957Salfred 1530338788Shselasky pxfer0 = libusb10_get_transfer(devh, endpoint, 0); 1531338788Shselasky pxfer1 = libusb10_get_transfer(devh, endpoint, 1); 1532195957Salfred 1533199575Sthompsa if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { 1534199575Sthompsa /* only update the transfer status */ 1535199575Sthompsa uxfer->status = LIBUSB_TRANSFER_CANCELLED; 1536199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1537199575Sthompsa } else if (sxfer->entry.tqe_prev != NULL) { 1538195957Salfred /* we are lucky - transfer is on a queue */ 1539195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1540195957Salfred sxfer->entry.tqe_prev = NULL; 1541199575Sthompsa libusb10_complete_transfer(NULL, 1542199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1543338788Shselasky /* make sure our event loop spins the done handler */ 1544338788Shselasky libusb10_wakeup_event_loop(dev->ctx); 1545195957Salfred } else if (pxfer0 == NULL || pxfer1 == NULL) { 1546195957Salfred /* not started */ 1547199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1548195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { 1549199575Sthompsa libusb10_complete_transfer(pxfer0, 1550199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1551338788Shselasky if (dev->device_is_gone != 0) { 1552338788Shselasky /* clear transfer pointer */ 1553338788Shselasky libusb20_tr_set_priv_sc1(pxfer0, NULL); 1554338788Shselasky /* make sure our event loop spins the done handler */ 1555338788Shselasky libusb10_wakeup_event_loop(dev->ctx); 1556338788Shselasky } else { 1557338788Shselasky libusb20_tr_stop(pxfer0); 1558338788Shselasky /* make sure the queue doesn't stall */ 1559338788Shselasky libusb10_submit_transfer_sub(devh, endpoint); 1560338788Shselasky } 1561195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { 1562199575Sthompsa libusb10_complete_transfer(pxfer1, 1563199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1564338788Shselasky /* check if handle is still active */ 1565338788Shselasky if (dev->device_is_gone != 0) { 1566338788Shselasky /* clear transfer pointer */ 1567338788Shselasky libusb20_tr_set_priv_sc1(pxfer1, NULL); 1568338788Shselasky /* make sure our event loop spins the done handler */ 1569338788Shselasky libusb10_wakeup_event_loop(dev->ctx); 1570338788Shselasky } else { 1571338788Shselasky libusb20_tr_stop(pxfer1); 1572338788Shselasky /* make sure the queue doesn't stall */ 1573338788Shselasky libusb10_submit_transfer_sub(devh, endpoint); 1574338788Shselasky } 1575195957Salfred } else { 1576195957Salfred /* not started */ 1577199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1578195957Salfred } 1579195957Salfred 1580195957Salfred CTX_UNLOCK(dev->ctx); 1581195957Salfred 1582195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); 1583195957Salfred 1584199575Sthompsa return (retval); 1585194676Sthompsa} 1586194676Sthompsa 1587195957SalfredUNEXPORTED void 1588195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev) 1589195957Salfred{ 1590301842Shselasky struct libusb20_device *pdev = dev->os_priv; 1591301842Shselasky unsigned x; 1592301842Shselasky 1593301842Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1594301842Shselasky struct libusb20_transfer *xfer; 1595301842Shselasky 1596301842Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1597301842Shselasky if (xfer == NULL) 1598301842Shselasky continue; 1599301842Shselasky libusb20_tr_close(xfer); 1600301842Shselasky } 1601195957Salfred} 1602199055Sthompsa 1603338788ShselaskyUNEXPORTED void 1604338788Shselaskylibusb10_cancel_all_transfer_locked(struct libusb20_device *pdev, struct libusb_device *dev) 1605338788Shselasky{ 1606338788Shselasky struct libusb_super_transfer *sxfer; 1607338788Shselasky unsigned x; 1608338788Shselasky 1609338788Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1610338788Shselasky struct libusb20_transfer *xfer; 1611338788Shselasky 1612338788Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1613338788Shselasky if (xfer == NULL) 1614338788Shselasky continue; 1615338788Shselasky if (libusb20_tr_pending(xfer) == 0) 1616338788Shselasky continue; 1617338788Shselasky sxfer = libusb20_tr_get_priv_sc1(xfer); 1618338788Shselasky if (sxfer == NULL) 1619338788Shselasky continue; 1620338788Shselasky /* complete pending transfer */ 1621338788Shselasky libusb10_complete_transfer(xfer, sxfer, LIBUSB_TRANSFER_ERROR); 1622338788Shselasky } 1623338788Shselasky 1624338788Shselasky while ((sxfer = TAILQ_FIRST(&dev->tr_head))) { 1625338788Shselasky TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1626338788Shselasky 1627338788Shselasky /* complete pending transfer */ 1628338788Shselasky libusb10_complete_transfer(NULL, sxfer, LIBUSB_TRANSFER_ERROR); 1629338788Shselasky } 1630338788Shselasky} 1631338788Shselasky 1632199055Sthompsauint16_t 1633199055Sthompsalibusb_cpu_to_le16(uint16_t x) 1634199055Sthompsa{ 1635199055Sthompsa return (htole16(x)); 1636199055Sthompsa} 1637199055Sthompsa 1638199055Sthompsauint16_t 1639199055Sthompsalibusb_le16_to_cpu(uint16_t x) 1640199055Sthompsa{ 1641199055Sthompsa return (le16toh(x)); 1642199055Sthompsa} 1643199055Sthompsa 1644213853Shselaskyconst char * 1645213853Shselaskylibusb_strerror(int code) 1646213853Shselasky{ 1647225659Shselasky switch (code) { 1648225659Shselasky case LIBUSB_SUCCESS: 1649225659Shselasky return ("Success"); 1650225659Shselasky case LIBUSB_ERROR_IO: 1651225659Shselasky return ("I/O error"); 1652225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1653225659Shselasky return ("Invalid parameter"); 1654225659Shselasky case LIBUSB_ERROR_ACCESS: 1655225659Shselasky return ("Permissions error"); 1656225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1657225659Shselasky return ("No device"); 1658225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1659225659Shselasky return ("Not found"); 1660225659Shselasky case LIBUSB_ERROR_BUSY: 1661225659Shselasky return ("Device busy"); 1662225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1663225659Shselasky return ("Timeout"); 1664225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1665225659Shselasky return ("Overflow"); 1666225659Shselasky case LIBUSB_ERROR_PIPE: 1667225659Shselasky return ("Pipe error"); 1668225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1669225659Shselasky return ("Interrupted"); 1670225659Shselasky case LIBUSB_ERROR_NO_MEM: 1671225659Shselasky return ("Out of memory"); 1672225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1673225659Shselasky return ("Not supported"); 1674225659Shselasky case LIBUSB_ERROR_OTHER: 1675225659Shselasky return ("Other error"); 1676225659Shselasky default: 1677225659Shselasky return ("Unknown error"); 1678225659Shselasky } 1679213853Shselasky} 1680225659Shselasky 1681225659Shselaskyconst char * 1682225659Shselaskylibusb_error_name(int code) 1683225659Shselasky{ 1684225659Shselasky switch (code) { 1685225659Shselasky case LIBUSB_SUCCESS: 1686225659Shselasky return ("LIBUSB_SUCCESS"); 1687225659Shselasky case LIBUSB_ERROR_IO: 1688225659Shselasky return ("LIBUSB_ERROR_IO"); 1689225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1690225659Shselasky return ("LIBUSB_ERROR_INVALID_PARAM"); 1691225659Shselasky case LIBUSB_ERROR_ACCESS: 1692225659Shselasky return ("LIBUSB_ERROR_ACCESS"); 1693225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1694225659Shselasky return ("LIBUSB_ERROR_NO_DEVICE"); 1695225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1696225659Shselasky return ("LIBUSB_ERROR_NOT_FOUND"); 1697225659Shselasky case LIBUSB_ERROR_BUSY: 1698225659Shselasky return ("LIBUSB_ERROR_BUSY"); 1699225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1700225659Shselasky return ("LIBUSB_ERROR_TIMEOUT"); 1701225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1702225659Shselasky return ("LIBUSB_ERROR_OVERFLOW"); 1703225659Shselasky case LIBUSB_ERROR_PIPE: 1704225659Shselasky return ("LIBUSB_ERROR_PIPE"); 1705225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1706225659Shselasky return ("LIBUSB_ERROR_INTERRUPTED"); 1707225659Shselasky case LIBUSB_ERROR_NO_MEM: 1708225659Shselasky return ("LIBUSB_ERROR_NO_MEM"); 1709225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1710225659Shselasky return ("LIBUSB_ERROR_NOT_SUPPORTED"); 1711225659Shselasky case LIBUSB_ERROR_OTHER: 1712225659Shselasky return ("LIBUSB_ERROR_OTHER"); 1713225659Shselasky default: 1714225659Shselasky return ("LIBUSB_ERROR_UNKNOWN"); 1715225659Shselasky } 1716225659Shselasky} 1717362224Skevans 1718362224Skevansint 1719362224Skevanslibusb_has_capability(uint32_t capability) 1720362224Skevans{ 1721362224Skevans 1722362224Skevans switch (capability) { 1723362224Skevans case LIBUSB_CAP_HAS_CAPABILITY: 1724362224Skevans case LIBUSB_CAP_HAS_HOTPLUG: 1725362224Skevans case LIBUSB_CAP_HAS_HID_ACCESS: 1726362224Skevans case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: 1727362224Skevans return (1); 1728362224Skevans default: 1729362224Skevans return (0); 1730362224Skevans } 1731362224Skevans} 1732