Tue Nov 20 13:01:47 2012 UTC ()
Added patch from OpenBSD

Rework the OpenBSD backend to add *basic support* for non ugen(4) devices.
It is now possible to have a read access and submit control transfers to
all USB devices using libusb, please note that controllers and hubs also
appear as devices.


(pettai)
diff -r1.7 -r1.8 pkgsrc/devel/libusb1/Makefile
diff -r1.3 -r1.4 pkgsrc/devel/libusb1/distinfo
diff -r1.2 -r1.3 pkgsrc/devel/libusb1/patches/patch-libusb_os_openbsd__usb.c

cvs diff -r1.7 -r1.8 pkgsrc/devel/libusb1/Makefile (expand / switch to unified diff)

--- pkgsrc/devel/libusb1/Makefile 2012/10/31 11:17:23 1.7
+++ pkgsrc/devel/libusb1/Makefile 2012/11/20 13:01:47 1.8
@@ -1,18 +1,19 @@ @@ -1,18 +1,19 @@
1# $NetBSD: Makefile,v 1.7 2012/10/31 11:17:23 asau Exp $ 1# $NetBSD: Makefile,v 1.8 2012/11/20 13:01:47 pettai Exp $
2# 2#
3 3
4DISTNAME= libusb-1.0.9 4DISTNAME= libusb-1.0.9
5PKGNAME= ${DISTNAME:S/libusb/libusb1/} 5PKGNAME= ${DISTNAME:S/libusb/libusb1/}
 6PKGREVISION= 1
6CATEGORIES= devel 7CATEGORIES= devel
7MASTER_SITES= ${MASTER_SITE_SOURCEFORGE:=libusb/} 8MASTER_SITES= ${MASTER_SITE_SOURCEFORGE:=libusb/}
8EXTRACT_SUFX= .tar.bz2 9EXTRACT_SUFX= .tar.bz2
9 10
10MAINTAINER= pkgsrc-users@NetBSD.org 11MAINTAINER= pkgsrc-users@NetBSD.org
11HOMEPAGE= http://www.libusb.org/wiki/libusb-1.0 12HOMEPAGE= http://www.libusb.org/wiki/libusb-1.0
12COMMENT= USB Access Library (version 1) 13COMMENT= USB Access Library (version 1)
13LICENSE= gnu-lgpl-v2.1 14LICENSE= gnu-lgpl-v2.1
14 15
15NOT_FOR_PLATFORM= DragonFly-*-* SunOS-*-* 16NOT_FOR_PLATFORM= DragonFly-*-* SunOS-*-*
16 17
17GNU_CONFIGURE= yes 18GNU_CONFIGURE= yes
18USE_LIBTOOL= yes 19USE_LIBTOOL= yes

cvs diff -r1.3 -r1.4 pkgsrc/devel/libusb1/distinfo (expand / switch to unified diff)

--- pkgsrc/devel/libusb1/distinfo 2012/10/08 16:59:26 1.3
+++ pkgsrc/devel/libusb1/distinfo 2012/11/20 13:01:47 1.4
@@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
1$NetBSD: distinfo,v 1.3 2012/10/08 16:59:26 dholland Exp $ 1$NetBSD: distinfo,v 1.4 2012/11/20 13:01:47 pettai Exp $
2 2
3SHA1 (libusb-1.0.9.tar.bz2) = 025582ff2f6216e2dbc2610ae16b2e073e1b3346 3SHA1 (libusb-1.0.9.tar.bz2) = 025582ff2f6216e2dbc2610ae16b2e073e1b3346
4RMD160 (libusb-1.0.9.tar.bz2) = 5410570f8ce31783044eb04aebaae7ade3b21a61 4RMD160 (libusb-1.0.9.tar.bz2) = 5410570f8ce31783044eb04aebaae7ade3b21a61
5Size (libusb-1.0.9.tar.bz2) = 421971 bytes 5Size (libusb-1.0.9.tar.bz2) = 421971 bytes
6SHA1 (patch-configure) = 16945e970e356009d1022d9832ef3ee532435422 6SHA1 (patch-configure) = 16945e970e356009d1022d9832ef3ee532435422
7SHA1 (patch-configure.ac) = 3d8234d368409a23da0f346822bea276c6081e8b 7SHA1 (patch-configure.ac) = 3d8234d368409a23da0f346822bea276c6081e8b
8SHA1 (patch-libusb_os_openbsd__usb.c) = 2c8c5b9efe7c809120d752b49c6484edbc2cac71 8SHA1 (patch-libusb_os_openbsd__usb.c) = be31799029f8e2acf7abb6be566a51c78026479d

