1194676Sthompsa/* $FreeBSD: stable/10/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 54302272Shselasky#define LIBUSB_NUM_SW_ENDPOINTS (16 * 4) 55302272Shselasky 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 72302275Shselaskystatic const struct libusb_version libusb_version = { 73302275Shselasky .major = 1, 74302275Shselasky .minor = 0, 75302275Shselasky .micro = 0, 76302275Shselasky .nano = 2016, 77302275Shselasky .rc = "", 78302275Shselasky .describe = "http://www.freebsd.org" 79302275Shselasky}; 80302275Shselasky 81302275Shselaskyconst struct libusb_version * 82302275Shselaskylibusb_get_version(void) 83302275Shselasky{ 84302275Shselasky 85302275Shselasky return (&libusb_version); 86302275Shselasky} 87302275Shselasky 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 115338789Shselaskystatic void 116338789Shselaskylibusb10_wakeup_event_loop(libusb_context *ctx) 117338789Shselasky{ 118338789Shselasky uint8_t dummy = 0; 119338789Shselasky int err; 120338789Shselasky 121338789Shselasky err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 122338789Shselasky if (err < (int)sizeof(dummy)) { 123338789Shselasky /* ignore error, if any */ 124338789Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "Waking up event loop failed!"); 125338789Shselasky } 126338789Shselasky} 127338789Shselasky 128194676Sthompsaint 129195957Salfredlibusb_init(libusb_context **context) 130194676Sthompsa{ 131194676Sthompsa struct libusb_context *ctx; 132236944Shselasky pthread_condattr_t attr; 133195957Salfred char *debug; 134194676Sthompsa int ret; 135194676Sthompsa 136194676Sthompsa ctx = malloc(sizeof(*ctx)); 137194676Sthompsa if (!ctx) 138194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 139194676Sthompsa 140194676Sthompsa memset(ctx, 0, sizeof(*ctx)); 141194676Sthompsa 142194676Sthompsa debug = getenv("LIBUSB_DEBUG"); 143194676Sthompsa if (debug != NULL) { 144194676Sthompsa ctx->debug = atoi(debug); 145194676Sthompsa if (ctx->debug != 0) 146194676Sthompsa ctx->debug_fixed = 1; 147194676Sthompsa } 148195957Salfred TAILQ_INIT(&ctx->pollfds); 149195957Salfred TAILQ_INIT(&ctx->tr_done); 150302275Shselasky TAILQ_INIT(&ctx->hotplug_cbh); 151302275Shselasky TAILQ_INIT(&ctx->hotplug_devs); 152194676Sthompsa 153236944Shselasky if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) { 154236944Shselasky free(ctx); 155236944Shselasky return (LIBUSB_ERROR_NO_MEM); 156236944Shselasky } 157302275Shselasky if (pthread_mutex_init(&ctx->hotplug_lock, NULL) != 0) { 158302275Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 159302275Shselasky free(ctx); 160302275Shselasky return (LIBUSB_ERROR_NO_MEM); 161302275Shselasky } 162236944Shselasky if (pthread_condattr_init(&attr) != 0) { 163236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 164302275Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 165236944Shselasky free(ctx); 166236944Shselasky return (LIBUSB_ERROR_NO_MEM); 167236944Shselasky } 168236944Shselasky if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) { 169236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 170302275Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 171236944Shselasky pthread_condattr_destroy(&attr); 172236944Shselasky free(ctx); 173236944Shselasky return (LIBUSB_ERROR_OTHER); 174236944Shselasky } 175236944Shselasky if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) { 176236944Shselasky pthread_mutex_destroy(&ctx->ctx_lock); 177302275Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 178236944Shselasky pthread_condattr_destroy(&attr); 179236944Shselasky free(ctx); 180236944Shselasky return (LIBUSB_ERROR_NO_MEM); 181236944Shselasky } 182236944Shselasky pthread_condattr_destroy(&attr); 183194676Sthompsa 184195957Salfred ctx->ctx_handler = NO_THREAD; 185302275Shselasky ctx->hotplug_handler = NO_THREAD; 186194676Sthompsa 187194676Sthompsa ret = pipe(ctx->ctrl_pipe); 188194676Sthompsa if (ret < 0) { 189195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 190302275Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 191195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 192194676Sthompsa free(ctx); 193194676Sthompsa return (LIBUSB_ERROR_OTHER); 194194676Sthompsa } 195195957Salfred /* set non-blocking mode on the control pipe to avoid deadlock */ 196213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[0]); 197213853Shselasky libusb_set_nonblocking(ctx->ctrl_pipe[1]); 198194676Sthompsa 199195957Salfred libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); 200194676Sthompsa 201194676Sthompsa pthread_mutex_lock(&default_context_lock); 202194676Sthompsa if (usbi_default_context == NULL) { 203194676Sthompsa usbi_default_context = ctx; 204194676Sthompsa } 205194676Sthompsa pthread_mutex_unlock(&default_context_lock); 206194676Sthompsa 207194676Sthompsa if (context) 208194676Sthompsa *context = ctx; 209194676Sthompsa 210195957Salfred DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); 211195957Salfred 212194676Sthompsa return (0); 213194676Sthompsa} 214194676Sthompsa 215194676Sthompsavoid 216195957Salfredlibusb_exit(libusb_context *ctx) 217194676Sthompsa{ 218195957Salfred ctx = GET_CONTEXT(ctx); 219194676Sthompsa 220195957Salfred if (ctx == NULL) 221195957Salfred return; 222195957Salfred 223302275Shselasky /* stop hotplug thread, if any */ 224302275Shselasky 225302275Shselasky if (ctx->hotplug_handler != NO_THREAD) { 226302275Shselasky pthread_t td; 227302275Shselasky void *ptr; 228302275Shselasky 229302275Shselasky HOTPLUG_LOCK(ctx); 230302275Shselasky td = ctx->hotplug_handler; 231302275Shselasky ctx->hotplug_handler = NO_THREAD; 232302275Shselasky HOTPLUG_UNLOCK(ctx); 233302275Shselasky 234302275Shselasky pthread_join(td, &ptr); 235302275Shselasky } 236302275Shselasky 237195957Salfred /* XXX cleanup devices */ 238195957Salfred 239195957Salfred libusb10_remove_pollfd(ctx, &ctx->ctx_poll); 240194676Sthompsa close(ctx->ctrl_pipe[0]); 241194676Sthompsa close(ctx->ctrl_pipe[1]); 242195957Salfred pthread_mutex_destroy(&ctx->ctx_lock); 243302275Shselasky pthread_mutex_destroy(&ctx->hotplug_lock); 244195957Salfred pthread_cond_destroy(&ctx->ctx_cond); 245194676Sthompsa 246194676Sthompsa pthread_mutex_lock(&default_context_lock); 247194676Sthompsa if (ctx == usbi_default_context) { 248194676Sthompsa usbi_default_context = NULL; 249194676Sthompsa } 250194676Sthompsa pthread_mutex_unlock(&default_context_lock); 251194676Sthompsa 252194676Sthompsa free(ctx); 253194676Sthompsa} 254194676Sthompsa 255194676Sthompsa/* Device handling and initialisation. */ 256194676Sthompsa 257194676Sthompsassize_t 258195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list) 259194676Sthompsa{ 260195957Salfred struct libusb20_backend *usb_backend; 261194676Sthompsa struct libusb20_device *pdev; 262194676Sthompsa struct libusb_device *dev; 263194676Sthompsa int i; 264194676Sthompsa 265195957Salfred ctx = GET_CONTEXT(ctx); 266194676Sthompsa 267195957Salfred if (ctx == NULL) 268195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 269195957Salfred 270195957Salfred if (list == NULL) 271195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 272195957Salfred 273194676Sthompsa usb_backend = libusb20_be_alloc_default(); 274194676Sthompsa if (usb_backend == NULL) 275195957Salfred return (LIBUSB_ERROR_NO_MEM); 276194676Sthompsa 277195957Salfred /* figure out how many USB devices are present */ 278194676Sthompsa pdev = NULL; 279194676Sthompsa i = 0; 280194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) 281194676Sthompsa i++; 282194676Sthompsa 283195957Salfred /* allocate device pointer list */ 284194676Sthompsa *list = malloc((i + 1) * sizeof(void *)); 285194676Sthompsa if (*list == NULL) { 286194676Sthompsa libusb20_be_free(usb_backend); 287194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 288194676Sthompsa } 289195957Salfred /* create libusb v1.0 compliant devices */ 290194676Sthompsa i = 0; 291194676Sthompsa while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 292194676Sthompsa 293194676Sthompsa dev = malloc(sizeof(*dev)); 294194676Sthompsa if (dev == NULL) { 295195560Sthompsa while (i != 0) { 296195560Sthompsa libusb_unref_device((*list)[i - 1]); 297195560Sthompsa i--; 298195560Sthompsa } 299194676Sthompsa free(*list); 300195957Salfred *list = NULL; 301194676Sthompsa libusb20_be_free(usb_backend); 302194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 303194676Sthompsa } 304199055Sthompsa /* get device into libUSB v1.0 list */ 305199055Sthompsa libusb20_be_dequeue_device(usb_backend, pdev); 306199055Sthompsa 307194676Sthompsa memset(dev, 0, sizeof(*dev)); 308194676Sthompsa 309195957Salfred /* init transfer queues */ 310195957Salfred TAILQ_INIT(&dev->tr_head); 311195957Salfred 312195957Salfred /* set context we belong to */ 313194676Sthompsa dev->ctx = ctx; 314194676Sthompsa 315194676Sthompsa /* link together the two structures */ 316194676Sthompsa dev->os_priv = pdev; 317195957Salfred pdev->privLuData = dev; 318194676Sthompsa 319194676Sthompsa (*list)[i] = libusb_ref_device(dev); 320194676Sthompsa i++; 321194676Sthompsa } 322194676Sthompsa (*list)[i] = NULL; 323194676Sthompsa 324194676Sthompsa libusb20_be_free(usb_backend); 325194676Sthompsa return (i); 326194676Sthompsa} 327194676Sthompsa 328194676Sthompsavoid 329194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices) 330194676Sthompsa{ 331194676Sthompsa int i; 332194676Sthompsa 333194676Sthompsa if (list == NULL) 334195957Salfred return; /* be NULL safe */ 335194676Sthompsa 336194676Sthompsa if (unref_devices) { 337194676Sthompsa for (i = 0; list[i] != NULL; i++) 338194676Sthompsa libusb_unref_device(list[i]); 339194676Sthompsa } 340194676Sthompsa free(list); 341194676Sthompsa} 342194676Sthompsa 343194676Sthompsauint8_t 344195957Salfredlibusb_get_bus_number(libusb_device *dev) 345194676Sthompsa{ 346194676Sthompsa if (dev == NULL) 347195957Salfred return (0); /* should not happen */ 348195957Salfred return (libusb20_dev_get_bus_number(dev->os_priv)); 349194676Sthompsa} 350194676Sthompsa 351302275Shselaskyuint8_t 352302275Shselaskylibusb_get_port_number(libusb_device *dev) 353302275Shselasky{ 354302275Shselasky if (dev == NULL) 355302275Shselasky return (0); /* should not happen */ 356302275Shselasky return (libusb20_dev_get_parent_port(dev->os_priv)); 357302275Shselasky} 358302275Shselasky 359250342Semasteint 360251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) 361251495Semaste{ 362251495Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 363251495Semaste} 364251495Semaste 365251495Semasteint 366250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, 367250342Semaste uint8_t bufsize) 368250342Semaste{ 369250342Semaste return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize)); 370250342Semaste} 371250342Semaste 372194676Sthompsauint8_t 373195957Salfredlibusb_get_device_address(libusb_device *dev) 374194676Sthompsa{ 375194676Sthompsa if (dev == NULL) 376195957Salfred return (0); /* should not happen */ 377195957Salfred return (libusb20_dev_get_address(dev->os_priv)); 378194676Sthompsa} 379194676Sthompsa 380224903Shselaskyenum libusb_speed 381224903Shselaskylibusb_get_device_speed(libusb_device *dev) 382224903Shselasky{ 383224903Shselasky if (dev == NULL) 384225035Shselasky return (LIBUSB_SPEED_UNKNOWN); /* should not happen */ 385224903Shselasky 386224903Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 387224903Shselasky case LIBUSB20_SPEED_LOW: 388224903Shselasky return (LIBUSB_SPEED_LOW); 389224903Shselasky case LIBUSB20_SPEED_FULL: 390224903Shselasky return (LIBUSB_SPEED_FULL); 391224903Shselasky case LIBUSB20_SPEED_HIGH: 392224903Shselasky return (LIBUSB_SPEED_HIGH); 393224903Shselasky case LIBUSB20_SPEED_SUPER: 394224903Shselasky return (LIBUSB_SPEED_SUPER); 395224903Shselasky default: 396224903Shselasky break; 397224903Shselasky } 398224903Shselasky return (LIBUSB_SPEED_UNKNOWN); 399224903Shselasky} 400224903Shselasky 401194676Sthompsaint 402195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint) 403194676Sthompsa{ 404194676Sthompsa struct libusb_config_descriptor *pdconf; 405194676Sthompsa struct libusb_interface *pinf; 406194676Sthompsa struct libusb_interface_descriptor *pdinf; 407194676Sthompsa struct libusb_endpoint_descriptor *pdend; 408195957Salfred int i; 409195957Salfred int j; 410195957Salfred int k; 411195957Salfred int ret; 412194676Sthompsa 413194676Sthompsa if (dev == NULL) 414194676Sthompsa return (LIBUSB_ERROR_NO_DEVICE); 415194676Sthompsa 416195957Salfred ret = libusb_get_active_config_descriptor(dev, &pdconf); 417195957Salfred if (ret < 0) 418195957Salfred return (ret); 419195957Salfred 420194676Sthompsa ret = LIBUSB_ERROR_NOT_FOUND; 421195957Salfred for (i = 0; i < pdconf->bNumInterfaces; i++) { 422194676Sthompsa pinf = &pdconf->interface[i]; 423195957Salfred for (j = 0; j < pinf->num_altsetting; j++) { 424194676Sthompsa pdinf = &pinf->altsetting[j]; 425195957Salfred for (k = 0; k < pdinf->bNumEndpoints; k++) { 426194676Sthompsa pdend = &pdinf->endpoint[k]; 427194676Sthompsa if (pdend->bEndpointAddress == endpoint) { 428194676Sthompsa ret = pdend->wMaxPacketSize; 429194676Sthompsa goto out; 430194676Sthompsa } 431194676Sthompsa } 432194676Sthompsa } 433194676Sthompsa } 434194676Sthompsa 435194676Sthompsaout: 436194676Sthompsa libusb_free_config_descriptor(pdconf); 437194676Sthompsa return (ret); 438194676Sthompsa} 439194676Sthompsa 440234193Shselaskyint 441234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint) 442234193Shselasky{ 443234193Shselasky int multiplier; 444234193Shselasky int ret; 445234193Shselasky 446234193Shselasky ret = libusb_get_max_packet_size(dev, endpoint); 447234193Shselasky 448234193Shselasky switch (libusb20_dev_get_speed(dev->os_priv)) { 449234193Shselasky case LIBUSB20_SPEED_LOW: 450234193Shselasky case LIBUSB20_SPEED_FULL: 451234193Shselasky break; 452234193Shselasky default: 453234193Shselasky if (ret > -1) { 454234193Shselasky multiplier = (1 + ((ret >> 11) & 3)); 455234193Shselasky if (multiplier > 3) 456234193Shselasky multiplier = 3; 457234193Shselasky ret = (ret & 0x7FF) * multiplier; 458234193Shselasky } 459234193Shselasky break; 460234193Shselasky } 461234193Shselasky return (ret); 462234193Shselasky} 463234193Shselasky 464194676Sthompsalibusb_device * 465195957Salfredlibusb_ref_device(libusb_device *dev) 466194676Sthompsa{ 467194676Sthompsa if (dev == NULL) 468195957Salfred return (NULL); /* be NULL safe */ 469194676Sthompsa 470195957Salfred CTX_LOCK(dev->ctx); 471194676Sthompsa dev->refcnt++; 472195957Salfred CTX_UNLOCK(dev->ctx); 473194676Sthompsa 474194676Sthompsa return (dev); 475194676Sthompsa} 476194676Sthompsa 477194676Sthompsavoid 478195957Salfredlibusb_unref_device(libusb_device *dev) 479194676Sthompsa{ 480194676Sthompsa if (dev == NULL) 481195957Salfred return; /* be NULL safe */ 482194676Sthompsa 483195957Salfred CTX_LOCK(dev->ctx); 484194676Sthompsa dev->refcnt--; 485195957Salfred CTX_UNLOCK(dev->ctx); 486194676Sthompsa 487194676Sthompsa if (dev->refcnt == 0) { 488194676Sthompsa libusb20_dev_free(dev->os_priv); 489194676Sthompsa free(dev); 490194676Sthompsa } 491194676Sthompsa} 492194676Sthompsa 493194676Sthompsaint 494195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh) 495194676Sthompsa{ 496194676Sthompsa libusb_context *ctx = dev->ctx; 497194676Sthompsa struct libusb20_device *pdev = dev->os_priv; 498194676Sthompsa int err; 499194676Sthompsa 500194676Sthompsa if (devh == NULL) 501194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 502194676Sthompsa 503195957Salfred /* set default device handle value */ 504195957Salfred *devh = NULL; 505194676Sthompsa 506195957Salfred dev = libusb_ref_device(dev); 507195957Salfred if (dev == NULL) 508195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 509195957Salfred 510302272Shselasky err = libusb20_dev_open(pdev, LIBUSB_NUM_SW_ENDPOINTS); 511194676Sthompsa if (err) { 512195957Salfred libusb_unref_device(dev); 513194676Sthompsa return (LIBUSB_ERROR_NO_MEM); 514194676Sthompsa } 515195957Salfred libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 516194676Sthompsa POLLOUT | POLLRDNORM | POLLWRNORM); 517194676Sthompsa 518195957Salfred /* make sure our event loop detects the new device */ 519338789Shselasky libusb10_wakeup_event_loop(ctx); 520338789Shselasky 521195957Salfred *devh = pdev; 522194676Sthompsa 523194676Sthompsa return (0); 524194676Sthompsa} 525194676Sthompsa 526194676Sthompsalibusb_device_handle * 527195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, 528194676Sthompsa uint16_t product_id) 529194676Sthompsa{ 530194676Sthompsa struct libusb_device **devs; 531194676Sthompsa struct libusb20_device *pdev; 532194676Sthompsa struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 533195957Salfred int i; 534195957Salfred int j; 535194676Sthompsa 536195957Salfred ctx = GET_CONTEXT(ctx); 537195957Salfred if (ctx == NULL) 538195957Salfred return (NULL); /* be NULL safe */ 539195957Salfred 540345541Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid enter"); 541194676Sthompsa 542194676Sthompsa if ((i = libusb_get_device_list(ctx, &devs)) < 0) 543194676Sthompsa return (NULL); 544194676Sthompsa 545228236Shselasky pdev = NULL; 546194676Sthompsa for (j = 0; j < i; j++) { 547228236Shselasky struct libusb20_device *tdev; 548228236Shselasky 549228236Shselasky tdev = devs[j]->os_priv; 550228236Shselasky pdesc = libusb20_dev_get_device_desc(tdev); 551195957Salfred /* 552195957Salfred * NOTE: The USB library will automatically swap the 553195957Salfred * fields in the device descriptor to be of host 554195957Salfred * endian type! 555195957Salfred */ 556194676Sthompsa if (pdesc->idVendor == vendor_id && 557195560Sthompsa pdesc->idProduct == product_id) { 558228235Shselasky libusb_open(devs[j], &pdev); 559195957Salfred break; 560195560Sthompsa } 561194676Sthompsa } 562194676Sthompsa 563194676Sthompsa libusb_free_device_list(devs, 1); 564345541Shselasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid leave"); 565195957Salfred return (pdev); 566194676Sthompsa} 567194676Sthompsa 568194676Sthompsavoid 569195957Salfredlibusb_close(struct libusb20_device *pdev) 570194676Sthompsa{ 571194676Sthompsa libusb_context *ctx; 572195957Salfred struct libusb_device *dev; 573194676Sthompsa 574195957Salfred if (pdev == NULL) 575195957Salfred return; /* be NULL safe */ 576194676Sthompsa 577195957Salfred dev = libusb_get_device(pdev); 578195957Salfred ctx = dev->ctx; 579194676Sthompsa 580195957Salfred libusb10_remove_pollfd(ctx, &dev->dev_poll); 581194676Sthompsa 582195957Salfred libusb20_dev_close(pdev); 583199055Sthompsa 584199055Sthompsa /* unref will free the "pdev" when the refcount reaches zero */ 585195957Salfred libusb_unref_device(dev); 586194676Sthompsa 587195957Salfred /* make sure our event loop detects the closed device */ 588338789Shselasky libusb10_wakeup_event_loop(ctx); 589194676Sthompsa} 590194676Sthompsa 591194676Sthompsalibusb_device * 592195957Salfredlibusb_get_device(struct libusb20_device *pdev) 593194676Sthompsa{ 594195957Salfred if (pdev == NULL) 595194676Sthompsa return (NULL); 596195957Salfred return ((libusb_device *)pdev->privLuData); 597194676Sthompsa} 598194676Sthompsa 599194676Sthompsaint 600195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config) 601194676Sthompsa{ 602195957Salfred struct libusb20_config *pconf; 603194676Sthompsa 604195957Salfred if (pdev == NULL || config == NULL) 605194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 606194676Sthompsa 607195957Salfred pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); 608195957Salfred if (pconf == NULL) 609195957Salfred return (LIBUSB_ERROR_NO_MEM); 610194676Sthompsa 611195957Salfred *config = pconf->desc.bConfigurationValue; 612195957Salfred 613195957Salfred free(pconf); 614195957Salfred 615194676Sthompsa return (0); 616194676Sthompsa} 617194676Sthompsa 618194676Sthompsaint 619195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration) 620194676Sthompsa{ 621195957Salfred struct libusb20_config *pconf; 622195957Salfred struct libusb_device *dev; 623195957Salfred int err; 624195957Salfred uint8_t i; 625194676Sthompsa 626195957Salfred dev = libusb_get_device(pdev); 627195957Salfred if (dev == NULL) 628194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 629194676Sthompsa 630195957Salfred if (configuration < 1) { 631195957Salfred /* unconfigure */ 632195957Salfred i = 255; 633195957Salfred } else { 634195957Salfred for (i = 0; i != 255; i++) { 635195957Salfred uint8_t found; 636194676Sthompsa 637195957Salfred pconf = libusb20_dev_alloc_config(pdev, i); 638195957Salfred if (pconf == NULL) 639195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 640195957Salfred found = (pconf->desc.bConfigurationValue 641195957Salfred == configuration); 642195957Salfred free(pconf); 643195957Salfred 644195957Salfred if (found) 645195957Salfred goto set_config; 646195957Salfred } 647195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 648195957Salfred } 649195957Salfred 650195957Salfredset_config: 651195957Salfred 652195957Salfred libusb10_cancel_all_transfer(dev); 653195957Salfred 654195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 655195957Salfred 656195957Salfred err = libusb20_dev_set_config_index(pdev, i); 657195957Salfred 658195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | 659195957Salfred POLLOUT | POLLRDNORM | POLLWRNORM); 660195957Salfred 661195957Salfred return (err ? LIBUSB_ERROR_INVALID_PARAM : 0); 662194676Sthompsa} 663194676Sthompsa 664194676Sthompsaint 665195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number) 666194676Sthompsa{ 667195957Salfred libusb_device *dev; 668302275Shselasky int err = 0; 669194676Sthompsa 670195957Salfred dev = libusb_get_device(pdev); 671194676Sthompsa if (dev == NULL) 672194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 673194676Sthompsa 674195957Salfred if (interface_number < 0 || interface_number > 31) 675194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 676194676Sthompsa 677302275Shselasky if (pdev->auto_detach != 0) { 678302275Shselasky err = libusb_detach_kernel_driver(pdev, interface_number); 679302275Shselasky if (err != 0) 680302275Shselasky goto done; 681302275Shselasky } 682302275Shselasky 683195957Salfred CTX_LOCK(dev->ctx); 684261475Shselasky dev->claimed_interfaces |= (1 << interface_number); 685261475Shselasky CTX_UNLOCK(dev->ctx); 686302275Shselaskydone: 687302275Shselasky return (err); 688194676Sthompsa} 689194676Sthompsa 690194676Sthompsaint 691195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number) 692194676Sthompsa{ 693195957Salfred libusb_device *dev; 694195957Salfred int err = 0; 695194676Sthompsa 696195957Salfred dev = libusb_get_device(pdev); 697194676Sthompsa if (dev == NULL) 698194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 699194676Sthompsa 700195957Salfred if (interface_number < 0 || interface_number > 31) 701194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 702194676Sthompsa 703302275Shselasky if (pdev->auto_detach != 0) { 704302275Shselasky err = libusb_attach_kernel_driver(pdev, interface_number); 705302275Shselasky if (err != 0) 706302275Shselasky goto done; 707302275Shselasky } 708302275Shselasky 709195957Salfred CTX_LOCK(dev->ctx); 710194676Sthompsa if (!(dev->claimed_interfaces & (1 << interface_number))) 711195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 712302275Shselasky else 713194676Sthompsa dev->claimed_interfaces &= ~(1 << interface_number); 714195957Salfred CTX_UNLOCK(dev->ctx); 715302275Shselaskydone: 716195957Salfred return (err); 717194676Sthompsa} 718194676Sthompsa 719194676Sthompsaint 720195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev, 721194676Sthompsa int interface_number, int alternate_setting) 722194676Sthompsa{ 723195957Salfred libusb_device *dev; 724195957Salfred int err = 0; 725194676Sthompsa 726195957Salfred dev = libusb_get_device(pdev); 727194676Sthompsa if (dev == NULL) 728194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 729194676Sthompsa 730195957Salfred if (interface_number < 0 || interface_number > 31) 731194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 732194676Sthompsa 733195957Salfred CTX_LOCK(dev->ctx); 734195957Salfred if (!(dev->claimed_interfaces & (1 << interface_number))) 735195957Salfred err = LIBUSB_ERROR_NOT_FOUND; 736195957Salfred CTX_UNLOCK(dev->ctx); 737194676Sthompsa 738195957Salfred if (err) 739195957Salfred return (err); 740195957Salfred 741195957Salfred libusb10_cancel_all_transfer(dev); 742195957Salfred 743195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 744195957Salfred 745195957Salfred err = libusb20_dev_set_alt_index(pdev, 746195957Salfred interface_number, alternate_setting); 747195957Salfred 748195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 749195957Salfred pdev, libusb20_dev_get_fd(pdev), 750195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 751195957Salfred 752195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 753194676Sthompsa} 754194676Sthompsa 755195957Salfredstatic struct libusb20_transfer * 756195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev, 757234491Shselasky uint8_t endpoint, uint8_t xfer_index) 758195957Salfred{ 759234491Shselasky xfer_index &= 1; /* double buffering */ 760195957Salfred 761234491Shselasky xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4; 762195957Salfred 763195957Salfred if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) { 764195957Salfred /* this is an IN endpoint */ 765234491Shselasky xfer_index |= 2; 766195957Salfred } 767234491Shselasky return (libusb20_tr_get_pointer(pdev, xfer_index)); 768195957Salfred} 769195957Salfred 770194676Sthompsaint 771195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint) 772194676Sthompsa{ 773194676Sthompsa struct libusb20_transfer *xfer; 774195957Salfred struct libusb_device *dev; 775195957Salfred int err; 776194676Sthompsa 777195957Salfred xfer = libusb10_get_transfer(pdev, endpoint, 0); 778195560Sthompsa if (xfer == NULL) 779195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 780194676Sthompsa 781195957Salfred dev = libusb_get_device(pdev); 782213853Shselasky if (dev == NULL) 783213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 784195957Salfred 785195957Salfred CTX_LOCK(dev->ctx); 786223642Shselasky err = libusb20_tr_open(xfer, 0, 1, endpoint); 787195957Salfred CTX_UNLOCK(dev->ctx); 788195957Salfred 789195957Salfred if (err != 0 && err != LIBUSB20_ERROR_BUSY) 790194676Sthompsa return (LIBUSB_ERROR_OTHER); 791194676Sthompsa 792194676Sthompsa libusb20_tr_clear_stall_sync(xfer); 793195957Salfred 794195957Salfred /* check if we opened the transfer */ 795195957Salfred if (err == 0) { 796195957Salfred CTX_LOCK(dev->ctx); 797194676Sthompsa libusb20_tr_close(xfer); 798195957Salfred CTX_UNLOCK(dev->ctx); 799195957Salfred } 800195957Salfred return (0); /* success */ 801194676Sthompsa} 802194676Sthompsa 803194676Sthompsaint 804195957Salfredlibusb_reset_device(struct libusb20_device *pdev) 805194676Sthompsa{ 806195957Salfred libusb_device *dev; 807195957Salfred int err; 808194676Sthompsa 809195957Salfred dev = libusb_get_device(pdev); 810194676Sthompsa if (dev == NULL) 811213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 812194676Sthompsa 813195957Salfred libusb10_cancel_all_transfer(dev); 814195957Salfred 815195957Salfred libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); 816195957Salfred 817195957Salfred err = libusb20_dev_reset(pdev); 818195957Salfred 819195957Salfred libusb10_add_pollfd(dev->ctx, &dev->dev_poll, 820195957Salfred pdev, libusb20_dev_get_fd(pdev), 821195957Salfred POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 822195957Salfred 823195957Salfred return (err ? LIBUSB_ERROR_OTHER : 0); 824194676Sthompsa} 825194676Sthompsa 826194676Sthompsaint 827213848Shselaskylibusb_check_connected(struct libusb20_device *pdev) 828213848Shselasky{ 829213848Shselasky libusb_device *dev; 830213848Shselasky int err; 831213848Shselasky 832213848Shselasky dev = libusb_get_device(pdev); 833213848Shselasky if (dev == NULL) 834213848Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 835213848Shselasky 836213848Shselasky err = libusb20_dev_check_connected(pdev); 837213848Shselasky 838213848Shselasky return (err ? LIBUSB_ERROR_NO_DEVICE : 0); 839213848Shselasky} 840213848Shselasky 841213848Shselaskyint 842195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface) 843194676Sthompsa{ 844195957Salfred if (pdev == NULL) 845194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 846194676Sthompsa 847226220Shselasky if (libusb20_dev_kernel_driver_active(pdev, interface)) 848226220Shselasky return (0); /* no kernel driver is active */ 849226220Shselasky else 850226220Shselasky return (1); /* kernel driver is active */ 851194676Sthompsa} 852194676Sthompsa 853194676Sthompsaint 854213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface, 855213853Shselasky char *name, int namelen) 856213853Shselasky{ 857213853Shselasky return (libusb_get_driver(pdev, interface, name, namelen)); 858213853Shselasky} 859213853Shselasky 860213853Shselaskyint 861213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface, 862213853Shselasky char *name, int namelen) 863213853Shselasky{ 864213853Shselasky char *ptr; 865213853Shselasky int err; 866213853Shselasky 867213853Shselasky if (pdev == NULL) 868213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 869213853Shselasky if (namelen < 1) 870213853Shselasky return (LIBUSB_ERROR_INVALID_PARAM); 871224085Shselasky if (namelen > 255) 872224085Shselasky namelen = 255; 873213853Shselasky 874213853Shselasky err = libusb20_dev_get_iface_desc( 875213853Shselasky pdev, interface, name, namelen); 876213853Shselasky 877213853Shselasky if (err != 0) 878213853Shselasky return (LIBUSB_ERROR_OTHER); 879213853Shselasky 880213853Shselasky /* we only want the driver name */ 881213853Shselasky ptr = strstr(name, ":"); 882213853Shselasky if (ptr != NULL) 883213853Shselasky *ptr = 0; 884213853Shselasky 885213853Shselasky return (0); 886213853Shselasky} 887213853Shselasky 888213853Shselaskyint 889213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface) 890213853Shselasky{ 891213853Shselasky return (libusb_detach_kernel_driver(pdev, interface)); 892213853Shselasky} 893213853Shselasky 894213853Shselaskyint 895195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface) 896194676Sthompsa{ 897195957Salfred int err; 898194676Sthompsa 899195957Salfred if (pdev == NULL) 900194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 901194676Sthompsa 902195957Salfred err = libusb20_dev_detach_kernel_driver( 903195957Salfred pdev, interface); 904194676Sthompsa 905213853Shselasky return (err ? LIBUSB_ERROR_OTHER : 0); 906194676Sthompsa} 907194676Sthompsa 908194676Sthompsaint 909195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface) 910194676Sthompsa{ 911195957Salfred if (pdev == NULL) 912194676Sthompsa return (LIBUSB_ERROR_INVALID_PARAM); 913195957Salfred /* stub - currently not supported by libusb20 */ 914194676Sthompsa return (0); 915194676Sthompsa} 916194676Sthompsa 917302275Shselaskyint 918302275Shselaskylibusb_set_auto_detach_kernel_driver(libusb_device_handle *dev, int enable) 919302275Shselasky{ 920302275Shselasky dev->auto_detach = (enable ? 1 : 0); 921302275Shselasky return (0); 922302275Shselasky} 923302275Shselasky 924194676Sthompsa/* Asynchronous device I/O */ 925194676Sthompsa 926194676Sthompsastruct libusb_transfer * 927194676Sthompsalibusb_alloc_transfer(int iso_packets) 928194676Sthompsa{ 929195957Salfred struct libusb_transfer *uxfer; 930195957Salfred struct libusb_super_transfer *sxfer; 931194676Sthompsa int len; 932194676Sthompsa 933194676Sthompsa len = sizeof(struct libusb_transfer) + 934195957Salfred sizeof(struct libusb_super_transfer) + 935194676Sthompsa (iso_packets * sizeof(libusb_iso_packet_descriptor)); 936194676Sthompsa 937195957Salfred sxfer = malloc(len); 938195957Salfred if (sxfer == NULL) 939194676Sthompsa return (NULL); 940194676Sthompsa 941195957Salfred memset(sxfer, 0, len); 942194676Sthompsa 943195957Salfred uxfer = (struct libusb_transfer *)( 944195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 945194676Sthompsa 946195957Salfred /* set default value */ 947195957Salfred uxfer->num_iso_packets = iso_packets; 948195957Salfred 949195957Salfred return (uxfer); 950194676Sthompsa} 951194676Sthompsa 952194676Sthompsavoid 953195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer) 954194676Sthompsa{ 955195957Salfred struct libusb_super_transfer *sxfer; 956194676Sthompsa 957195957Salfred if (uxfer == NULL) 958195957Salfred return; /* be NULL safe */ 959194676Sthompsa 960215253Shselasky /* check if we should free the transfer buffer */ 961215253Shselasky if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) 962215253Shselasky free(uxfer->buffer); 963215253Shselasky 964195957Salfred sxfer = (struct libusb_super_transfer *)( 965195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 966194676Sthompsa 967195957Salfred free(sxfer); 968194676Sthompsa} 969194676Sthompsa 970219100Shselaskystatic uint32_t 971195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 972195560Sthompsa{ 973219100Shselasky uint32_t ret; 974195560Sthompsa 975195560Sthompsa switch (xfer->type) { 976195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 977219100Shselasky ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE; /* 60ms */ 978195957Salfred break; 979195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 980195560Sthompsa ret = 2; 981195957Salfred break; 982195560Sthompsa default: 983195560Sthompsa ret = 1; 984195957Salfred break; 985195560Sthompsa } 986195957Salfred return (ret); 987195560Sthompsa} 988195560Sthompsa 989195560Sthompsastatic int 990195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 991195560Sthompsa{ 992195560Sthompsa int ret; 993195560Sthompsa int usb_speed; 994195560Sthompsa 995195560Sthompsa usb_speed = libusb20_dev_get_speed(pdev); 996195560Sthompsa 997195560Sthompsa switch (xfer->type) { 998195560Sthompsa case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 999195957Salfred ret = 0; /* kernel will auto-select */ 1000195957Salfred break; 1001195560Sthompsa case LIBUSB_TRANSFER_TYPE_CONTROL: 1002195957Salfred ret = 1024; 1003195957Salfred break; 1004195957Salfred default: 1005195560Sthompsa switch (usb_speed) { 1006195957Salfred case LIBUSB20_SPEED_LOW: 1007195957Salfred ret = 256; 1008195957Salfred break; 1009195957Salfred case LIBUSB20_SPEED_FULL: 1010195957Salfred ret = 4096; 1011195957Salfred break; 1012264641Shselasky case LIBUSB20_SPEED_SUPER: 1013264641Shselasky ret = 65536; 1014264641Shselasky break; 1015195957Salfred default: 1016195957Salfred ret = 16384; 1017195957Salfred break; 1018195560Sthompsa } 1019195957Salfred break; 1020195560Sthompsa } 1021195957Salfred return (ret); 1022195560Sthompsa} 1023195560Sthompsa 1024195957Salfredstatic int 1025195957Salfredlibusb10_convert_error(uint8_t status) 1026195957Salfred{ 1027195957Salfred ; /* indent fix */ 1028195957Salfred 1029195957Salfred switch (status) { 1030195957Salfred case LIBUSB20_TRANSFER_START: 1031195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1032195957Salfred return (LIBUSB_TRANSFER_COMPLETED); 1033195957Salfred case LIBUSB20_TRANSFER_OVERFLOW: 1034195957Salfred return (LIBUSB_TRANSFER_OVERFLOW); 1035195957Salfred case LIBUSB20_TRANSFER_NO_DEVICE: 1036195957Salfred return (LIBUSB_TRANSFER_NO_DEVICE); 1037195957Salfred case LIBUSB20_TRANSFER_STALL: 1038195957Salfred return (LIBUSB_TRANSFER_STALL); 1039195957Salfred case LIBUSB20_TRANSFER_CANCELLED: 1040195957Salfred return (LIBUSB_TRANSFER_CANCELLED); 1041195957Salfred case LIBUSB20_TRANSFER_TIMED_OUT: 1042195957Salfred return (LIBUSB_TRANSFER_TIMED_OUT); 1043195957Salfred default: 1044195957Salfred return (LIBUSB_TRANSFER_ERROR); 1045195957Salfred } 1046195957Salfred} 1047195957Salfred 1048195957Salfred/* This function must be called locked */ 1049195957Salfred 1050194676Sthompsastatic void 1051195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer, 1052195957Salfred struct libusb_super_transfer *sxfer, int status) 1053194676Sthompsa{ 1054195957Salfred struct libusb_transfer *uxfer; 1055195957Salfred struct libusb_device *dev; 1056195957Salfred 1057195957Salfred uxfer = (struct libusb_transfer *)( 1058195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1059195957Salfred 1060195957Salfred if (pxfer != NULL) 1061195957Salfred libusb20_tr_set_priv_sc1(pxfer, NULL); 1062195957Salfred 1063199575Sthompsa /* set transfer status */ 1064195957Salfred uxfer->status = status; 1065195957Salfred 1066199575Sthompsa /* update super transfer state */ 1067199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_NONE; 1068199575Sthompsa 1069195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1070195957Salfred 1071195957Salfred TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); 1072195957Salfred} 1073195957Salfred 1074195957Salfred/* This function must be called locked */ 1075195957Salfred 1076195957Salfredstatic void 1077195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer) 1078195957Salfred{ 1079195957Salfred struct libusb_super_transfer *sxfer; 1080195957Salfred struct libusb_transfer *uxfer; 1081195957Salfred uint32_t actlen; 1082195957Salfred uint16_t iso_packets; 1083195957Salfred uint16_t i; 1084194676Sthompsa uint8_t status; 1085195957Salfred uint8_t flags; 1086194676Sthompsa 1087195957Salfred status = libusb20_tr_get_status(pxfer); 1088195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1089195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1090195957Salfred iso_packets = libusb20_tr_get_max_frames(pxfer); 1091194676Sthompsa 1092195957Salfred if (sxfer == NULL) 1093195957Salfred return; /* cancelled - nothing to do */ 1094195957Salfred 1095195957Salfred uxfer = (struct libusb_transfer *)( 1096195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1097195957Salfred 1098195957Salfred if (iso_packets > uxfer->num_iso_packets) 1099195957Salfred iso_packets = uxfer->num_iso_packets; 1100195957Salfred 1101195957Salfred if (iso_packets == 0) 1102195957Salfred return; /* nothing to do */ 1103195957Salfred 1104195957Salfred /* make sure that the number of ISOCHRONOUS packets is valid */ 1105195957Salfred uxfer->num_iso_packets = iso_packets; 1106195957Salfred 1107195957Salfred flags = uxfer->flags; 1108195957Salfred 1109194676Sthompsa switch (status) { 1110194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1111195560Sthompsa 1112195957Salfred /* update actual length */ 1113195957Salfred uxfer->actual_length = actlen; 1114195957Salfred for (i = 0; i != iso_packets; i++) { 1115195957Salfred uxfer->iso_packet_desc[i].actual_length = 1116195957Salfred libusb20_tr_get_length(pxfer, i); 1117195957Salfred } 1118195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1119195957Salfred break; 1120195560Sthompsa 1121194676Sthompsa case LIBUSB20_TRANSFER_START: 1122195957Salfred 1123195957Salfred /* setup length(s) */ 1124195957Salfred actlen = 0; 1125195957Salfred for (i = 0; i != iso_packets; i++) { 1126195957Salfred libusb20_tr_setup_isoc(pxfer, 1127195957Salfred &uxfer->buffer[actlen], 1128195957Salfred uxfer->iso_packet_desc[i].length, i); 1129195957Salfred actlen += uxfer->iso_packet_desc[i].length; 1130194676Sthompsa } 1131195957Salfred 1132195957Salfred /* no remainder */ 1133195957Salfred sxfer->rem_len = 0; 1134195957Salfred 1135195957Salfred libusb20_tr_set_total_frames(pxfer, iso_packets); 1136195957Salfred libusb20_tr_submit(pxfer); 1137195957Salfred 1138195957Salfred /* fork another USB transfer, if any */ 1139195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1140195957Salfred break; 1141195957Salfred 1142194676Sthompsa default: 1143195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1144195957Salfred break; 1145194676Sthompsa } 1146195957Salfred} 1147194676Sthompsa 1148195957Salfred/* This function must be called locked */ 1149195957Salfred 1150195957Salfredstatic void 1151195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) 1152195957Salfred{ 1153195957Salfred struct libusb_super_transfer *sxfer; 1154195957Salfred struct libusb_transfer *uxfer; 1155195957Salfred uint32_t max_bulk; 1156195957Salfred uint32_t actlen; 1157195957Salfred uint8_t status; 1158195957Salfred uint8_t flags; 1159195957Salfred 1160195957Salfred status = libusb20_tr_get_status(pxfer); 1161195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1162195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1163195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1164195957Salfred 1165195957Salfred if (sxfer == NULL) 1166195957Salfred return; /* cancelled - nothing to do */ 1167195957Salfred 1168195957Salfred uxfer = (struct libusb_transfer *)( 1169195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1170195957Salfred 1171195957Salfred flags = uxfer->flags; 1172195957Salfred 1173194676Sthompsa switch (status) { 1174194676Sthompsa case LIBUSB20_TRANSFER_COMPLETED: 1175195957Salfred 1176195957Salfred uxfer->actual_length += actlen; 1177195957Salfred 1178195957Salfred /* check for short packet */ 1179195957Salfred if (sxfer->last_len != actlen) { 1180195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1181195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1182195957Salfred } else { 1183195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1184195957Salfred } 1185195957Salfred break; 1186195957Salfred } 1187195957Salfred /* check for end of data */ 1188195957Salfred if (sxfer->rem_len == 0) { 1189195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1190195957Salfred break; 1191195957Salfred } 1192195957Salfred /* FALLTHROUGH */ 1193195957Salfred 1194195957Salfred case LIBUSB20_TRANSFER_START: 1195195957Salfred if (max_bulk > sxfer->rem_len) { 1196195957Salfred max_bulk = sxfer->rem_len; 1197195957Salfred } 1198195957Salfred /* setup new BULK or INTERRUPT transaction */ 1199195957Salfred libusb20_tr_setup_bulk(pxfer, 1200195957Salfred sxfer->curr_data, max_bulk, uxfer->timeout); 1201195957Salfred 1202195957Salfred /* update counters */ 1203195957Salfred sxfer->last_len = max_bulk; 1204195957Salfred sxfer->curr_data += max_bulk; 1205195957Salfred sxfer->rem_len -= max_bulk; 1206195957Salfred 1207195957Salfred libusb20_tr_submit(pxfer); 1208195957Salfred 1209195957Salfred /* check if we can fork another USB transfer */ 1210195957Salfred if (sxfer->rem_len == 0) 1211195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1212195957Salfred break; 1213195957Salfred 1214195957Salfred default: 1215195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1216195957Salfred break; 1217194676Sthompsa } 1218194676Sthompsa} 1219194676Sthompsa 1220195957Salfred/* This function must be called locked */ 1221195957Salfred 1222195957Salfredstatic void 1223195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer) 1224194676Sthompsa{ 1225195957Salfred struct libusb_super_transfer *sxfer; 1226195957Salfred struct libusb_transfer *uxfer; 1227195957Salfred uint32_t max_bulk; 1228195957Salfred uint32_t actlen; 1229195957Salfred uint8_t status; 1230195957Salfred uint8_t flags; 1231194676Sthompsa 1232195957Salfred status = libusb20_tr_get_status(pxfer); 1233195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer); 1234195957Salfred max_bulk = libusb20_tr_get_max_total_length(pxfer); 1235195957Salfred actlen = libusb20_tr_get_actual_length(pxfer); 1236194676Sthompsa 1237195957Salfred if (sxfer == NULL) 1238195957Salfred return; /* cancelled - nothing to do */ 1239194676Sthompsa 1240195957Salfred uxfer = (struct libusb_transfer *)( 1241195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1242194676Sthompsa 1243195957Salfred flags = uxfer->flags; 1244194676Sthompsa 1245195957Salfred switch (status) { 1246195957Salfred case LIBUSB20_TRANSFER_COMPLETED: 1247194676Sthompsa 1248195957Salfred uxfer->actual_length += actlen; 1249195957Salfred 1250195957Salfred /* subtract length of SETUP packet, if any */ 1251195957Salfred actlen -= libusb20_tr_get_length(pxfer, 0); 1252195957Salfred 1253195957Salfred /* check for short packet */ 1254195957Salfred if (sxfer->last_len != actlen) { 1255195957Salfred if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { 1256195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); 1257195957Salfred } else { 1258195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1259195957Salfred } 1260195957Salfred break; 1261194676Sthompsa } 1262195957Salfred /* check for end of data */ 1263195957Salfred if (sxfer->rem_len == 0) { 1264195957Salfred libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); 1265195957Salfred break; 1266195957Salfred } 1267195957Salfred /* FALLTHROUGH */ 1268194676Sthompsa 1269195957Salfred case LIBUSB20_TRANSFER_START: 1270195957Salfred if (max_bulk > sxfer->rem_len) { 1271195957Salfred max_bulk = sxfer->rem_len; 1272195957Salfred } 1273195957Salfred /* setup new CONTROL transaction */ 1274195957Salfred if (status == LIBUSB20_TRANSFER_COMPLETED) { 1275195957Salfred /* next fragment - don't send SETUP packet */ 1276195957Salfred libusb20_tr_set_length(pxfer, 0, 0); 1277195957Salfred } else { 1278195957Salfred /* first fragment - send SETUP packet */ 1279195957Salfred libusb20_tr_set_length(pxfer, 8, 0); 1280195957Salfred libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0); 1281195957Salfred } 1282195957Salfred 1283195957Salfred if (max_bulk != 0) { 1284195957Salfred libusb20_tr_set_length(pxfer, max_bulk, 1); 1285195957Salfred libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1); 1286195957Salfred libusb20_tr_set_total_frames(pxfer, 2); 1287195957Salfred } else { 1288195957Salfred libusb20_tr_set_total_frames(pxfer, 1); 1289195957Salfred } 1290195957Salfred 1291195957Salfred /* update counters */ 1292195957Salfred sxfer->last_len = max_bulk; 1293195957Salfred sxfer->curr_data += max_bulk; 1294195957Salfred sxfer->rem_len -= max_bulk; 1295195957Salfred 1296195957Salfred libusb20_tr_submit(pxfer); 1297195957Salfred 1298195957Salfred /* check if we can fork another USB transfer */ 1299195957Salfred if (sxfer->rem_len == 0) 1300195957Salfred libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint); 1301195957Salfred break; 1302195957Salfred 1303195957Salfred default: 1304195957Salfred libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); 1305195957Salfred break; 1306194676Sthompsa } 1307195957Salfred} 1308195957Salfred 1309195957Salfred/* The following function must be called locked */ 1310195957Salfred 1311195957Salfredstatic void 1312195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint) 1313195957Salfred{ 1314195957Salfred struct libusb20_transfer *pxfer0; 1315195957Salfred struct libusb20_transfer *pxfer1; 1316195957Salfred struct libusb_super_transfer *sxfer; 1317195957Salfred struct libusb_transfer *uxfer; 1318195957Salfred struct libusb_device *dev; 1319195957Salfred int err; 1320195957Salfred int buffsize; 1321195957Salfred int maxframe; 1322195957Salfred int temp; 1323195957Salfred 1324195957Salfred dev = libusb_get_device(pdev); 1325195957Salfred 1326195957Salfred pxfer0 = libusb10_get_transfer(pdev, endpoint, 0); 1327195957Salfred pxfer1 = libusb10_get_transfer(pdev, endpoint, 1); 1328195957Salfred 1329195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) 1330195957Salfred return; /* shouldn't happen */ 1331195957Salfred 1332195957Salfred temp = 0; 1333195957Salfred if (libusb20_tr_pending(pxfer0)) 1334195957Salfred temp |= 1; 1335195957Salfred if (libusb20_tr_pending(pxfer1)) 1336195957Salfred temp |= 2; 1337195957Salfred 1338195957Salfred switch (temp) { 1339195957Salfred case 3: 1340195957Salfred /* wait till one of the transfers complete */ 1341195957Salfred return; 1342195957Salfred case 2: 1343195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer1); 1344199575Sthompsa if (sxfer == NULL) 1345199575Sthompsa return; /* cancelling */ 1346195957Salfred if (sxfer->rem_len) 1347195957Salfred return; /* cannot queue another one */ 1348195957Salfred /* swap transfers */ 1349195957Salfred pxfer1 = pxfer0; 1350195957Salfred break; 1351195957Salfred case 1: 1352195957Salfred sxfer = libusb20_tr_get_priv_sc1(pxfer0); 1353199575Sthompsa if (sxfer == NULL) 1354199575Sthompsa return; /* cancelling */ 1355195957Salfred if (sxfer->rem_len) 1356195957Salfred return; /* cannot queue another one */ 1357195957Salfred /* swap transfers */ 1358195957Salfred pxfer0 = pxfer1; 1359195957Salfred break; 1360195957Salfred default: 1361195957Salfred break; 1362194676Sthompsa } 1363195957Salfred 1364195957Salfred /* find next transfer on same endpoint */ 1365195957Salfred TAILQ_FOREACH(sxfer, &dev->tr_head, entry) { 1366195957Salfred 1367195957Salfred uxfer = (struct libusb_transfer *)( 1368195957Salfred ((uint8_t *)sxfer) + sizeof(*sxfer)); 1369195957Salfred 1370195957Salfred if (uxfer->endpoint == endpoint) { 1371195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1372195957Salfred sxfer->entry.tqe_prev = NULL; 1373195957Salfred goto found; 1374194676Sthompsa } 1375195957Salfred } 1376195957Salfred return; /* success */ 1377194676Sthompsa 1378195957Salfredfound: 1379194676Sthompsa 1380195957Salfred libusb20_tr_set_priv_sc0(pxfer0, pdev); 1381195957Salfred libusb20_tr_set_priv_sc1(pxfer0, sxfer); 1382194676Sthompsa 1383195957Salfred /* reset super transfer state */ 1384195957Salfred sxfer->rem_len = uxfer->length; 1385195957Salfred sxfer->curr_data = uxfer->buffer; 1386195957Salfred uxfer->actual_length = 0; 1387194676Sthompsa 1388195957Salfred switch (uxfer->type) { 1389195957Salfred case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 1390195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); 1391195957Salfred break; 1392195957Salfred case LIBUSB_TRANSFER_TYPE_BULK: 1393195957Salfred case LIBUSB_TRANSFER_TYPE_INTERRUPT: 1394195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); 1395195957Salfred break; 1396195957Salfred case LIBUSB_TRANSFER_TYPE_CONTROL: 1397195957Salfred libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); 1398195957Salfred if (sxfer->rem_len < 8) 1399195957Salfred goto failure; 1400194676Sthompsa 1401195957Salfred /* remove SETUP packet from data */ 1402195957Salfred sxfer->rem_len -= 8; 1403195957Salfred sxfer->curr_data += 8; 1404195957Salfred break; 1405195957Salfred default: 1406195957Salfred goto failure; 1407195560Sthompsa } 1408195957Salfred 1409195957Salfred buffsize = libusb10_get_buffsize(pdev, uxfer); 1410195957Salfred maxframe = libusb10_get_maxframe(pdev, uxfer); 1411195957Salfred 1412195957Salfred /* make sure the transfer is opened */ 1413302275Shselasky err = libusb20_tr_open_stream(pxfer0, buffsize, maxframe, 1414302275Shselasky endpoint, sxfer->stream_id); 1415195957Salfred if (err && (err != LIBUSB20_ERROR_BUSY)) { 1416195957Salfred goto failure; 1417194676Sthompsa } 1418195957Salfred libusb20_tr_start(pxfer0); 1419195957Salfred return; 1420194676Sthompsa 1421195957Salfredfailure: 1422195957Salfred libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); 1423195957Salfred /* make sure our event loop spins the done handler */ 1424338789Shselasky libusb10_wakeup_event_loop(dev->ctx); 1425195957Salfred} 1426194676Sthompsa 1427195957Salfred/* The following function must be called unlocked */ 1428194676Sthompsa 1429195957Salfredint 1430195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer) 1431195957Salfred{ 1432195957Salfred struct libusb20_transfer *pxfer0; 1433195957Salfred struct libusb20_transfer *pxfer1; 1434195957Salfred struct libusb_super_transfer *sxfer; 1435195957Salfred struct libusb_device *dev; 1436234684Shselasky uint8_t endpoint; 1437195957Salfred int err; 1438195957Salfred 1439195957Salfred if (uxfer == NULL) 1440195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1441195957Salfred 1442195957Salfred if (uxfer->dev_handle == NULL) 1443195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1444195957Salfred 1445195957Salfred endpoint = uxfer->endpoint; 1446195957Salfred 1447195957Salfred dev = libusb_get_device(uxfer->dev_handle); 1448195957Salfred 1449195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); 1450195957Salfred 1451195957Salfred sxfer = (struct libusb_super_transfer *)( 1452195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1453195957Salfred 1454195957Salfred CTX_LOCK(dev->ctx); 1455195957Salfred 1456195957Salfred pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); 1457195957Salfred pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); 1458195957Salfred 1459195957Salfred if (pxfer0 == NULL || pxfer1 == NULL) { 1460195957Salfred err = LIBUSB_ERROR_OTHER; 1461195957Salfred } else if ((sxfer->entry.tqe_prev != NULL) || 1462199575Sthompsa (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) || 1463195957Salfred (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) { 1464195957Salfred err = LIBUSB_ERROR_BUSY; 1465338789Shselasky } else if (dev->device_is_gone != 0) { 1466338789Shselasky err = LIBUSB_ERROR_NO_DEVICE; 1467195957Salfred } else { 1468199575Sthompsa 1469199575Sthompsa /* set pending state */ 1470199575Sthompsa sxfer->state = LIBUSB_SUPER_XFER_ST_PEND; 1471199575Sthompsa 1472199575Sthompsa /* insert transfer into transfer head list */ 1473195957Salfred TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry); 1474195957Salfred 1475199575Sthompsa /* start work transfers */ 1476195957Salfred libusb10_submit_transfer_sub( 1477195957Salfred uxfer->dev_handle, endpoint); 1478195957Salfred 1479195957Salfred err = 0; /* success */ 1480195957Salfred } 1481195957Salfred 1482195957Salfred CTX_UNLOCK(dev->ctx); 1483195957Salfred 1484195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); 1485195957Salfred 1486195957Salfred return (err); 1487194676Sthompsa} 1488194676Sthompsa 1489195957Salfred/* Asynchronous transfer cancel */ 1490195957Salfred 1491194676Sthompsaint 1492195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer) 1493194676Sthompsa{ 1494195957Salfred struct libusb20_transfer *pxfer0; 1495195957Salfred struct libusb20_transfer *pxfer1; 1496195957Salfred struct libusb_super_transfer *sxfer; 1497195957Salfred struct libusb_device *dev; 1498338789Shselasky struct libusb_device_handle *devh; 1499234684Shselasky uint8_t endpoint; 1500199575Sthompsa int retval; 1501194676Sthompsa 1502195957Salfred if (uxfer == NULL) 1503195957Salfred return (LIBUSB_ERROR_INVALID_PARAM); 1504194676Sthompsa 1505199575Sthompsa /* check if not initialised */ 1506338789Shselasky if ((devh = uxfer->dev_handle) == NULL) 1507199575Sthompsa return (LIBUSB_ERROR_NOT_FOUND); 1508194676Sthompsa 1509195957Salfred endpoint = uxfer->endpoint; 1510194676Sthompsa 1511338789Shselasky dev = libusb_get_device(devh); 1512195957Salfred 1513195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); 1514195957Salfred 1515195957Salfred sxfer = (struct libusb_super_transfer *)( 1516195957Salfred (uint8_t *)uxfer - sizeof(*sxfer)); 1517195957Salfred 1518199575Sthompsa retval = 0; 1519199575Sthompsa 1520195957Salfred CTX_LOCK(dev->ctx); 1521195957Salfred 1522338789Shselasky pxfer0 = libusb10_get_transfer(devh, endpoint, 0); 1523338789Shselasky pxfer1 = libusb10_get_transfer(devh, endpoint, 1); 1524195957Salfred 1525199575Sthompsa if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { 1526199575Sthompsa /* only update the transfer status */ 1527199575Sthompsa uxfer->status = LIBUSB_TRANSFER_CANCELLED; 1528199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1529199575Sthompsa } else if (sxfer->entry.tqe_prev != NULL) { 1530195957Salfred /* we are lucky - transfer is on a queue */ 1531195957Salfred TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1532195957Salfred sxfer->entry.tqe_prev = NULL; 1533199575Sthompsa libusb10_complete_transfer(NULL, 1534199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1535338789Shselasky /* make sure our event loop spins the done handler */ 1536338789Shselasky libusb10_wakeup_event_loop(dev->ctx); 1537195957Salfred } else if (pxfer0 == NULL || pxfer1 == NULL) { 1538195957Salfred /* not started */ 1539199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1540195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { 1541199575Sthompsa libusb10_complete_transfer(pxfer0, 1542199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1543338789Shselasky if (dev->device_is_gone != 0) { 1544338789Shselasky /* clear transfer pointer */ 1545338789Shselasky libusb20_tr_set_priv_sc1(pxfer0, NULL); 1546338789Shselasky /* make sure our event loop spins the done handler */ 1547338789Shselasky libusb10_wakeup_event_loop(dev->ctx); 1548338789Shselasky } else { 1549338789Shselasky libusb20_tr_stop(pxfer0); 1550338789Shselasky /* make sure the queue doesn't stall */ 1551338789Shselasky libusb10_submit_transfer_sub(devh, endpoint); 1552338789Shselasky } 1553195957Salfred } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { 1554199575Sthompsa libusb10_complete_transfer(pxfer1, 1555199575Sthompsa sxfer, LIBUSB_TRANSFER_CANCELLED); 1556338789Shselasky /* check if handle is still active */ 1557338789Shselasky if (dev->device_is_gone != 0) { 1558338789Shselasky /* clear transfer pointer */ 1559338789Shselasky libusb20_tr_set_priv_sc1(pxfer1, NULL); 1560338789Shselasky /* make sure our event loop spins the done handler */ 1561338789Shselasky libusb10_wakeup_event_loop(dev->ctx); 1562338789Shselasky } else { 1563338789Shselasky libusb20_tr_stop(pxfer1); 1564338789Shselasky /* make sure the queue doesn't stall */ 1565338789Shselasky libusb10_submit_transfer_sub(devh, endpoint); 1566338789Shselasky } 1567195957Salfred } else { 1568195957Salfred /* not started */ 1569199575Sthompsa retval = LIBUSB_ERROR_NOT_FOUND; 1570195957Salfred } 1571195957Salfred 1572195957Salfred CTX_UNLOCK(dev->ctx); 1573195957Salfred 1574195957Salfred DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); 1575195957Salfred 1576199575Sthompsa return (retval); 1577194676Sthompsa} 1578194676Sthompsa 1579195957SalfredUNEXPORTED void 1580195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev) 1581195957Salfred{ 1582302272Shselasky struct libusb20_device *pdev = dev->os_priv; 1583302272Shselasky unsigned x; 1584302272Shselasky 1585302272Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1586302272Shselasky struct libusb20_transfer *xfer; 1587302272Shselasky 1588302272Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1589302272Shselasky if (xfer == NULL) 1590302272Shselasky continue; 1591302272Shselasky libusb20_tr_close(xfer); 1592302272Shselasky } 1593195957Salfred} 1594199055Sthompsa 1595338789ShselaskyUNEXPORTED void 1596338789Shselaskylibusb10_cancel_all_transfer_locked(struct libusb20_device *pdev, struct libusb_device *dev) 1597338789Shselasky{ 1598338789Shselasky struct libusb_super_transfer *sxfer; 1599338789Shselasky unsigned x; 1600338789Shselasky 1601338789Shselasky for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) { 1602338789Shselasky struct libusb20_transfer *xfer; 1603338789Shselasky 1604338789Shselasky xfer = libusb20_tr_get_pointer(pdev, x); 1605338789Shselasky if (xfer == NULL) 1606338789Shselasky continue; 1607338789Shselasky if (libusb20_tr_pending(xfer) == 0) 1608338789Shselasky continue; 1609338789Shselasky sxfer = libusb20_tr_get_priv_sc1(xfer); 1610338789Shselasky if (sxfer == NULL) 1611338789Shselasky continue; 1612338789Shselasky /* complete pending transfer */ 1613338789Shselasky libusb10_complete_transfer(xfer, sxfer, LIBUSB_TRANSFER_ERROR); 1614338789Shselasky } 1615338789Shselasky 1616338789Shselasky while ((sxfer = TAILQ_FIRST(&dev->tr_head))) { 1617338789Shselasky TAILQ_REMOVE(&dev->tr_head, sxfer, entry); 1618338789Shselasky 1619338789Shselasky /* complete pending transfer */ 1620338789Shselasky libusb10_complete_transfer(NULL, sxfer, LIBUSB_TRANSFER_ERROR); 1621338789Shselasky } 1622338789Shselasky} 1623338789Shselasky 1624199055Sthompsauint16_t 1625199055Sthompsalibusb_cpu_to_le16(uint16_t x) 1626199055Sthompsa{ 1627199055Sthompsa return (htole16(x)); 1628199055Sthompsa} 1629199055Sthompsa 1630199055Sthompsauint16_t 1631199055Sthompsalibusb_le16_to_cpu(uint16_t x) 1632199055Sthompsa{ 1633199055Sthompsa return (le16toh(x)); 1634199055Sthompsa} 1635199055Sthompsa 1636213853Shselaskyconst char * 1637213853Shselaskylibusb_strerror(int code) 1638213853Shselasky{ 1639225659Shselasky switch (code) { 1640225659Shselasky case LIBUSB_SUCCESS: 1641225659Shselasky return ("Success"); 1642225659Shselasky case LIBUSB_ERROR_IO: 1643225659Shselasky return ("I/O error"); 1644225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1645225659Shselasky return ("Invalid parameter"); 1646225659Shselasky case LIBUSB_ERROR_ACCESS: 1647225659Shselasky return ("Permissions error"); 1648225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1649225659Shselasky return ("No device"); 1650225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1651225659Shselasky return ("Not found"); 1652225659Shselasky case LIBUSB_ERROR_BUSY: 1653225659Shselasky return ("Device busy"); 1654225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1655225659Shselasky return ("Timeout"); 1656225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1657225659Shselasky return ("Overflow"); 1658225659Shselasky case LIBUSB_ERROR_PIPE: 1659225659Shselasky return ("Pipe error"); 1660225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1661225659Shselasky return ("Interrupted"); 1662225659Shselasky case LIBUSB_ERROR_NO_MEM: 1663225659Shselasky return ("Out of memory"); 1664225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1665225659Shselasky return ("Not supported"); 1666225659Shselasky case LIBUSB_ERROR_OTHER: 1667225659Shselasky return ("Other error"); 1668225659Shselasky default: 1669225659Shselasky return ("Unknown error"); 1670225659Shselasky } 1671213853Shselasky} 1672225659Shselasky 1673225659Shselaskyconst char * 1674225659Shselaskylibusb_error_name(int code) 1675225659Shselasky{ 1676225659Shselasky switch (code) { 1677225659Shselasky case LIBUSB_SUCCESS: 1678225659Shselasky return ("LIBUSB_SUCCESS"); 1679225659Shselasky case LIBUSB_ERROR_IO: 1680225659Shselasky return ("LIBUSB_ERROR_IO"); 1681225659Shselasky case LIBUSB_ERROR_INVALID_PARAM: 1682225659Shselasky return ("LIBUSB_ERROR_INVALID_PARAM"); 1683225659Shselasky case LIBUSB_ERROR_ACCESS: 1684225659Shselasky return ("LIBUSB_ERROR_ACCESS"); 1685225659Shselasky case LIBUSB_ERROR_NO_DEVICE: 1686225659Shselasky return ("LIBUSB_ERROR_NO_DEVICE"); 1687225659Shselasky case LIBUSB_ERROR_NOT_FOUND: 1688225659Shselasky return ("LIBUSB_ERROR_NOT_FOUND"); 1689225659Shselasky case LIBUSB_ERROR_BUSY: 1690225659Shselasky return ("LIBUSB_ERROR_BUSY"); 1691225659Shselasky case LIBUSB_ERROR_TIMEOUT: 1692225659Shselasky return ("LIBUSB_ERROR_TIMEOUT"); 1693225659Shselasky case LIBUSB_ERROR_OVERFLOW: 1694225659Shselasky return ("LIBUSB_ERROR_OVERFLOW"); 1695225659Shselasky case LIBUSB_ERROR_PIPE: 1696225659Shselasky return ("LIBUSB_ERROR_PIPE"); 1697225659Shselasky case LIBUSB_ERROR_INTERRUPTED: 1698225659Shselasky return ("LIBUSB_ERROR_INTERRUPTED"); 1699225659Shselasky case LIBUSB_ERROR_NO_MEM: 1700225659Shselasky return ("LIBUSB_ERROR_NO_MEM"); 1701225659Shselasky case LIBUSB_ERROR_NOT_SUPPORTED: 1702225659Shselasky return ("LIBUSB_ERROR_NOT_SUPPORTED"); 1703225659Shselasky case LIBUSB_ERROR_OTHER: 1704225659Shselasky return ("LIBUSB_ERROR_OTHER"); 1705225659Shselasky default: 1706225659Shselasky return ("LIBUSB_ERROR_UNKNOWN"); 1707225659Shselasky } 1708225659Shselasky} 1709362224Skevans 1710362224Skevansint 1711362224Skevanslibusb_has_capability(uint32_t capability) 1712362224Skevans{ 1713362224Skevans 1714362224Skevans switch (capability) { 1715362224Skevans case LIBUSB_CAP_HAS_CAPABILITY: 1716362224Skevans case LIBUSB_CAP_HAS_HOTPLUG: 1717362224Skevans case LIBUSB_CAP_HAS_HID_ACCESS: 1718362224Skevans case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: 1719362224Skevans return (1); 1720362224Skevans default: 1721362224Skevans return (0); 1722362224Skevans } 1723362224Skevans} 1724