| @@ -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 | |
3 | Fix build on Dragonfly. | | 3 | Fix build on Dragonfly. |
| | | 4 | Add 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 | +} |