1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/* 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org> 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * This library is free software; you can redistribute it and/or 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * modify it under the terms of the GNU Lesser General Public 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * License as published by the Free Software Foundation; either 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * version 2.1 of the License, or (at your option) any later version. 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * This library is distributed in the hope that it will be useful, 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Lesser General Public License for more details. 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * You should have received a copy of the GNU Lesser General Public 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * License along with this library; if not, write to the Free Software 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <sys/time.h> 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <sys/types.h> 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <errno.h> 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <fcntl.h> 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdio.h> 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdlib.h> 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string.h> 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <unistd.h> 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <dev/usb/usb.h> 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "libusb.h" 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "libusbi.h" 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct device_priv { 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char *devname; /* name of the ugen(4) node */ 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int fd; /* device file descriptor */ 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char *cdesc; /* active config descriptor */ 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usb_device_descriptor_t ddesc; /* usb device descriptor */ 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct handle_priv { 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int pipe[2]; /* for event notification */ 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int endpoints[USB_MAX_ENDPOINTS]; 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/* 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Backend functions 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_get_device_list(struct libusb_context *, 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct discovered_devs **); 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_open(struct libusb_device_handle *); 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void obsd_close(struct libusb_device_handle *); 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_get_device_descriptor(struct libusb_device *, unsigned char *, 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int *); 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_get_active_config_descriptor(struct libusb_device *, 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char *, size_t, int *); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_get_config_descriptor(struct libusb_device *, uint8_t, 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char *, size_t, int *); 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_get_configuration(struct libusb_device_handle *, int *); 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_set_configuration(struct libusb_device_handle *, int); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_claim_interface(struct libusb_device_handle *, int); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_release_interface(struct libusb_device_handle *, int); 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_set_interface_altsetting(struct libusb_device_handle *, int, 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int); 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_clear_halt(struct libusb_device_handle *, unsigned char); 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_reset_device(struct libusb_device_handle *); 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void obsd_destroy_device(struct libusb_device *); 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_submit_transfer(struct usbi_transfer *); 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_cancel_transfer(struct usbi_transfer *); 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void obsd_clear_transfer_priv(struct usbi_transfer *); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_handle_events(struct libusb_context *ctx, struct pollfd *, 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nfds_t, int); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int obsd_clock_gettime(int, struct timespec *); 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/* 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Private functions 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int _errno_to_libusb(int); 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static int _cache_active_config_descriptor(struct libusb_device *); 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int _sync_control_transfer(struct usbi_transfer *); 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int _sync_gen_transfer(struct usbi_transfer *); 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int _access_endpoint(struct libusb_transfer *); 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static int _bus_open(int); 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst struct usbi_os_backend openbsd_backend = { 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Synchronous OpenBSD backend", 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 0, 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, /* init() */ 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, /* exit() */ 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_get_device_list, 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL, /* hotplug_poll */ 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_open, 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_close, 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_get_device_descriptor, 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_get_active_config_descriptor, 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_get_config_descriptor, 106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL, /* get_config_descriptor_by_value() */ 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_get_configuration, 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_set_configuration, 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_claim_interface, 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_release_interface, 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_set_interface_altsetting, 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_clear_halt, 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_reset_device, 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, /* kernel_driver_active() */ 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, /* detach_kernel_driver() */ 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, /* attach_kernel_driver() */ 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_destroy_device, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_submit_transfer, 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_cancel_transfer, 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_clear_transfer_priv, 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_handle_events, 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch obsd_clock_gettime, 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sizeof(struct device_priv), 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sizeof(struct handle_priv), 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, /* transfer_priv_size */ 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, /* add_iso_packet_size */ 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define DEVPATH "/dev/" 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define USBDEV DEVPATH "usb" 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_get_device_list(struct libusb_context * ctx, 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct discovered_devs **discdevs) 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct discovered_devs *ddd; 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_device *dev; 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv; 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct usb_device_info di; 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct usb_device_ddesc dd; 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned long session_id; 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char devices[USB_MAX_DEVICES]; 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char busnode[16]; 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char *udevname; 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int fd, addr, i, j; 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (i = 0; i < 8; i++) { 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) snprintf(busnode, sizeof(busnode), USBDEV "%d", i); 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((fd = open(busnode, O_RDWR)) < 0) { 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (errno != ENOENT && errno != ENXIO) 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_err(ctx, "could not open %s", busnode); 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bzero(devices, sizeof(devices)); 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (addr = 1; addr < USB_MAX_DEVICES; addr++) { 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (devices[addr]) 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) di.udi_addr = addr; 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_DEVICEINFO, &di) < 0) 17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /* 17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * XXX If ugen(4) is attached to the USB device 17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * it will be used. 17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udevname = NULL; 18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (j = 0; j < USB_MAX_DEVNAMES; j++) 18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!strncmp("ugen", di.udi_devnames[j], 4)) { 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udevname = strdup(di.udi_devnames[j]); 18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) session_id = (di.udi_bus << 8 | di.udi_addr); 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev = usbi_get_device_by_session_id(ctx, session_id); 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dev == NULL) { 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev = usbi_alloc_device(ctx, session_id); 19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dev == NULL) { 19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_NO_MEM); 19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev->bus_number = di.udi_bus; 19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev->device_address = di.udi_addr; 19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev->speed = di.udi_speed; 19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv = (struct device_priv *)dev->os_priv; 20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->fd = -1; 20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->cdesc = NULL; 20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->devname = udevname; 20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dd.udd_bus = di.udi_bus; 20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dd.udd_addr = di.udi_addr; 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) { 20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) libusb_unref_device(dev); 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->ddesc = dd.udd_desc; 21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (_cache_active_config_descriptor(dev)) { 21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) libusb_unref_device(dev); 21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (usbi_sanitize_device(dev)) 21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) libusb_unref_device(dev); 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ddd = discovered_devs_append(*discdevs, dev); 22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ddd == NULL) { 22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_NO_MEM); 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *discdevs = ddd; 22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) devices[addr] = 1; 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_open(struct libusb_device_handle *handle) 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char devnode[16]; 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname) { 24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /* 24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Only open ugen(4) attached devices read-write, all 24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * read-only operations are done through the bus node. 24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", 25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->devname); 25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->fd = open(devnode, O_RDWR); 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (dpriv->fd < 0) 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("open %s: fd %d", devnode, dpriv->fd); 25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (pipe(hpriv->pipe) < 0) 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN); 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_close(struct libusb_device_handle *handle) 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname) { 27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("close: fd %d", dpriv->fd); 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(dpriv->fd); 27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->fd = -1; 27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch close(hpriv->pipe[0]); 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch close(hpriv->pipe[1]); 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, 286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int *host_endian) 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *host_endian = 0; 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_get_active_config_descriptor(struct libusb_device *dev, 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char *buf, size_t len, int *host_endian) 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch len = MIN(len, UGETW(ucd->wTotalLength)); 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("len %d", len); 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memcpy(buf, dpriv->cdesc, len); 311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *host_endian = 0; 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (len); 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char *buf, size_t len, int *host_endian) 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct usb_device_fdesc udf; 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int fd, err; 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((fd = _bus_open(dev->bus_number)) < 0) 32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_bus = dev->bus_number; 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_addr = dev->device_address; 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_config_index = idx; 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_size = len; 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_data = buf; 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("index %d, len %d", udf.udf_config_index, len); 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = errno; 33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(err); 339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *host_endian = 0; 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (len); 345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_get_configuration(struct libusb_device_handle *handle, int *config) 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; 352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *config = ucd->bConfigurationValue; 354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("bConfigurationValue %d", *config); 356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_set_configuration(struct libusb_device_handle *handle, int config) 362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname == NULL) 36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_NOT_SUPPORTED); 36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("bConfigurationValue %d", config); 369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) 371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _cache_active_config_descriptor(handle->dev); 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_claim_interface(struct libusb_device_handle *handle, int iface) 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int i; 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (i = 0; i < USB_MAX_ENDPOINTS; i++) 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv->endpoints[i] = -1; 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_release_interface(struct libusb_device_handle *handle, int iface) 390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int i; 393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (i = 0; i < USB_MAX_ENDPOINTS; i++) 395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (hpriv->endpoints[i] >= 0) 396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch close(hpriv->endpoints[i]); 397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int altsetting) 404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct usb_alt_interface intf; 407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname == NULL) 40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_NOT_SUPPORTED); 41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("iface %d, setting %d", iface, altsetting); 412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memset(&intf, 0, sizeof(intf)); 414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch intf.uai_interface_index = iface; 416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch intf.uai_alt_no = altsetting; 417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) 419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) 426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct usb_ctl_request req; 42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int fd, err; 42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((fd = _bus_open(handle->dev->bus_number)) < 0) 43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) req.ucr_addr = handle->dev->device_address; 436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; 437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_request.bRequest = UR_CLEAR_FEATURE; 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); 439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch USETW(req.ucr_request.wIndex, endpoint); 440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch USETW(req.ucr_request.wLength, 0); 441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_REQUEST, &req) < 0) { 44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) err = errno; 44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(err); 44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_reset_device(struct libusb_device_handle *handle) 454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_NOT_SUPPORTED); 458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_destroy_device(struct libusb_device *dev) 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch free(dpriv->cdesc); 46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) free(dpriv->devname); 469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_submit_transfer(struct usbi_transfer *itransfer) 473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_transfer *transfer; 475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv; 476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int err = 0; 477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (transfer->type) { 484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case LIBUSB_TRANSFER_TYPE_CONTROL: 485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = _sync_control_transfer(itransfer); 486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFEROUT(transfer)) { 489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Isochronous write is not supported */ 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = LIBUSB_ERROR_NOT_SUPPORTED; 491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = _sync_gen_transfer(itransfer); 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case LIBUSB_TRANSFER_TYPE_BULK: 496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case LIBUSB_TRANSFER_TYPE_INTERRUPT: 497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFEROUT(transfer) && 498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { 499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = LIBUSB_ERROR_NOT_SUPPORTED; 500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = _sync_gen_transfer(itransfer); 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (err) 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (err); 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) 510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_cancel_transfer(struct usbi_transfer *itransfer) 517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_NOT_SUPPORTED); 521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid 524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_clear_transfer_priv(struct usbi_transfer *itransfer) 525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Nothing to do */ 529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, 533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int num_ready) 534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_device_handle *handle; 536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv = NULL; 537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct usbi_transfer *itransfer; 538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct pollfd *pollfd; 539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int i, err = 0; 540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg(""); 542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pthread_mutex_lock(&ctx->open_devs_lock); 544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (i = 0; i < nfds && num_ready > 0; i++) { 545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pollfd = &fds[i]; 546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!pollfd->revents) 548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv = NULL; 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_ready--; 552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch list_for_each_entry(handle, &ctx->open_devs, list, 553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_device_handle) { 554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv = (struct handle_priv *)handle->os_priv; 555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (hpriv->pipe[0] == pollfd->fd) 557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv = NULL; 560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (NULL == hpriv) { 563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("fd %d is not an event pipe!", pollfd->fd); 564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = ENOENT; 565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (pollfd->revents & POLLERR) { 569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); 570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_handle_disconnect(handle); 571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) { 575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch err = errno; 576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((err = usbi_handle_transfer_completion(itransfer, 580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LIBUSB_TRANSFER_COMPLETED))) 581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pthread_mutex_unlock(&ctx->open_devs_lock); 584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (err) 586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(err); 587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_SUCCESS); 589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochobsd_clock_gettime(int clkid, struct timespec *tp) 593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("clock %d", clkid); 595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (clkid == USBI_CLOCK_REALTIME) 597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return clock_gettime(CLOCK_REALTIME, tp); 598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (clkid == USBI_CLOCK_MONOTONIC) 600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return clock_gettime(CLOCK_MONOTONIC, tp); 601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_INVALID_PARAM); 603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch_errno_to_libusb(int err) 607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 60868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("error: %s (%d)", strerror(err), err); 60968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (err) { 611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case EIO: 612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_IO); 613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case EACCES: 614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_ACCESS); 615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ENOENT: 616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_NO_DEVICE); 617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ENOMEM: 618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_NO_MEM); 61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case ETIMEDOUT: 62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_TIMEOUT); 621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_OTHER); 624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)_cache_active_config_descriptor(struct libusb_device *dev) 628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct usb_device_cdesc udc; 63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct usb_device_fdesc udf; 632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char* buf; 63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int fd, len, err; 634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((fd = _bus_open(dev->bus_number)) < 0) 63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 63868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("fd %d, addr %d", fd, dev->device_address); 639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 64068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udc.udc_bus = dev->bus_number; 64168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udc.udc_addr = dev->device_address; 64268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udc.udc_config_index = USB_CURRENT_CONFIG_INDEX; 64368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) { 64468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) err = errno; 64568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 64768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("active bLength %d", udc.udc_desc.bLength); 650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) len = UGETW(udc.udc_desc.wTotalLength); 652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch buf = malloc(len); 653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (buf == NULL) 654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (LIBUSB_ERROR_NO_MEM); 655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_bus = dev->bus_number; 65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_addr = dev->device_address; 65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_config_index = udc.udc_config_index; 65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_size = len; 66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) udf.udf_data = buf; 661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("index %d, len %d", udf.udf_config_index, len); 663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { 66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) err = errno; 66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch free(buf); 66868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(err); 669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 67068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (dpriv->cdesc) 673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch free(dpriv->cdesc); 674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dpriv->cdesc = buf; 675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_SUCCESS); 677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch_sync_control_transfer(struct usbi_transfer *itransfer) 681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_transfer *transfer; 683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_control_setup *setup; 684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv; 685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct usb_ctl_request req; 686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; 689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch setup = (struct libusb_control_setup *)transfer->buffer; 690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("type %x request %x value %x index %d length %d timeout %d", 692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch setup->bmRequestType, setup->bRequest, 693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch libusb_le16_to_cpu(setup->wValue), 694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch libusb_le16_to_cpu(setup->wIndex), 695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch libusb_le16_to_cpu(setup->wLength), transfer->timeout); 696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) req.ucr_addr = transfer->dev_handle->dev->device_address; 698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_request.bmRequestType = setup->bmRequestType; 699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_request.bRequest = setup->bRequest; 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Don't use USETW, libusbx already deals with the endianness */ 701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; 702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; 703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; 704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) 707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch req.ucr_flags = USBD_SHORT_XFER_OK; 708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 70968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname == NULL) { 71068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /* 71168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * XXX If the device is not attached to ugen(4) it is 71268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * XXX still possible to submit a control transfer but 71368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * XXX with the default timeout only. 71468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 71568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int fd, err; 716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 71768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) 71868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 71968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 72068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((ioctl(fd, USB_REQUEST, &req)) < 0) { 72168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) err = errno; 72268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 72368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(err); 72468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 72568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close(fd); 72668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 72768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) 72868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 72968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 73068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) 73168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return _errno_to_libusb(errno); 73268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch itransfer->transferred = req.ucr_actlen; 735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("transferred %d", itransfer->transferred); 737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (0); 739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch_access_endpoint(struct libusb_transfer *transfer) 743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct handle_priv *hpriv; 745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct device_priv *dpriv; 74668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char devnode[16]; 747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int fd, endpt; 748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode_t mode; 749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; 751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; 752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch endpt = UE_GET_ADDR(transfer->endpoint); 754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; 755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_dbg("endpoint %d mode %d", endpt, mode); 757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (hpriv->endpoints[endpt] < 0) { 75968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /* Pick the right endpoint node */ 76068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d", 76168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv->devname, endpt); 762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* We may need to read/write to the same endpoint later. */ 764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) 765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((fd = open(devnode, mode)) < 0) 766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (-1); 767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch hpriv->endpoints[endpt] = fd; 769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (hpriv->endpoints[endpt]); 772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint 775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch_sync_gen_transfer(struct usbi_transfer *itransfer) 776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct libusb_transfer *transfer; 77868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct device_priv *dpriv; 779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int fd, nr = 1; 780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 78268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; 78368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 78468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dpriv->devname == NULL) 78568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (LIBUSB_ERROR_NOT_SUPPORTED); 786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* 788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Bulk, Interrupt or Isochronous transfer depends on the 789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * endpoint and thus the node to open. 790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((fd = _access_endpoint(transfer)) < 0) 792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) 795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFERIN(transfer)) { 798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) 799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) 800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nr = read(fd, transfer->buffer, transfer->length); 803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nr = write(fd, transfer->buffer, transfer->length); 805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (nr < 0) 808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return _errno_to_libusb(errno); 809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch itransfer->transferred = nr; 811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (0); 813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 81468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 81568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int 81668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)_bus_open(int number) 81768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles){ 81868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char busnode[16]; 81968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 82068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) snprintf(busnode, sizeof(busnode), USBDEV "%d", number); 82168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 82268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return open(busnode, O_RDWR); 82368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 824