Home | History | Annotate | Download | only in libusb
      1 /*
      2  * Core functions for libusb-compat-0.1
      3  * Copyright (C) 2008 Daniel Drake <dsd (at) gentoo.org>
      4  * Copyright (c) 2000-2003 Johannes Erdfelt <johannes (at) erdfelt.com>
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, write to the Free Software
     18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19  */
     20 
     21 #include <config.h>
     22 #include <errno.h>
     23 #include <stdarg.h>
     24 #include <stdio.h>
     25 #include <string.h>
     26 
     27 #include <libusb.h>
     28 
     29 #include "usb.h"
     30 #include "usbi.h"
     31 
     32 static libusb_context *ctx = NULL;
     33 static int usb_debug = 0;
     34 
     35 enum usbi_log_level {
     36 	LOG_LEVEL_DEBUG,
     37 	LOG_LEVEL_INFO,
     38 	LOG_LEVEL_WARNING,
     39 	LOG_LEVEL_ERROR,
     40 };
     41 
     42 #ifdef ENABLE_LOGGING
     43 #define _usbi_log(level, fmt...) usbi_log(level, __FUNCTION__, fmt)
     44 #else
     45 #define _usbi_log(level, fmt...)
     46 #endif
     47 
     48 #ifdef ENABLE_DEBUG_LOGGING
     49 #define usbi_dbg(fmt...) _usbi_log(LOG_LEVEL_DEBUG, fmt)
     50 #else
     51 #define usbi_dbg(fmt...)
     52 #endif
     53 
     54 #define usbi_info(fmt...) _usbi_log(LOG_LEVEL_INFO, fmt)
     55 #define usbi_warn(fmt...) _usbi_log(LOG_LEVEL_WARNING, fmt)
     56 #define usbi_err(fmt...) _usbi_log(LOG_LEVEL_ERROR, fmt)
     57 
     58 API_EXPORTED struct usb_bus *usb_busses = NULL;
     59 
     60 #define compat_err(e) -(errno=libusb_to_errno(e))
     61 
     62 static int libusb_to_errno(int result)
     63 {
     64 	switch (result) {
     65 	case LIBUSB_SUCCESS:
     66 		return 0;
     67 	case LIBUSB_ERROR_IO:
     68 		return EIO;
     69 	case LIBUSB_ERROR_INVALID_PARAM:
     70 		return EINVAL;
     71 	case LIBUSB_ERROR_ACCESS:
     72 		return EACCES;
     73 	case LIBUSB_ERROR_NO_DEVICE:
     74 		return ENXIO;
     75 	case LIBUSB_ERROR_NOT_FOUND:
     76 		return ENOENT;
     77 	case LIBUSB_ERROR_BUSY:
     78 		return EBUSY;
     79 	case LIBUSB_ERROR_TIMEOUT:
     80 		return ETIMEDOUT;
     81 	case LIBUSB_ERROR_OVERFLOW:
     82 		return EOVERFLOW;
     83 	case LIBUSB_ERROR_PIPE:
     84 		return EPIPE;
     85 	case LIBUSB_ERROR_INTERRUPTED:
     86 		return EINTR;
     87 	case LIBUSB_ERROR_NO_MEM:
     88 		return ENOMEM;
     89 	case LIBUSB_ERROR_NOT_SUPPORTED:
     90 		return ENOSYS;
     91 	default:
     92 		return ERANGE;
     93 	}
     94 }
     95 
     96 static void usbi_log(enum usbi_log_level level, const char *function,
     97 	const char *format, ...)
     98 {
     99 	va_list args;
    100 	FILE *stream = stdout;
    101 	const char *prefix;
    102 
    103 #ifndef ENABLE_DEBUG_LOGGING
    104 	if (!usb_debug)
    105 		return;
    106 #endif
    107 
    108 	switch (level) {
    109 	case LOG_LEVEL_INFO:
    110 		prefix = "info";
    111 		break;
    112 	case LOG_LEVEL_WARNING:
    113 		stream = stderr;
    114 		prefix = "warning";
    115 		break;
    116 	case LOG_LEVEL_ERROR:
    117 		stream = stderr;
    118 		prefix = "error";
    119 		break;
    120 	case LOG_LEVEL_DEBUG:
    121 		stream = stderr;
    122 		prefix = "debug";
    123 		break;
    124 	default:
    125 		stream = stderr;
    126 		prefix = "unknown";
    127 		break;
    128 	}
    129 
    130 	fprintf(stream, "libusb-compat %s: %s: ", prefix, function);
    131 
    132 	va_start (args, format);
    133 	vfprintf(stream, format, args);
    134 	va_end (args);
    135 
    136 	fprintf(stream, "\n");
    137 }
    138 
    139 API_EXPORTED void usb_init(void)
    140 {
    141 	int r;
    142 	usbi_dbg("");
    143 
    144 	if (!ctx) {
    145 		r = libusb_init(&ctx);
    146 		if (r < 0) {
    147 			usbi_err("initialization failed!");
    148 			return;
    149 		}
    150 
    151 		/* usb_set_debug can be called before usb_init */
    152 		if (usb_debug)
    153 			libusb_set_debug(ctx, 3);
    154 	}
    155 }
    156 
    157 API_EXPORTED void usb_set_debug(int level)
    158 {
    159 	usb_debug = level;
    160 
    161 	/* usb_set_debug can be called before usb_init */
    162 	if (ctx)
    163 		libusb_set_debug(ctx, 3);
    164 }
    165 
    166 API_EXPORTED char *usb_strerror(void)
    167 {
    168 	return strerror(errno);
    169 }
    170 
    171 static int find_busses(struct usb_bus **ret)
    172 {
    173 	libusb_device **dev_list = NULL;
    174 	struct usb_bus *busses = NULL;
    175 	struct usb_bus *bus;
    176 	int dev_list_len = 0;
    177 	int i;
    178 	int r;
    179 
    180 	r = libusb_get_device_list(ctx, &dev_list);
    181 	if (r < 0) {
    182 		usbi_err("get_device_list failed with error %d", r);
    183 		return compat_err(r);
    184 	}
    185 
    186 	if (r == 0) {
    187 		libusb_free_device_list(dev_list, 1);
    188 		/* no buses */
    189 		return 0;
    190 	}
    191 
    192 	/* iterate over the device list, identifying the individual busses.
    193 	 * we use the location field of the usb_bus structure to store the
    194 	 * bus number. */
    195 
    196 	dev_list_len = r;
    197 	for (i = 0; i < dev_list_len; i++) {
    198 		libusb_device *dev = dev_list[i];
    199 		uint8_t bus_num = libusb_get_bus_number(dev);
    200 
    201 		/* if we already know about it, continue */
    202 		if (busses) {
    203 			bus = busses;
    204 			int found = 0;
    205 			do {
    206 				if (bus_num == bus->location) {
    207 					found = 1;
    208 					break;
    209 				}
    210 			} while ((bus = bus->next) != NULL);
    211 			if (found)
    212 				continue;
    213 		}
    214 
    215 		/* add it to the list of busses */
    216 		bus = malloc(sizeof(*bus));
    217 		if (!bus)
    218 			goto err;
    219 
    220 		memset(bus, 0, sizeof(*bus));
    221 		bus->location = bus_num;
    222 		sprintf(bus->dirname, "%03d", bus_num);
    223 		LIST_ADD(busses, bus);
    224 	}
    225 
    226 	libusb_free_device_list(dev_list, 1);
    227 	*ret = busses;
    228 	return 0;
    229 
    230 err:
    231 	bus = busses;
    232 	while (bus) {
    233 		struct usb_bus *tbus = bus->next;
    234 		free(bus);
    235 		bus = tbus;
    236 	}
    237 	return -ENOMEM;
    238 }
    239 
    240 API_EXPORTED int usb_find_busses(void)
    241 {
    242 	struct usb_bus *new_busses = NULL;
    243 	struct usb_bus *bus;
    244 	int changes = 0;
    245 	int r;
    246 
    247 	/* libusb-1.0 initialization might have failed, but we can't indicate
    248 	 * this with libusb-0.1, so trap that situation here */
    249 	if (!ctx)
    250 		return 0;
    251 
    252 	usbi_dbg("");
    253 	r = find_busses(&new_busses);
    254 	if (r < 0) {
    255 		usbi_err("find_busses failed with error %d", r);
    256 		return r;
    257 	}
    258 
    259 	/* walk through all busses we already know about, removing duplicates
    260 	 * from the new list. if we do not find it in the new list, the bus
    261 	 * has been removed. */
    262 
    263 	bus = usb_busses;
    264 	while (bus) {
    265 		struct usb_bus *tbus = bus->next;
    266 		struct usb_bus *nbus = new_busses;
    267 		int found = 0;
    268 		usbi_dbg("in loop");
    269 
    270 #if 0 /* (yavor)  NO caching */
    271 		while (nbus) {
    272 			struct usb_bus *tnbus = nbus->next;
    273 
    274 			if (bus->location == nbus->location) {
    275 				LIST_DEL(new_busses, nbus);
    276 				free(nbus);
    277 				found = 1;
    278 				break;
    279 			}
    280 			nbus = tnbus;
    281 		}
    282 #endif
    283 		if (!found) {
    284 			/* bus removed */
    285 			usbi_dbg("bus %d removed", bus->location);
    286 			changes++;
    287 			LIST_DEL(usb_busses, bus);
    288 			free(bus);
    289 		}
    290 
    291 		bus = tbus;
    292 	}
    293 
    294 	/* anything remaining in new_busses is a new bus */
    295 	bus = new_busses;
    296 	while (bus) {
    297 		struct usb_bus *tbus = bus->next;
    298 		usbi_dbg("bus %d added", bus->location);
    299 		LIST_DEL(new_busses, bus);
    300 		LIST_ADD(usb_busses, bus);
    301 		changes++;
    302 		bus = tbus;
    303 	}
    304 
    305 	return changes;
    306 }
    307 
    308 static int find_devices(libusb_device **dev_list, int dev_list_len,
    309 	struct usb_bus *bus, struct usb_device **ret)
    310 {
    311 	struct usb_device *devices = NULL;
    312 	struct usb_device *dev;
    313 	int i;
    314 
    315 	for (i = 0; i < dev_list_len; i++) {
    316 		libusb_device *newlib_dev = dev_list[i];
    317 		uint8_t bus_num = libusb_get_bus_number(newlib_dev);
    318 
    319 		if (bus_num != bus->location)
    320 			continue;
    321 
    322 		dev = malloc(sizeof(*dev));
    323 		if (!dev)
    324 			goto err;
    325 
    326 		/* No need to reference the device now, just take the pointer. We
    327 		 * increase the reference count later if we keep the device. */
    328 		dev->dev = newlib_dev;
    329 
    330 		dev->bus = bus;
    331 		dev->devnum = libusb_get_device_address(newlib_dev);
    332 		sprintf(dev->filename, "%03d", dev->devnum);
    333 		LIST_ADD(devices, dev);
    334 	}
    335 
    336 	*ret = devices;
    337 	return 0;
    338 
    339 err:
    340 	dev = devices;
    341 	while (dev) {
    342 		struct usb_device *tdev = dev->next;
    343 		free(dev);
    344 		dev = tdev;
    345 	}
    346 	return -ENOMEM;
    347 }
    348 
    349 static void clear_endpoint_descriptor(struct usb_endpoint_descriptor *ep)
    350 {
    351 	if (ep->extra)
    352 		free(ep->extra);
    353 }
    354 
    355 static void clear_interface_descriptor(struct usb_interface_descriptor *iface)
    356 {
    357 	if (iface->extra)
    358 		free(iface->extra);
    359 	if (iface->endpoint) {
    360 		int i;
    361 		for (i = 0; i < iface->bNumEndpoints; i++)
    362 			clear_endpoint_descriptor(iface->endpoint + i);
    363 		free(iface->endpoint);
    364 	}
    365 }
    366 
    367 static void clear_interface(struct usb_interface *iface)
    368 {
    369 	if (iface->altsetting) {
    370 		int i;
    371 		for (i = 0; i < iface->num_altsetting; i++)
    372 			clear_interface_descriptor(iface->altsetting + i);
    373 		free(iface->altsetting);
    374 	}
    375 }
    376 
    377 static void clear_config_descriptor(struct usb_config_descriptor *config)
    378 {
    379 	if (config->extra)
    380 		free(config->extra);
    381 	if (config->interface) {
    382 		int i;
    383 		for (i = 0; i < config->bNumInterfaces; i++)
    384 			clear_interface(config->interface + i);
    385 		free(config->interface);
    386 	}
    387 }
    388 
    389 static void clear_device(struct usb_device *dev)
    390 {
    391 	int i;
    392 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
    393 		clear_config_descriptor(dev->config + i);
    394 }
    395 
    396 static int copy_endpoint_descriptor(struct usb_endpoint_descriptor *dest,
    397 	const struct libusb_endpoint_descriptor *src)
    398 {
    399 	memcpy(dest, src, USB_DT_ENDPOINT_AUDIO_SIZE);
    400 
    401 	dest->extralen = src->extra_length;
    402 	if (src->extra_length) {
    403 		dest->extra = malloc(src->extra_length);
    404 		if (!dest->extra)
    405 			return -ENOMEM;
    406 		memcpy(dest->extra, src->extra, src->extra_length);
    407 	}
    408 
    409 	return 0;
    410 }
    411 
    412 static int copy_interface_descriptor(struct usb_interface_descriptor *dest,
    413 	const struct libusb_interface_descriptor *src)
    414 {
    415 	int i;
    416 	int num_endpoints = src->bNumEndpoints;
    417 	size_t alloc_size = sizeof(struct usb_endpoint_descriptor) * num_endpoints;
    418 
    419 	memcpy(dest, src, USB_DT_INTERFACE_SIZE);
    420 	dest->endpoint = malloc(alloc_size);
    421 	if (!dest->endpoint)
    422 		return -ENOMEM;
    423 	memset(dest->endpoint, 0, alloc_size);
    424 
    425 	for (i = 0; i < num_endpoints; i++) {
    426 		int r = copy_endpoint_descriptor(dest->endpoint + i, &src->endpoint[i]);
    427 		if (r < 0) {
    428 			clear_interface_descriptor(dest);
    429 			return r;
    430 		}
    431 	}
    432 
    433 	dest->extralen = src->extra_length;
    434 	if (src->extra_length) {
    435 		dest->extra = malloc(src->extra_length);
    436 		if (!dest->extra) {
    437 			clear_interface_descriptor(dest);
    438 			return -ENOMEM;
    439 		}
    440 		memcpy(dest->extra, src->extra, src->extra_length);
    441 	}
    442 
    443 	return 0;
    444 }
    445 
    446 static int copy_interface(struct usb_interface *dest,
    447 	const struct libusb_interface *src)
    448 {
    449 	int i;
    450 	int num_altsetting = src->num_altsetting;
    451 	size_t alloc_size = sizeof(struct usb_interface_descriptor)
    452 		* num_altsetting;
    453 
    454 	dest->num_altsetting = num_altsetting;
    455 	dest->altsetting = malloc(alloc_size);
    456 	if (!dest->altsetting)
    457 		return -ENOMEM;
    458 	memset(dest->altsetting, 0, alloc_size);
    459 
    460 	for (i = 0; i < num_altsetting; i++) {
    461 		int r = copy_interface_descriptor(dest->altsetting + i,
    462 			&src->altsetting[i]);
    463 		if (r < 0) {
    464 			clear_interface(dest);
    465 			return r;
    466 		}
    467 	}
    468 
    469 	return 0;
    470 }
    471 
    472 static int copy_config_descriptor(struct usb_config_descriptor *dest,
    473 	const struct libusb_config_descriptor *src)
    474 {
    475 	int i;
    476 	int num_interfaces = src->bNumInterfaces;
    477 	size_t alloc_size = sizeof(struct usb_interface) * num_interfaces;
    478 
    479 	memcpy(dest, src, USB_DT_CONFIG_SIZE);
    480 	dest->interface = malloc(alloc_size);
    481 	if (!dest->interface)
    482 		return -ENOMEM;
    483 	memset(dest->interface, 0, alloc_size);
    484 
    485 	for (i = 0; i < num_interfaces; i++) {
    486 		int r = copy_interface(dest->interface + i, &src->interface[i]);
    487 		if (r < 0) {
    488 			clear_config_descriptor(dest);
    489 			return r;
    490 		}
    491 	}
    492 
    493 	dest->extralen = src->extra_length;
    494 	if (src->extra_length) {
    495 		dest->extra = malloc(src->extra_length);
    496 		if (!dest->extra) {
    497 			clear_config_descriptor(dest);
    498 			return -ENOMEM;
    499 		}
    500 		memcpy(dest->extra, src->extra, src->extra_length);
    501 	}
    502 
    503 	return 0;
    504 }
    505 
    506 static int initialize_device(struct usb_device *dev)
    507 {
    508 	libusb_device *newlib_dev = dev->dev;
    509 	int num_configurations;
    510 	size_t alloc_size;
    511 	int r;
    512 	int i;
    513 
    514 	/* device descriptor is identical in both libs */
    515 	r = libusb_get_device_descriptor(newlib_dev,
    516 		(struct libusb_device_descriptor *) &dev->descriptor);
    517 	if (r < 0) {
    518 		usbi_err("error %d getting device descriptor", r);
    519 		return compat_err(r);
    520 	}
    521 
    522 	num_configurations = dev->descriptor.bNumConfigurations;
    523 	alloc_size = sizeof(struct usb_config_descriptor) * num_configurations;
    524 	dev->config = malloc(alloc_size);
    525 	if (!dev->config)
    526 		return -ENOMEM;
    527 	memset(dev->config, 0, alloc_size);
    528 
    529 	/* even though structures are identical, we can't just use libusb-1.0's
    530 	 * config descriptors because we have to store all configurations in
    531 	 * a single flat memory area (libusb-1.0 provides separate allocations).
    532 	 * we hand-copy libusb-1.0's descriptors into our own structures. */
    533 	for (i = 0; i < num_configurations; i++) {
    534 		struct libusb_config_descriptor *newlib_config;
    535 		r = libusb_get_config_descriptor(newlib_dev, i, &newlib_config);
    536 		if (r < 0) {
    537 			clear_device(dev);
    538 			free(dev->config);
    539 			return compat_err(r);
    540 		}
    541 		r = copy_config_descriptor(dev->config + i, newlib_config);
    542 		libusb_free_config_descriptor(newlib_config);
    543 		if (r < 0) {
    544 			clear_device(dev);
    545 			free(dev->config);
    546 			return r;
    547 		}
    548 	}
    549 
    550 	/* libusb doesn't implement this and it doesn't seem that important. If
    551 	 * someone asks for it, we can implement it in v1.1 or later. */
    552 	dev->num_children = 0;
    553 	dev->children = NULL;
    554 
    555 	libusb_ref_device(newlib_dev);
    556 	return 0;
    557 }
    558 
    559 static void free_device(struct usb_device *dev)
    560 {
    561 	clear_device(dev);
    562 	libusb_unref_device(dev->dev);
    563 	free(dev);
    564 }
    565 
    566 API_EXPORTED int usb_find_devices(void)
    567 {
    568 	struct usb_bus *bus;
    569 	libusb_device **dev_list;
    570 	int dev_list_len;
    571 	int r;
    572 	int changes = 0;
    573 
    574 	/* libusb-1.0 initialization might have failed, but we can't indicate
    575 	 * this with libusb-0.1, so trap that situation here */
    576 	if (!ctx)
    577 		return 0;
    578 
    579 	usbi_dbg("");
    580 	dev_list_len = libusb_get_device_list(ctx, &dev_list);
    581 	if (dev_list_len < 0)
    582 		return compat_err(dev_list_len);
    583 
    584 	for (bus = usb_busses; bus; bus = bus->next) {
    585 		struct usb_device *new_devices = NULL;
    586 		struct usb_device *dev;
    587 
    588 		r = find_devices(dev_list, dev_list_len, bus, &new_devices);
    589 		if (r < 0) {
    590 			libusb_free_device_list(dev_list, 1);
    591 			return r;
    592 		}
    593 
    594 		/* walk through the devices we already know about, removing duplicates
    595 		 * from the new list. if we do not find it in the new list, the device
    596 		 * has been removed. */
    597 		dev = bus->devices;
    598 		while (dev) {
    599 			int found = 0;
    600 			struct usb_device *tdev = dev->next;
    601 			struct usb_device *ndev = new_devices;
    602 
    603 			while (ndev) {
    604 				if (ndev->devnum == dev->devnum) {
    605 					LIST_DEL(new_devices, ndev);
    606 					free(ndev);
    607 					found = 1;
    608 					break;
    609 				}
    610 				ndev = ndev->next;
    611 			}
    612 
    613 			if (!found) {
    614 				usbi_dbg("device %d.%d removed",
    615 					dev->bus->location, dev->devnum);
    616 				LIST_DEL(bus->devices, dev);
    617 				free_device(dev);
    618 				changes++;
    619 			}
    620 
    621 			dev = tdev;
    622 		}
    623 
    624 		/* anything left in new_devices is a new device */
    625 		dev = new_devices;
    626 		while (dev) {
    627 			struct usb_device *tdev = dev->next;
    628 			r = initialize_device(dev);
    629 			if (r < 0) {
    630 				usbi_err("couldn't initialize device %d.%d (error %d)",
    631 					dev->bus->location, dev->devnum, r);
    632 				dev = tdev;
    633 				continue;
    634 			}
    635 			usbi_dbg("device %d.%d added", dev->bus->location, dev->devnum);
    636 			LIST_DEL(new_devices, dev);
    637 			LIST_ADD(bus->devices, dev);
    638 			changes++;
    639 			dev = tdev;
    640 		}
    641 	}
    642 
    643 	libusb_free_device_list(dev_list, 1);
    644 	return changes;
    645 }
    646 
    647 API_EXPORTED struct usb_bus *usb_get_busses(void)
    648 {
    649 	return usb_busses;
    650 }
    651 
    652 API_EXPORTED usb_dev_handle *usb_open(struct usb_device *dev)
    653 {
    654 	int r;
    655 	usbi_dbg("");
    656 
    657 	usb_dev_handle *udev = malloc(sizeof(*udev));
    658 	if (!udev)
    659 		return NULL;
    660 
    661 	r = libusb_open((libusb_device *) dev->dev, &udev->handle);
    662 	if (r < 0) {
    663 		usbi_err("could not open device, error %d", r);
    664 		free(udev);
    665 		errno = libusb_to_errno(r);
    666 		return NULL;
    667 	}
    668 
    669 	udev->last_claimed_interface = -1;
    670 	udev->device = dev;
    671 	return udev;
    672 }
    673 
    674 API_EXPORTED int usb_close(usb_dev_handle *dev)
    675 {
    676 	usbi_dbg("");
    677 	libusb_close(dev->handle);
    678 	free(dev);
    679 	return 0;
    680 }
    681 
    682 API_EXPORTED struct usb_device *usb_device(usb_dev_handle *dev)
    683 {
    684 	return dev->device;
    685 }
    686 
    687 API_EXPORTED int usb_set_configuration(usb_dev_handle *dev, int configuration)
    688 {
    689 	usbi_dbg("configuration %d", configuration);
    690 	return compat_err(libusb_set_configuration(dev->handle, configuration));
    691 }
    692 
    693 API_EXPORTED int usb_claim_interface(usb_dev_handle *dev, int interface)
    694 {
    695 	int r;
    696 	usbi_dbg("interface %d", interface);
    697 
    698 	r = libusb_claim_interface(dev->handle, interface);
    699 	if (r == 0) {
    700 		dev->last_claimed_interface = interface;
    701 		return 0;
    702 	}
    703 
    704 	return compat_err(r);
    705 }
    706 
    707 API_EXPORTED int usb_release_interface(usb_dev_handle *dev, int interface)
    708 {
    709 	int r;
    710 	usbi_dbg("interface %d", interface);
    711 
    712 	r = libusb_release_interface(dev->handle, interface);
    713 	if (r == 0)
    714 		dev->last_claimed_interface = -1;
    715 
    716 	return compat_err(r);
    717 }
    718 
    719 API_EXPORTED int usb_set_altinterface(usb_dev_handle *dev, int alternate)
    720 {
    721 	usbi_dbg("alternate %d", alternate);
    722 	if (dev->last_claimed_interface < 0)
    723 		return -(errno=EINVAL);
    724 
    725 	return compat_err(libusb_set_interface_alt_setting(dev->handle,
    726 		dev->last_claimed_interface, alternate));
    727 }
    728 
    729 API_EXPORTED int usb_resetep(usb_dev_handle *dev, unsigned int ep)
    730 {
    731 	return compat_err(usb_clear_halt(dev, ep));
    732 }
    733 
    734 API_EXPORTED int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
    735 {
    736 	usbi_dbg("endpoint %x", ep);
    737 	return compat_err(libusb_clear_halt(dev->handle, ep & 0xff));
    738 }
    739 
    740 API_EXPORTED int usb_reset(usb_dev_handle *dev)
    741 {
    742 	usbi_dbg("");
    743 	return compat_err(libusb_reset_device(dev->handle));
    744 }
    745 
    746 static int usb_bulk_io(usb_dev_handle *dev, int ep, char *bytes,
    747 	int size, int timeout)
    748 {
    749 	int actual_length;
    750 	int r;
    751 	usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
    752 	r = libusb_bulk_transfer(dev->handle, ep & 0xff, bytes, size,
    753 		&actual_length, timeout);
    754 
    755 	/* if we timed out but did transfer some data, report as successful short
    756 	 * read. FIXME: is this how libusb-0.1 works? */
    757 	if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0))
    758 		return actual_length;
    759 
    760 	return compat_err(r);
    761 }
    762 
    763 API_EXPORTED int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes,
    764 	int size, int timeout)
    765 {
    766 	if (!(ep & USB_ENDPOINT_IN)) {
    767 		/* libusb-0.1 will strangely fix up a read request from endpoint
    768 		 * 0x01 to be from endpoint 0x81. do the same thing here, but
    769 		 * warn about this silly behaviour. */
    770 		usbi_warn("endpoint %x is missing IN direction bit, fixing");
    771 		ep |= USB_ENDPOINT_IN;
    772 	}
    773 
    774 	return usb_bulk_io(dev, ep, bytes, size, timeout);
    775 }
    776 
    777 API_EXPORTED int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes,
    778 	int size, int timeout)
    779 {
    780 	if (ep & USB_ENDPOINT_IN) {
    781 		/* libusb-0.1 on BSD strangely fix up a write request to endpoint
    782 		 * 0x81 to be to endpoint 0x01. do the same thing here, but
    783 		 * warn about this silly behaviour. */
    784 		usbi_warn("endpoint %x has excessive IN direction bit, fixing");
    785 		ep &= ~USB_ENDPOINT_IN;
    786 	}
    787 
    788 	return usb_bulk_io(dev, ep, bytes, size, timeout);
    789 }
    790 
    791 static int usb_interrupt_io(usb_dev_handle *dev, int ep, char *bytes,
    792 	int size, int timeout)
    793 {
    794 	int actual_length;
    795 	int r;
    796 	usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
    797 	r = libusb_interrupt_transfer(dev->handle, ep & 0xff, bytes, size,
    798 		&actual_length, timeout);
    799 
    800 	/* if we timed out but did transfer some data, report as successful short
    801 	 * read. FIXME: is this how libusb-0.1 works? */
    802 	if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0))
    803 		return actual_length;
    804 
    805 	return compat_err(r);
    806 }
    807 
    808 API_EXPORTED int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes,
    809 	int size, int timeout)
    810 {
    811 	if (!(ep & USB_ENDPOINT_IN)) {
    812 		/* libusb-0.1 will strangely fix up a read request from endpoint
    813 		 * 0x01 to be from endpoint 0x81. do the same thing here, but
    814 		 * warn about this silly behaviour. */
    815 		usbi_warn("endpoint %x is missing IN direction bit, fixing");
    816 		ep |= USB_ENDPOINT_IN;
    817 	}
    818 	return usb_interrupt_io(dev, ep, bytes, size, timeout);
    819 }
    820 
    821 API_EXPORTED int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes,
    822 	int size, int timeout)
    823 {
    824 	if (ep & USB_ENDPOINT_IN) {
    825 		/* libusb-0.1 on BSD strangely fix up a write request to endpoint
    826 		 * 0x81 to be to endpoint 0x01. do the same thing here, but
    827 		 * warn about this silly behaviour. */
    828 		usbi_warn("endpoint %x has excessive IN direction bit, fixing");
    829 		ep &= ~USB_ENDPOINT_IN;
    830 	}
    831 
    832 	return usb_interrupt_io(dev, ep, bytes, size, timeout);
    833 }
    834 
    835 API_EXPORTED int usb_control_msg(usb_dev_handle *dev, int bmRequestType,
    836 	int bRequest, int wValue, int wIndex, char *bytes, int size, int timeout)
    837 {
    838 	int r;
    839 	usbi_dbg("RQT=%x RQ=%x V=%x I=%x len=%d timeout=%d", bmRequestType,
    840 		bRequest, wValue, wIndex, size, timeout);
    841 
    842 	r = libusb_control_transfer(dev->handle, bmRequestType & 0xff,
    843 		bRequest & 0xff, wValue & 0xffff, wIndex & 0xffff, bytes, size & 0xffff,
    844 		timeout);
    845 
    846 	if (r >= 0)
    847 		return r;
    848 
    849 	return compat_err(r);
    850 }
    851 
    852 API_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 
    863 API_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 
    874 API_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 
    884 API_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 
    899 API_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 
    914 API_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