cvs diff -r1.2 -r1.3 pkgsrc/devel/libusb1/patches/Attic/patch-libusb_os_openbsd__usb.c (expand / switch to unified diff)

--- pkgsrc/devel/libusb1/patches/Attic/patch-libusb_os_openbsd__usb.c 2012/10/08 16:59:26 1.2
+++ pkgsrc/devel/libusb1/patches/Attic/patch-libusb_os_openbsd__usb.c 2012/11/20 13:01:47 1.3
@@ -1,18 +1,626 @@ @@ -1,18 +1,626 @@
1$NetBSD: patch-libusb_os_openbsd__usb.c,v 1.2 2012/10/08 16:59:26 dholland Exp $ 1$NetBSD: patch-libusb_os_openbsd__usb.c,v 1.3 2012/11/20 13:01:47 pettai Exp $
2 2
3Fix build on Dragonfly. 3Fix build on Dragonfly.
 4Add support for non ugen(4) attached devices through usb(4) buses.
4 5
5--- libusb/os/openbsd_usb.c.orig 2012-04-20 06:44:27.000000000 +0000 6--- libusb/os/openbsd_usb.c.orig 2012-11-20 11:50:40.000000000 +0000
6+++ libusb/os/openbsd_usb.c 7+++ libusb/os/openbsd_usb.c
7@@ -26,7 +26,11 @@ 8@@ -1,5 +1,5 @@
8 #include <string.h> 9 /*
9 #include <unistd.h> 10- * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
10  11+ * Copyright (c) 2011-2012 Martin Pieuchot <mpi@openbsd.org>
11+#ifdef __DragonFly__ 12 *
12+#include <bus/usb/usb.h> 13 * This library is free software; you can redistribute it and/or
13+#else 14 * modify it under the terms of the GNU Lesser General Public
14 #include <dev/usb/usb.h> 15@@ -36,8 +36,8 @@
15+#endif 
16  
17 #include "libusb.h" 
18 #include "libusbi.h" 16 #include "libusbi.h"
 17
 18 struct device_priv {
 19- char devnode[16];
 20- int fd;
 21+ char *devname; /* name of the ugen(4) node */
 22+ int fd; /* device file descriptor */
 23
 24 unsigned char *cdesc; /* active config descriptor */
 25 usb_device_descriptor_t ddesc; /* usb device descriptor */
 26@@ -91,6 +91,13 @@ static int _sync_control_transfer(struct
 27 static int _sync_gen_transfer(struct usbi_transfer *);
 28 static int _access_endpoint(struct libusb_transfer *);
 29
 30+static int _bus_open(int);
 31+static int _bus_get_config(int, int, int *);
 32+static int _bus_get_device_desc(int, int, usb_device_descriptor_t *);
 33+static int _bus_get_full_desc(int, int, int, int, void *);
 34+static int _bus_get_config_desc(int, int, int, usb_config_descriptor_t *);
 35+
 36+
 37 const struct usbi_os_backend openbsd_backend = {
 38 "Synchronous OpenBSD backend",
 39 NULL, /* init() */
 40@@ -132,75 +139,102 @@ const struct usbi_os_backend openbsd_bac
 41 0, /* add_iso_packet_size */
 42 };
 43
 44+#define DEVPATH "/dev/"
 45+#define USBDEV DEVPATH "usb"
 46+
 47 int
 48 obsd_get_device_list(struct libusb_context * ctx,
 49 struct discovered_devs **discdevs)
 50 {
 51+ struct discovered_devs *dd;
 52 struct libusb_device *dev;
 53 struct device_priv *dpriv;
 54 struct usb_device_info di;
 55 unsigned long session_id;
 56- char devnode[16];
 57- int fd, err, i;
 58+ char devices[USB_MAX_DEVICES];
 59+ char busnode[16];
 60+ char *udevname;
 61+ int fd, addr, i, j;
 62
 63 usbi_dbg("");
 64
 65- /* Only ugen(4) is supported */
 66- for (i = 0; i < USB_MAX_DEVICES; i++) {
 67- /* Control endpoint is always .00 */
 68- snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
 69+ for (i = 0; i < 8; i++) {
 70+ snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
 71
 72- if ((fd = open(devnode, O_RDONLY)) < 0) {
 73+ if ((fd = open(busnode, O_RDWR)) < 0) {
 74 if (errno != ENOENT && errno != ENXIO)
 75- usbi_err(ctx, "could not open %s", devnode);
 76+ usbi_err(ctx, "could not open %s", busnode);
 77 continue;
 78 }
 79
 80- if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
 81- continue;
 82-
 83- session_id = (di.udi_bus << 8 | di.udi_addr);
 84- dev = usbi_get_device_by_session_id(ctx, session_id);
 85-
 86- if (dev == NULL) {
 87- dev = usbi_alloc_device(ctx, session_id);
 88- if (dev == NULL)
 89- return (LIBUSB_ERROR_NO_MEM);
 90+ bzero(devices, sizeof(devices));
 91+ for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
 92+ if (devices[addr])
 93+ continue;
 94+
 95+ di.udi_addr = addr;
 96+ if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
 97+ continue;
 98+
 99+ /*
 100+ * XXX If ugen(4) is attached to the USB device
 101+ * it will be used.
 102+ */
 103+ udevname = NULL;
 104+ for (j = 0; j < USB_MAX_DEVNAMES; j++)
 105+ if (!strncmp("ugen", di.udi_devnames[j], 4)) {
 106+ udevname = strdup(di.udi_devnames[j]);
 107+ break;
 108+ }
 109+
 110+ session_id = (di.udi_bus << 8 | di.udi_addr);
 111+ dev = usbi_get_device_by_session_id(ctx, session_id);
 112+
 113+ if (dev == NULL) {
 114+ dev = usbi_alloc_device(ctx, session_id);
 115+ if (dev == NULL) {
 116+ close(fd);
 117+ return (LIBUSB_ERROR_NO_MEM);
 118+ }
 119+
 120+ dev->bus_number = di.udi_bus;
 121+ dev->device_address = di.udi_addr;
 122+ dev->speed = di.udi_speed;
 123+
 124+ dpriv = (struct device_priv *)dev->os_priv;
 125+ dpriv->fd = -1;
 126+ dpriv->cdesc = NULL;
 127+ dpriv->devname = udevname;
 128+
 129+ if (_bus_get_device_desc(fd, addr, &dpriv->ddesc)) {
 130+ libusb_unref_device(dev);
 131+ continue;
 132+ }
 133+
 134+ /* XXX Assume the active config is at index 0 */
 135+ if (_cache_active_config_descriptor(dev, 0)) {
 136+ libusb_unref_device(dev);
 137+ continue;
 138+ }
 139
 140- dev->bus_number = di.udi_bus;
 141- dev->device_address = di.udi_addr;
 142- dev->speed = di.udi_speed;
 143-
 144- dpriv = (struct device_priv *)dev->os_priv;
 145- strlcpy(dpriv->devnode, devnode, sizeof(devnode));
 146- dpriv->fd = -1;
 147-
 148- if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
 149- err = errno;
 150- goto error;
 151+ if (usbi_sanitize_device(dev))
 152+ libusb_unref_device(dev);
 153 }
 154
 155- dpriv->cdesc = NULL;
 156- if (_cache_active_config_descriptor(dev, fd)) {
 157- err = errno;
 158- goto error;
 159+ dd = discovered_devs_append(*discdevs, dev);
 160+ if (dd == NULL) {
 161+ close(fd);
 162+ return (LIBUSB_ERROR_NO_MEM);
 163 }
 164
 165- if ((err = usbi_sanitize_device(dev)))
 166- goto error;
 167+ *discdevs = dd;
 168+ devices[addr] = 1;
 169 }
 170- close(fd);
 171
 172- if (discovered_devs_append(*discdevs, dev) == NULL)
 173- return (LIBUSB_ERROR_NO_MEM);
 174+ close(fd);
 175 }
 176
 177 return (LIBUSB_SUCCESS);
 178-
 179-error:
 180- close(fd);
 181- libusb_unref_device(dev);
 182- return _errno_to_libusb(err);
 183 }
 184
 185 int
 186@@ -208,15 +242,21 @@ obsd_open(struct libusb_device_handle *h
 187 {
 188 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 189 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 190+ char devnode[16];
 191
 192- dpriv->fd = open(dpriv->devnode, O_RDWR);
 193- if (dpriv->fd < 0) {
 194- dpriv->fd = open(dpriv->devnode, O_RDONLY);
 195+ if (dpriv->devname) {
 196+ /*
 197+ * Only open ugen(4) attached devices read-write, all
 198+ * read-only operations are done through the bus node.
 199+ */
 200+ snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
 201+ dpriv->devname);
 202+ dpriv->fd = open(devnode, O_RDWR);
 203 if (dpriv->fd < 0)
 204 return _errno_to_libusb(errno);
 205- }
 206
 207- usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
 208+ usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
 209+ }
 210
 211 if (pipe(hpriv->pipe) < 0)
 212 return _errno_to_libusb(errno);
 213@@ -230,10 +270,12 @@ obsd_close(struct libusb_device_handle *
 214 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 215 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 216
 217- usbi_dbg("close: fd %d", dpriv->fd);
 218+ if (dpriv->devname) {
 219+ usbi_dbg("close: fd %d", dpriv->fd);
 220
 221- close(dpriv->fd);
 222- dpriv->fd = -1;
 223+ close(dpriv->fd);
 224+ dpriv->fd = -1;
 225+ }
 226
 227 usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
 228
 229@@ -279,34 +321,19 @@ int
 230 obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
 231 unsigned char *buf, size_t len, int *host_endian)
 232 {
 233- struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 234- struct usb_full_desc ufd;
 235 int fd, err;
 236
 237- usbi_dbg("index %d, len %d", idx, len);
 238-
 239- /* A config descriptor may be requested before opening the device */
 240- if (dpriv->fd >= 0) {
 241- fd = dpriv->fd;
 242- } else {
 243- fd = open(dpriv->devnode, O_RDONLY);
 244- if (fd < 0)
 245- return _errno_to_libusb(errno);
 246- }
 247+ if ((fd = _bus_open(dev->bus_number)) < 0)
 248+ return _errno_to_libusb(errno);
 249
 250- ufd.ufd_config_index = idx;
 251- ufd.ufd_size = len;
 252- ufd.ufd_data = buf;
 253+ usbi_dbg("index %d, len %d", idx, len);
 254
 255- if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
 256+ if (_bus_get_full_desc(fd, dev->device_address, idx, len, buf)) {
 257 err = errno;
 258- if (dpriv->fd < 0)
 259- close(fd);
 260+ close(fd);
 261 return _errno_to_libusb(err);
 262 }
 263-
 264- if (dpriv->fd < 0)
 265- close(fd);
 266+ close(fd);
 267
 268 *host_endian = 0;
 269
 270@@ -316,14 +343,19 @@ obsd_get_config_descriptor(struct libusb
 271 int
 272 obsd_get_configuration(struct libusb_device_handle *handle, int *config)
 273 {
 274- struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 275-
 276- usbi_dbg("");
 277+ int fd, err;
 278
 279- if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
 280+ if ((fd = _bus_open(handle->dev->bus_number)) < 0)
 281 return _errno_to_libusb(errno);
 282
 283- usbi_dbg("configuration %d", *config);
 284+ if (_bus_get_config(fd, handle->dev->device_address, config)) {
 285+ err = errno;
 286+ close(fd);
 287+ return _errno_to_libusb(err);
 288+ }
 289+ close(fd);
 290+
 291+ usbi_dbg("bConfigurationValue %d", *config);
 292
 293 return (LIBUSB_SUCCESS);
 294 }
 295@@ -332,13 +364,23 @@ int
 296 obsd_set_configuration(struct libusb_device_handle *handle, int config)
 297 {
 298 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 299+ int idx;
 300
 301- usbi_dbg("configuration %d", config);
 302+ if (dpriv->devname == NULL)
 303+ return (LIBUSB_ERROR_NOT_SUPPORTED);
 304+
 305+ usbi_dbg("bConfigurationValue %d", config);
 306
 307 if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
 308 return _errno_to_libusb(errno);
 309
 310- return _cache_active_config_descriptor(handle->dev, dpriv->fd);
 311+ /*
 312+ * XXX Instead of assuming that the index is at bConfigurationValue
 313+ * minus one, we should iterate against the possible configurations.
 314+ */
 315+ idx = config - 1;
 316+
 317+ return _cache_active_config_descriptor(handle->dev, idx);
 318 }
 319
 320 int
 321@@ -373,6 +415,9 @@ obsd_set_interface_altsetting(struct lib
 322 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 323 struct usb_alt_interface intf;
 324
 325+ if (dpriv->devname == NULL)
 326+ return (LIBUSB_ERROR_NOT_SUPPORTED);
 327+
 328 usbi_dbg("iface %d, setting %d", iface, altsetting);
 329
 330 memset(&intf, 0, sizeof(intf));
 331@@ -389,19 +434,27 @@ obsd_set_interface_altsetting(struct lib
 332 int
 333 obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
 334 {
 335- struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 336 struct usb_ctl_request req;
 337+ int fd, err;
 338+
 339+ if ((fd = _bus_open(handle->dev->bus_number)) < 0)
 340+ return _errno_to_libusb(errno);
 341
 342 usbi_dbg("");
 343
 344+ req.ucr_addr = handle->dev->device_address;
 345 req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
 346 req.ucr_request.bRequest = UR_CLEAR_FEATURE;
 347 USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
 348 USETW(req.ucr_request.wIndex, endpoint);
 349 USETW(req.ucr_request.wLength, 0);
 350
 351- if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
 352- return _errno_to_libusb(errno);
 353+ if (ioctl(fd, USB_REQUEST, &req) < 0) {
 354+ err = errno;
 355+ close(fd);
 356+ return _errno_to_libusb(err);
 357+ }
 358+ close(fd);
 359
 360 return (LIBUSB_SUCCESS);
 361 }
 362@@ -422,6 +475,7 @@ obsd_destroy_device(struct libusb_device
 363 usbi_dbg("");
 364
 365 free(dpriv->cdesc);
 366+ free(dpriv->devname);
 367 }
 368
 369 int
 370@@ -561,6 +615,8 @@ obsd_clock_gettime(int clkid, struct tim
 371 int
 372 _errno_to_libusb(int err)
 373 {
 374+ usbi_dbg("error: %s (%d)", strerror(err), err);
 375+
 376 switch (err) {
 377 case EIO:
 378 return (LIBUSB_ERROR_IO);
 379@@ -570,52 +626,52 @@ _errno_to_libusb(int err)
 380 return (LIBUSB_ERROR_NO_DEVICE);
 381 case ENOMEM:
 382 return (LIBUSB_ERROR_NO_MEM);
 383+ case ETIMEDOUT:
 384+ return (LIBUSB_ERROR_TIMEOUT);
 385 }
 386
 387- usbi_dbg("error: %s", strerror(err));
 388-
 389 return (LIBUSB_ERROR_OTHER);
 390 }
 391
 392 int
 393-_cache_active_config_descriptor(struct libusb_device *dev, int fd)
 394+_cache_active_config_descriptor(struct libusb_device *dev, int idx)
 395 {
 396 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
 397- struct usb_config_desc ucd;
 398- struct usb_full_desc ufd;
 399+ usb_config_descriptor_t cdesc;
 400 unsigned char* buf;
 401- int len;
 402+ int fd, len, err;
 403
 404- usbi_dbg("fd %d", fd);
 405+ if ((fd = _bus_open(dev->bus_number)) < 0)
 406+ return _errno_to_libusb(errno);
 407
 408- ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
 409+ usbi_dbg("fd %d, addr %d", fd, dev->device_address);
 410
 411- if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
 412+ if (_bus_get_config_desc(fd, dev->device_address, idx, &cdesc)) {
 413+ err = errno;
 414+ close(fd);
 415 return _errno_to_libusb(errno);
 416+ }
 417
 418- usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
 419+ usbi_dbg("active bLength %d", cdesc.bLength);
 420
 421- len = UGETW(ucd.ucd_desc.wTotalLength);
 422+ len = UGETW(cdesc.wTotalLength);
 423 buf = malloc(len);
 424 if (buf == NULL)
 425 return (LIBUSB_ERROR_NO_MEM);
 426
 427- ufd.ufd_config_index = ucd.ucd_config_index;
 428- ufd.ufd_size = len;
 429- ufd.ufd_data = buf;
 430-
 431- usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
 432-
 433- if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
 434+ if (_bus_get_full_desc(fd, dev->device_address, idx, len, buf)) {
 435+ err = errno;
 436+ close(fd);
 437 free(buf);
 438- return _errno_to_libusb(errno);
 439+ return _errno_to_libusb(err);
 440 }
 441+ close(fd);
 442
 443 if (dpriv->cdesc)
 444 free(dpriv->cdesc);
 445 dpriv->cdesc = buf;
 446
 447- return (0);
 448+ return (LIBUSB_SUCCESS);
 449 }
 450
 451 int
 452@@ -630,12 +686,13 @@ _sync_control_transfer(struct usbi_trans
 453 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 454 setup = (struct libusb_control_setup *)transfer->buffer;
 455
 456- usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
 457+ usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
 458 setup->bmRequestType, setup->bRequest,
 459 libusb_le16_to_cpu(setup->wValue),
 460 libusb_le16_to_cpu(setup->wIndex),
 461 libusb_le16_to_cpu(setup->wLength), transfer->timeout);
 462
 463+ req.ucr_addr = transfer->dev_handle->dev->device_address;
 464 req.ucr_request.bmRequestType = setup->bmRequestType;
 465 req.ucr_request.bRequest = setup->bRequest;
 466 /* Don't use USETW, libusb already deals with the endianness */
 467@@ -647,11 +704,30 @@ _sync_control_transfer(struct usbi_trans
 468 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
 469 req.ucr_flags = USBD_SHORT_XFER_OK;
 470
 471- if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
 472- return _errno_to_libusb(errno);
 473+ if (dpriv->devname == NULL) {
 474+ /*
 475+ * XXX If the device is not attached to ugen(4) it is
 476+ * XXX still possible to submit a control transfer but
 477+ * XXX with the default timeout only.
 478+ */
 479+ int fd, err;
 480
 481- if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
 482- return _errno_to_libusb(errno);
 483+ if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
 484+ return _errno_to_libusb(errno);
 485+
 486+ if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
 487+ err = errno;
 488+ close(fd);
 489+ return _errno_to_libusb(err);
 490+ }
 491+ close(fd);
 492+ } else {
 493+ if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
 494+ return _errno_to_libusb(errno);
 495+
 496+ if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
 497+ return _errno_to_libusb(errno);
 498+ }
 499
 500 itransfer->transferred = req.ucr_actlen;
 501
 502@@ -665,7 +741,7 @@ _access_endpoint(struct libusb_transfer
 503 {
 504 struct handle_priv *hpriv;
 505 struct device_priv *dpriv;
 506- char *s, devnode[16];
 507+ char devnode[16];
 508 int fd, endpt;
 509 mode_t mode;
 510
 511@@ -678,10 +754,9 @@ _access_endpoint(struct libusb_transfer
 512 usbi_dbg("endpoint %d mode %d", endpt, mode);
 513
 514 if (hpriv->endpoints[endpt] < 0) {
 515- /* Pick the right node given the control one */
 516- strlcpy(devnode, dpriv->devnode, sizeof(devnode));
 517- s = strchr(devnode, '.');
 518- snprintf(s, 4, ".%02d", endpt);
 519+ /* Pick the right endpoint node */
 520+ snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
 521+ dpriv->devname, endpt);
 522
 523 /* We may need to read/write to the same endpoint later. */
 524 if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
 525@@ -698,9 +773,14 @@ int
 526 _sync_gen_transfer(struct usbi_transfer *itransfer)
 527 {
 528 struct libusb_transfer *transfer;
 529+ struct device_priv *dpriv;
 530 int fd, nr = 1;
 531
 532 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 533+ dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
 534+
 535+ if (dpriv->devname == NULL)
 536+ return (LIBUSB_ERROR_NOT_SUPPORTED);
 537
 538 /*
 539 * Bulk, Interrupt or Isochronous transfer depends on the
 540@@ -729,3 +809,86 @@ _sync_gen_transfer(struct usbi_transfer
 541
 542 return (0);
 543 }
 544+
 545+int
 546+_bus_open(int number)
 547+{
 548+ char busnode[16];
 549+
 550+ snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
 551+
 552+ return open(busnode, O_RDWR);
 553+}
 554+
 555+int
 556+_bus_get_config(int fd, int addr, int *config)
 557+{
 558+ struct usb_ctl_request req;
 559+ uint8_t conf;
 560+ int err;
 561+
 562+ usbi_dbg("");
 563+
 564+ req.ucr_addr = addr;
 565+ req.ucr_request.bmRequestType = UT_READ_DEVICE;
 566+ req.ucr_request.bRequest = UR_GET_CONFIG;
 567+ USETW(req.ucr_request.wValue, 0);
 568+ USETW(req.ucr_request.wIndex, 0);
 569+ USETW(req.ucr_request.wLength, 1);
 570+ req.ucr_data = &conf;
 571+ req.ucr_flags = 0;
 572+
 573+ err = ioctl(fd, USB_REQUEST, &req);
 574+
 575+ *config = conf;
 576+
 577+ return (err);
 578+}
 579+
 580+static int
 581+_bus_get_desc(int fd, int addr, uint8_t type, uint8_t idx, int len, void *desc)
 582+{
 583+ struct usb_ctl_request req;
 584+
 585+ usbi_dbg("addr %d type %d index %d len %d", addr, type, idx, len);
 586+
 587+ req.ucr_addr = addr;
 588+ req.ucr_request.bmRequestType = UT_READ_DEVICE;
 589+ req.ucr_request.bRequest = UR_GET_DESCRIPTOR;
 590+ USETW2(req.ucr_request.wValue, type, idx);
 591+ USETW(req.ucr_request.wIndex, 0);
 592+ USETW(req.ucr_request.wLength, len);
 593+ req.ucr_data = desc;
 594+ req.ucr_flags = 0;
 595+
 596+ if (ioctl(fd, USB_REQUEST, &req) < 0)
 597+ return _errno_to_libusb(errno);
 598+
 599+ return (0);
 600+}
 601+
 602+int
 603+_bus_get_device_desc(int fd, int addr, usb_device_descriptor_t *ddesc)
 604+{
 605+ usbi_dbg("");
 606+
 607+ return _bus_get_desc(fd, addr, UDESC_DEVICE, 0,
 608+ USB_DEVICE_DESCRIPTOR_SIZE, ddesc);
 609+}
 610+
 611+int
 612+_bus_get_config_desc(int fd, int addr, int idx, usb_config_descriptor_t *cdesc)
 613+{
 614+ usbi_dbg("config index %d", idx);
 615+
 616+ return _bus_get_desc(fd, addr, UDESC_CONFIG, idx,
 617+ USB_CONFIG_DESCRIPTOR_SIZE, cdesc);
 618+}
 619+
 620+int
 621+_bus_get_full_desc(int fd, int addr, int idx, int size, void *desc)
 622+{
 623+ usbi_dbg("config index %d size %d", idx, size);
 624+
 625+ return _bus_get_desc(fd, addr, UDESC_CONFIG, idx, size, desc);
 626+}