1a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/* 2a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * Core functions for libusb-compat-0.1 3a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org> 4a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com> 5a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 6a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * This library is free software; you can redistribute it and/or 7a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * modify it under the terms of the GNU Lesser General Public 8a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * License as published by the Free Software Foundation; either 9a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * version 2.1 of the License, or (at your option) any later version. 10a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 11a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * This library is distributed in the hope that it will be useful, 12a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * but WITHOUT ANY WARRANTY; without even the implied warranty of 13a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * Lesser General Public License for more details. 15a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 16a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * You should have received a copy of the GNU Lesser General Public 17a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * License along with this library; if not, write to the Free Software 18a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor */ 20a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 21a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <config.h> 22a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <errno.h> 23a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <stdarg.h> 24a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <stdio.h> 25a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <string.h> 265100135ecf29d4246e6bd34318da9eb22c16b86aDouglas Gregor 27a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <libusb.h> 28a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 298229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include "usb.h" 301d32133b44487d9e98412e373d693416b05920bbNAKAMURA Takumi#include "usbi.h" 31a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 32a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic libusb_context *ctx = NULL; 33a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int usb_debug = 0; 34a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 35a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorenum usbi_log_level { 36a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LOG_LEVEL_DEBUG, 37a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LOG_LEVEL_INFO, 38a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LOG_LEVEL_WARNING, 39a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LOG_LEVEL_ERROR, 40a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor}; 41a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 42a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#ifdef ENABLE_LOGGING 43a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define _usbi_log(level, fmt...) usbi_log(level, __FUNCTION__, fmt) 44a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#else 45a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define _usbi_log(level, fmt...) 46a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#endif 471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 48a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#ifdef ENABLE_DEBUG_LOGGING 49a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define usbi_dbg(fmt...) _usbi_log(LOG_LEVEL_DEBUG, fmt) 50a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#else 51a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define usbi_dbg(fmt...) 52a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#endif 53a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 54a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define usbi_info(fmt...) _usbi_log(LOG_LEVEL_INFO, fmt) 55a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define usbi_warn(fmt...) _usbi_log(LOG_LEVEL_WARNING, fmt) 56a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define usbi_err(fmt...) _usbi_log(LOG_LEVEL_ERROR, fmt) 57a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 58a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED struct usb_bus *usb_busses = NULL; 59a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 60a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define compat_err(e) -(errno=libusb_to_errno(e)) 61a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 621a49d97d762570027863e9209af81d445e4f1502Douglas Gregorstatic int libusb_to_errno(int result) 631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch (result) { 651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_SUCCESS: 661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return 0; 671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_IO: 681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EIO; 691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_INVALID_PARAM: 701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EINVAL; 711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_ACCESS: 721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EACCES; 731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_NO_DEVICE: 741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ENXIO; 751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_NOT_FOUND: 761a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ENOENT; 771a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_BUSY: 781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EBUSY; 791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_TIMEOUT: 801a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ETIMEDOUT; 811a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_OVERFLOW: 821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EOVERFLOW; 831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_PIPE: 841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EPIPE; 851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_INTERRUPTED: 861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return EINTR; 871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_NO_MEM: 881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ENOMEM; 891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LIBUSB_ERROR_NOT_SUPPORTED: 901a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ENOSYS; 911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor default: 921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return ERANGE; 931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 961a49d97d762570027863e9209af81d445e4f1502Douglas Gregorstatic void usbi_log(enum usbi_log_level level, const char *function, 971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor const char *format, ...) 981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor va_list args; 1001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor FILE *stream = stdout; 1011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor const char *prefix; 1021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#ifndef ENABLE_DEBUG_LOGGING 1041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!usb_debug) 1051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#endif 1071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch (level) { 1091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LOG_LEVEL_INFO: 1101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor prefix = "info"; 1111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1121a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LOG_LEVEL_WARNING: 1131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor stream = stderr; 1141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor prefix = "warning"; 1151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LOG_LEVEL_ERROR: 1171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor stream = stderr; 1181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor prefix = "error"; 1191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case LOG_LEVEL_DEBUG: 121677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor stream = stderr; 1221a49d97d762570027863e9209af81d445e4f1502Douglas Gregor prefix = "debug"; 123fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor break; 124188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor default: 1251a49d97d762570027863e9209af81d445e4f1502Douglas Gregor stream = stderr; 1261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor prefix = "unknown"; 1271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1281a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1291a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor fprintf(stream, "libusb-compat %s: %s: ", prefix, function); 1311a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1321a49d97d762570027863e9209af81d445e4f1502Douglas Gregor va_start (args, format); 1331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor vfprintf(stream, format, args); 1341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor va_end (args); 1351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor fprintf(stream, "\n"); 1371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1391a49d97d762570027863e9209af81d445e4f1502Douglas GregorAPI_EXPORTED void usb_init(void) 1401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 1411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor int r; 1421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_dbg(""); 1431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!ctx) { 1451a49d97d762570027863e9209af81d445e4f1502Douglas Gregor r = libusb_init(&ctx); 1461a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (r < 0) { 1471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_err("initialization failed!"); 1481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1501a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* usb_set_debug can be called before usb_init */ 1521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (usb_debug) 1531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_set_debug(ctx, 3); 1541a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1571a49d97d762570027863e9209af81d445e4f1502Douglas GregorAPI_EXPORTED void usb_set_debug(int level) 1581a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 1591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usb_debug = level; 1601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* usb_set_debug can be called before usb_init */ 1621a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (ctx) 1631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_set_debug(ctx, 3); 1641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1661a49d97d762570027863e9209af81d445e4f1502Douglas GregorAPI_EXPORTED char *usb_strerror(void) 1671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 1681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return strerror(errno); 1691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1711a49d97d762570027863e9209af81d445e4f1502Douglas Gregorstatic int find_busses(struct usb_bus **ret) 1721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 1731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_device **dev_list = NULL; 1741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *busses = NULL; 1751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *bus; 176677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor int dev_list_len = 0; 177677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor int i; 178677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor int r; 179677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 180677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor r = libusb_get_device_list(ctx, &dev_list); 181677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (r < 0) { 182677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor usbi_err("get_device_list failed with error %d", r); 183677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return compat_err(r); 184677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 185677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 186677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (r == 0) { 1871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_free_device_list(dev_list, 1); 1881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* no buses */ 1891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return 0; 190677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 191677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 1921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* iterate over the device list, identifying the individual busses. 1931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor * we use the location field of the usb_bus structure to store the 1941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor * bus number. */ 1951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 196677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor dev_list_len = r; 197677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor for (i = 0; i < dev_list_len; i++) { 198677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor libusb_device *dev = dev_list[i]; 199677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor uint8_t bus_num = libusb_get_bus_number(dev); 2001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 201677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor /* if we already know about it, continue */ 202677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (busses) { 203fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor bus = busses; 204fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor int found = 0; 205fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor do { 2061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (bus_num == bus->location) { 2071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor found = 1; 2081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } while ((bus = bus->next) != NULL); 2111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (found) 2121a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 2131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* add it to the list of busses */ 2161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus = malloc(sizeof(*bus)); 2171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!bus) 2181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor goto err; 2191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor memset(bus, 0, sizeof(*bus)); 2211a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus->location = bus_num; 2221a49d97d762570027863e9209af81d445e4f1502Douglas Gregor sprintf(bus->dirname, "%03d", bus_num); 2231a49d97d762570027863e9209af81d445e4f1502Douglas Gregor LIST_ADD(busses, bus); 2241a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 225677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 2261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_free_device_list(dev_list, 1); 2271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor *ret = busses; 2281a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return 0; 2291a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2301a49d97d762570027863e9209af81d445e4f1502Douglas Gregorerr: 231677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor bus = busses; 232677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor while (bus) { 2331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *tbus = bus->next; 2341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor free(bus); 2351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus = tbus; 2361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return -ENOMEM; 2381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2401a49d97d762570027863e9209af81d445e4f1502Douglas GregorAPI_EXPORTED int usb_find_busses(void) 2411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 2421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *new_busses = NULL; 2431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *bus; 2441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor int changes = 0; 2451a49d97d762570027863e9209af81d445e4f1502Douglas Gregor int r; 2461a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* libusb-1.0 initialization might have failed, but we can't indicate 2481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor * this with libusb-0.1, so trap that situation here */ 2491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!ctx) 250677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return 0; 2511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_dbg(""); 253677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor r = find_busses(&new_busses); 254677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (r < 0) { 2551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_err("find_busses failed with error %d", r); 2561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return r; 257fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor } 258fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 2591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* walk through all busses we already know about, removing duplicates 2601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor * from the new list. if we do not find it in the new list, the bus 2611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor * has been removed. */ 2621a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 263677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor bus = usb_busses; 264677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor while (bus) { 2651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *tbus = bus->next; 266677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor struct usb_bus *nbus = new_busses; 267677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor int found = 0; 2681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_dbg("in loop"); 2691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#if 0 /* (yavor) NO caching */ 2711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (nbus) { 272677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor struct usb_bus *tnbus = nbus->next; 273677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 274677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (bus->location == nbus->location) { 275fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor LIST_DEL(new_busses, nbus); 276677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor free(nbus); 277677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor found = 1; 2781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 280188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor nbus = tnbus; 281188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor } 2821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#endif 2831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!found) { 2841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* bus removed */ 2851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor usbi_dbg("bus %d removed", bus->location); 2861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor changes++; 2871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor LIST_DEL(usb_busses, bus); 2881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor free(bus); 2891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2901a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus = tbus; 2921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /* anything remaining in new_busses is a new bus */ 2951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus = new_busses; 2961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (bus) { 2971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_bus *tbus = bus->next; 298fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor usbi_dbg("bus %d added", bus->location); 299fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor LIST_DEL(new_busses, bus); 3001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor LIST_ADD(usb_busses, bus); 3011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor changes++; 3021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bus = tbus; 3031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return changes; 306fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor} 307fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 308fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregorstatic int find_devices(libusb_device **dev_list, int dev_list_len, 309fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor struct usb_bus *bus, struct usb_device **ret) 310fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor{ 311fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor struct usb_device *devices = NULL; 312677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor struct usb_device *dev; 313677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor int i; 314fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 315fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor for (i = 0; i < dev_list_len; i++) { 316fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor libusb_device *newlib_dev = dev_list[i]; 317fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor uint8_t bus_num = libusb_get_bus_number(newlib_dev); 318fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 319fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (bus_num != bus->location) 320fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor continue; 321fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 322fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor dev = malloc(sizeof(*dev)); 323fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (!dev) 324fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor goto err; 325fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 326677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor /* No need to reference the device now, just take the pointer. We 327677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * increase the reference count later if we keep the device. */ 328fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor dev->dev = newlib_dev; 329fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 330fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor dev->bus = bus; 331677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor dev->devnum = libusb_get_device_address(newlib_dev); 332677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor sprintf(dev->filename, "%03d", dev->devnum); 3331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor LIST_ADD(devices, dev); 3341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor *ret = devices; 3371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return 0; 3381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3391a49d97d762570027863e9209af81d445e4f1502Douglas Gregorerr: 3401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor dev = devices; 3411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (dev) { 3421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor struct usb_device *tdev = dev->next; 3431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor free(dev); 344a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = tdev; 345a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 346a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 347a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 348a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 349a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void clear_endpoint_descriptor(struct usb_endpoint_descriptor *ep) 350a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 351a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (ep->extra) 352a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(ep->extra); 353a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 354a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 355a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void clear_interface_descriptor(struct usb_interface_descriptor *iface) 356a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 357a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (iface->extra) 358a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(iface->extra); 359a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (iface->endpoint) { 360a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 361a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < iface->bNumEndpoints; i++) 362a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_endpoint_descriptor(iface->endpoint + i); 363a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(iface->endpoint); 364a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 365a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 366a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 367a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void clear_interface(struct usb_interface *iface) 368a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 369a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (iface->altsetting) { 370a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 371a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < iface->num_altsetting; i++) 372a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_interface_descriptor(iface->altsetting + i); 373a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(iface->altsetting); 374a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 375a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 376a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 377a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void clear_config_descriptor(struct usb_config_descriptor *config) 378a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 379a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (config->extra) 380a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(config->extra); 381a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (config->interface) { 382a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 383a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < config->bNumInterfaces; i++) 384a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_interface(config->interface + i); 385a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(config->interface); 386a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 387a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 388a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 389a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void clear_device(struct usb_device *dev) 390a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 391a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 392a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < dev->descriptor.bNumConfigurations; i++) 393a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_config_descriptor(dev->config + i); 394a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 395a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 396a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int copy_endpoint_descriptor(struct usb_endpoint_descriptor *dest, 397a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const struct libusb_endpoint_descriptor *src) 398a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 399a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memcpy(dest, src, USB_DT_ENDPOINT_AUDIO_SIZE); 400a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 401a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extralen = src->extra_length; 402a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (src->extra_length) { 403a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extra = malloc(src->extra_length); 404a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->extra) 405a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 406a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memcpy(dest->extra, src->extra, src->extra_length); 407a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 408a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 409a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 410a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 411a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 412a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int copy_interface_descriptor(struct usb_interface_descriptor *dest, 413a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const struct libusb_interface_descriptor *src) 414a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 415a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 416a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int num_endpoints = src->bNumEndpoints; 417a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor size_t alloc_size = sizeof(struct usb_endpoint_descriptor) * num_endpoints; 418a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 419a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memcpy(dest, src, USB_DT_INTERFACE_SIZE); 420a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->endpoint = malloc(alloc_size); 421a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->endpoint) 422a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 423a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memset(dest->endpoint, 0, alloc_size); 424a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 425a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < num_endpoints; i++) { 426a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r = copy_endpoint_descriptor(dest->endpoint + i, &src->endpoint[i]); 427a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 428a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_interface_descriptor(dest); 429a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return r; 430a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 431a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 432a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 433a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extralen = src->extra_length; 434a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (src->extra_length) { 435a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extra = malloc(src->extra_length); 436a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->extra) { 437a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_interface_descriptor(dest); 4381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return -ENOMEM; 439a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 440a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memcpy(dest->extra, src->extra, src->extra_length); 441a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 442a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 443a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 444a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 445a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 446a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int copy_interface(struct usb_interface *dest, 4471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor const struct libusb_interface *src) 448a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 449a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 450a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int num_altsetting = src->num_altsetting; 451a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor size_t alloc_size = sizeof(struct usb_interface_descriptor) 452a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * num_altsetting; 453a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 454a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->num_altsetting = num_altsetting; 455a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->altsetting = malloc(alloc_size); 456a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->altsetting) 457a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 458a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memset(dest->altsetting, 0, alloc_size); 459a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 460a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < num_altsetting; i++) { 461a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r = copy_interface_descriptor(dest->altsetting + i, 462a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor &src->altsetting[i]); 463a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 464a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_interface(dest); 465a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return r; 466a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 467a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 468a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 469a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 470a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 4718e31d064e7543dde6e4205d5b27a95c96a4c3a4eDouglas Gregor 4728e31d064e7543dde6e4205d5b27a95c96a4c3a4eDouglas Gregorstatic int copy_config_descriptor(struct usb_config_descriptor *dest, 473a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const struct libusb_config_descriptor *src) 474a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 475a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 476a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int num_interfaces = src->bNumInterfaces; 477a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor size_t alloc_size = sizeof(struct usb_interface) * num_interfaces; 478a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 479a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memcpy(dest, src, USB_DT_CONFIG_SIZE); 480a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->interface = malloc(alloc_size); 481a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->interface) 482a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 483a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memset(dest->interface, 0, alloc_size); 484a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 485a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < num_interfaces; i++) { 486a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r = copy_interface(dest->interface + i, &src->interface[i]); 487a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 488a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_config_descriptor(dest); 489a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return r; 490a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 491a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 492a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 493a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extralen = src->extra_length; 494a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (src->extra_length) { 495a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dest->extra = malloc(src->extra_length); 496a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dest->extra) { 4971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor clear_config_descriptor(dest); 498a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -ENOMEM; 499a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 5001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor memcpy(dest->extra, src->extra, src->extra_length); 501a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 502a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 5031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return 0; 5041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 505a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 506a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int initialize_device(struct usb_device *dev) 5071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 5081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor libusb_device *newlib_dev = dev->dev; 509a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int num_configurations; 510a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor size_t alloc_size; 511a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 512a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int i; 513a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 514a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* device descriptor is identical in both libs */ 515a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_get_device_descriptor(newlib_dev, 516a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor (struct libusb_device_descriptor *) &dev->descriptor); 5171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (r < 0) { 518a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_err("error %d getting device descriptor", r); 519a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 520a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 521a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 522a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor num_configurations = dev->descriptor.bNumConfigurations; 523a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor alloc_size = sizeof(struct usb_config_descriptor) * num_configurations; 524a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->config = malloc(alloc_size); 525a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!dev->config) 5261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return -ENOMEM; 527a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor memset(dev->config, 0, alloc_size); 528a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 529a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* even though structures are identical, we can't just use libusb-1.0's 530a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * config descriptors because we have to store all configurations in 531a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * a single flat memory area (libusb-1.0 provides separate allocations). 532a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * we hand-copy libusb-1.0's descriptors into our own structures. */ 533a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (i = 0; i < num_configurations; i++) { 534a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct libusb_config_descriptor *newlib_config; 535a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_get_config_descriptor(newlib_dev, i, &newlib_config); 536a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 537a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_device(dev); 538a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(dev->config); 539a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 540a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 5411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor r = copy_config_descriptor(dev->config + i, newlib_config); 542a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_free_config_descriptor(newlib_config); 543a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 544a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_device(dev); 545a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(dev->config); 546a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return r; 547a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 548a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 549a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 550a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* libusb doesn't implement this and it doesn't seem that important. If 551a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * someone asks for it, we can implement it in v1.1 or later. */ 552a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->num_children = 0; 553a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->children = NULL; 554a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 555a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_ref_device(newlib_dev); 556a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 557a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 558a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 559a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void free_device(struct usb_device *dev) 560a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 561a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clear_device(dev); 562a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_unref_device(dev->dev); 563677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor free(dev); 564677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor} 565677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 566677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorAPI_EXPORTED int usb_find_devices(void) 567a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 568a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_bus *bus; 569a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_device **dev_list; 570a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int dev_list_len; 571a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 572a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int changes = 0; 573a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 574ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor /* libusb-1.0 initialization might have failed, but we can't indicate 575ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor * this with libusb-0.1, so trap that situation here */ 576ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor if (!ctx) 577677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return 0; 578677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 579677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor usbi_dbg(""); 580a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev_list_len = libusb_get_device_list(ctx, &dev_list); 581a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (dev_list_len < 0) 582a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(dev_list_len); 583a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 584a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (bus = usb_busses; bus; bus = bus->next) { 585a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_device *new_devices = NULL; 586a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_device *dev; 587a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 588a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = find_devices(dev_list, dev_list_len, bus, &new_devices); 589a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 590a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_free_device_list(dev_list, 1); 591a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return r; 592a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 593a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 594a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* walk through the devices we already know about, removing duplicates 595a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * from the new list. if we do not find it in the new list, the device 596a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * has been removed. */ 597a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = bus->devices; 598a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (dev) { 599a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int found = 0; 600a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_device *tdev = dev->next; 601a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_device *ndev = new_devices; 602a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 603a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (ndev) { 6041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (ndev->devnum == dev->devnum) { 6051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor LIST_DEL(new_devices, ndev); 606a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(ndev); 607a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor found = 1; 608a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor break; 609a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 610a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ndev = ndev->next; 611a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 612a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 613a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!found) { 614a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("device %d.%d removed", 615a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->bus->location, dev->devnum); 616a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LIST_DEL(bus->devices, dev); 617a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free_device(dev); 618a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor changes++; 619a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 620a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 621a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = tdev; 622a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 623a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 624a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* anything left in new_devices is a new device */ 625a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = new_devices; 626a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (dev) { 627a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct usb_device *tdev = dev->next; 628a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = initialize_device(dev); 629a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 630a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_err("couldn't initialize device %d.%d (error %d)", 631a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->bus->location, dev->devnum, r); 632a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = tdev; 633a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 634a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 635a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("device %d.%d added", dev->bus->location, dev->devnum); 636a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LIST_DEL(new_devices, dev); 637a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor LIST_ADD(bus->devices, dev); 638a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor changes++; 639a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev = tdev; 640a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 641a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 642a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 643a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_free_device_list(dev_list, 1); 644a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return changes; 645a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 646a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 647a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED struct usb_bus *usb_get_busses(void) 648a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 649a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return usb_busses; 650a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 651a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 652a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED usb_dev_handle *usb_open(struct usb_device *dev) 653a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 654a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 655a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg(""); 656a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 657a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usb_dev_handle *udev = malloc(sizeof(*udev)); 658a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!udev) 659a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return NULL; 660a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 661a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_open((libusb_device *) dev->dev, &udev->handle); 662a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r < 0) { 663a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_err("could not open device, error %d", r); 664a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(udev); 665a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor errno = libusb_to_errno(r); 666a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return NULL; 667a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 668a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 669a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor udev->last_claimed_interface = -1; 6701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor udev->device = dev; 671a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return udev; 672a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 673a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 674a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_close(usb_dev_handle *dev) 675a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 676a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg(""); 677a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor libusb_close(dev->handle); 678a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor free(dev); 679a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 680a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 681a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 682a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED struct usb_device *usb_device(usb_dev_handle *dev) 683a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 684a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return dev->device; 685a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 686a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 687a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_set_configuration(usb_dev_handle *dev, int configuration) 688a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 689a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("configuration %d", configuration); 690a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(libusb_set_configuration(dev->handle, configuration)); 691a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 692a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 693a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_claim_interface(usb_dev_handle *dev, int interface) 694a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 695a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 696a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("interface %d", interface); 697a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 698a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_claim_interface(dev->handle, interface); 699a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r == 0) { 700a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->last_claimed_interface = interface; 701a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return 0; 702a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 703a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 704a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 705a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 706a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 707a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_release_interface(usb_dev_handle *dev, int interface) 708a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 709a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 710a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("interface %d", interface); 711a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 712a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_release_interface(dev->handle, interface); 713a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r == 0) 714a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->last_claimed_interface = -1; 715a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 716a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 717a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 718a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 719a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_set_altinterface(usb_dev_handle *dev, int alternate) 720a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 721a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("alternate %d", alternate); 722a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (dev->last_claimed_interface < 0) 723a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return -(errno=EINVAL); 724a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 725a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(libusb_set_interface_alt_setting(dev->handle, 726a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor dev->last_claimed_interface, alternate)); 727a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 728a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 729a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_resetep(usb_dev_handle *dev, unsigned int ep) 730a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 731a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(usb_clear_halt(dev, ep)); 732a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 733a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 734a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_clear_halt(usb_dev_handle *dev, unsigned int ep) 735a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 736a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("endpoint %x", ep); 737a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(libusb_clear_halt(dev->handle, ep & 0xff)); 738a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 739a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 740a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_reset(usb_dev_handle *dev) 741a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 742a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg(""); 743a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(libusb_reset_device(dev->handle)); 744a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 745a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 746a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int usb_bulk_io(usb_dev_handle *dev, int ep, char *bytes, 747a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int size, int timeout) 748a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 749a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int actual_length; 750a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 751a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); 752a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_bulk_transfer(dev->handle, ep & 0xff, bytes, size, 753a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor &actual_length, timeout); 754a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 755a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* if we timed out but did transfer some data, report as successful short 756a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * read. FIXME: is this how libusb-0.1 works? */ 757a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) 758a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return actual_length; 759a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 760a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 761a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 762a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 763a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, 764a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int size, int timeout) 765a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 766a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!(ep & USB_ENDPOINT_IN)) { 767a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* libusb-0.1 will strangely fix up a read request from endpoint 768a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 0x01 to be from endpoint 0x81. do the same thing here, but 769a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * warn about this silly behaviour. */ 770a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_warn("endpoint %x is missing IN direction bit, fixing"); 771a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ep |= USB_ENDPOINT_IN; 772a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 773a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 774a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return usb_bulk_io(dev, ep, bytes, size, timeout); 775a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 776a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 777a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, 778a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int size, int timeout) 779a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 780a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (ep & USB_ENDPOINT_IN) { 781a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* libusb-0.1 on BSD strangely fix up a write request to endpoint 782a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 0x81 to be to endpoint 0x01. do the same thing here, but 783a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * warn about this silly behaviour. */ 784a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_warn("endpoint %x has excessive IN direction bit, fixing"); 785a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ep &= ~USB_ENDPOINT_IN; 786a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 787a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 788a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return usb_bulk_io(dev, ep, bytes, size, timeout); 789a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 790a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 791a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic int usb_interrupt_io(usb_dev_handle *dev, int ep, char *bytes, 792a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int size, int timeout) 79370e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola{ 79470e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola int actual_length; 795a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int r; 796a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); 797a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor r = libusb_interrupt_transfer(dev->handle, ep & 0xff, bytes, size, 798d2db16f59601bc028f4f973990cc6d4abe95b91aNAKAMURA Takumi &actual_length, timeout); 799a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 800a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* if we timed out but did transfer some data, report as successful short 801a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * read. FIXME: is this how libusb-0.1 works? */ 802a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) 803a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return actual_length; 804a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 805a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return compat_err(r); 806a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 807a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 808a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, 809a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int size, int timeout) 810a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor{ 811a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!(ep & USB_ENDPOINT_IN)) { 812a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /* libusb-0.1 will strangely fix up a read request from endpoint 813a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * 0x01 to be from endpoint 0x81. do the same thing here, but 814a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor * warn about this silly behaviour. */ 815a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor usbi_warn("endpoint %x is missing IN direction bit, fixing"); 816a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ep |= USB_ENDPOINT_IN; 817a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 818a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return usb_interrupt_io(dev, ep, bytes, size, timeout); 819a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 820a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 821a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorAPI_EXPORTED int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, 82287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis int size, int timeout) 82387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis{ 82487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis if (ep & USB_ENDPOINT_IN) { 82587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis /* libusb-0.1 on BSD strangely fix up a write request to endpoint 82687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis * 0x81 to be to endpoint 0x01. do the same thing here, but 82787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis * warn about this silly behaviour. */ 82887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis usbi_warn("endpoint %x has excessive IN direction bit, fixing"); 82987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis ep &= ~USB_ENDPOINT_IN; 83087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis } 83187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 83287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return usb_interrupt_io(dev, ep, bytes, size, timeout); 83387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 83487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 83587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios KyrtzidisAPI_EXPORTED int usb_control_msg(usb_dev_handle *dev, int bmRequestType, 83687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis int bRequest, int wValue, int wIndex, char *bytes, int size, int timeout) 83787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis{ 83887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis int r; 83987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis usbi_dbg("RQT=%x RQ=%x V=%x I=%x len=%d timeout=%d", bmRequestType, 84087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis bRequest, wValue, wIndex, size, timeout); 84187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 84287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis r = libusb_control_transfer(dev->handle, bmRequestType & 0xff, 84387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis bRequest & 0xff, wValue & 0xffff, wIndex & 0xffff, bytes, size & 0xffff, 84487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis timeout); 84587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 84687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis if (r >= 0) 84787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return r; 84887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 84987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return compat_err(r); 85087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 85187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 85287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios KyrtzidisAPI_EXPORTED int usb_get_string(usb_dev_handle *dev, int desc_index, int langid, 853 char *buf, size_t buflen) 854{ 855 int r; 856 r = libusb_get_string_descriptor(dev->handle, desc_index & 0xff, 857 langid & 0xffff, buf, (int) buflen); 858 if (r >= 0) 859 return r; 860 return compat_err(r); 861} 862 863API_EXPORTED int usb_get_string_simple(usb_dev_handle *dev, int desc_index, 864 char *buf, size_t buflen) 865{ 866 int r; 867 r = libusb_get_string_descriptor_ascii(dev->handle, desc_index & 0xff, 868 buf, (int) buflen); 869 if (r >= 0) 870 return r; 871 return compat_err(r); 872} 873 874API_EXPORTED int usb_get_descriptor(usb_dev_handle *dev, unsigned char type, 875 unsigned char desc_index, void *buf, int size) 876{ 877 int r; 878 r = libusb_get_descriptor(dev->handle, type, desc_index, buf, size); 879 if (r >= 0) 880 return r; 881 return compat_err(r); 882} 883 884API_EXPORTED int usb_get_descriptor_by_endpoint(usb_dev_handle *dev, int ep, 885 unsigned char type, unsigned char desc_index, void *buf, int size) 886{ 887 /* this function doesn't make much sense - the specs don't talk about 888 * getting a descriptor "by endpoint". libusb-1.0 does not provide this 889 * functionality so we just send a control message directly */ 890 int r; 891 r = libusb_control_transfer(dev->handle, 892 LIBUSB_ENDPOINT_IN | (ep & 0xff), LIBUSB_REQUEST_GET_DESCRIPTOR, 893 (type << 8) | desc_index, 0, buf, size, 1000); 894 if (r >= 0) 895 return r; 896 return compat_err(r); 897} 898 899API_EXPORTED int usb_get_driver_np(usb_dev_handle *dev, int interface, 900 char *name, unsigned int namelen) 901{ 902 int r = libusb_kernel_driver_active(dev->handle, interface); 903 if (r == 1) { 904 /* libusb-1.0 doesn't expose driver name, so fill in a dummy value */ 905 snprintf(name, namelen, "dummy"); 906 return 0; 907 } else if (r == 0) { 908 return -(errno=ENODATA); 909 } else { 910 return compat_err(r); 911 } 912} 913 914API_EXPORTED int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface) 915{ 916 return compat_err(libusb_detach_kernel_driver(dev->handle, interface)); 917} 918 919