1 /*
2 * Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <config.h>
20
21 #include <sys/time.h>
22 #include <sys/types.h>
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include <dev/usb/usb.h>
32
33 #include "libusbi.h"
34
35 struct device_priv {
36 char *devname; /* name of the ugen(4) node */
37 int fd; /* device file descriptor */
38
39 unsigned char *cdesc; /* active config descriptor */
40 usb_device_descriptor_t ddesc; /* usb device descriptor */
41 };
42
43 struct handle_priv {
44 int endpoints[USB_MAX_ENDPOINTS];
45 };
46
47 /*
48 * Backend functions
49 */
50 static int obsd_get_device_list(struct libusb_context *,
51 struct discovered_devs **);
52 static int obsd_open(struct libusb_device_handle *);
53 static void obsd_close(struct libusb_device_handle *);
54
55 static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *,
56 int *);
57 static int obsd_get_active_config_descriptor(struct libusb_device *,
58 unsigned char *, size_t, int *);
59 static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
60 unsigned char *, size_t, int *);
61
62 static int obsd_get_configuration(struct libusb_device_handle *, int *);
63 static int obsd_set_configuration(struct libusb_device_handle *, int);
64
65 static int obsd_claim_interface(struct libusb_device_handle *, int);
66 static int obsd_release_interface(struct libusb_device_handle *, int);
67
68 static int obsd_set_interface_altsetting(struct libusb_device_handle *, int,
69 int);
70 static int obsd_clear_halt(struct libusb_device_handle *, unsigned char);
71 static int obsd_reset_device(struct libusb_device_handle *);
72 static void obsd_destroy_device(struct libusb_device *);
73
74 static int obsd_submit_transfer(struct usbi_transfer *);
75 static int obsd_cancel_transfer(struct usbi_transfer *);
76 static void obsd_clear_transfer_priv(struct usbi_transfer *);
77 static int obsd_handle_transfer_completion(struct usbi_transfer *);
78 static int obsd_clock_gettime(int, struct timespec *);
79
80 /*
81 * Private functions
82 */
83 static int _errno_to_libusb(int);
84 static int _cache_active_config_descriptor(struct libusb_device *);
85 static int _sync_control_transfer(struct usbi_transfer *);
86 static int _sync_gen_transfer(struct usbi_transfer *);
87 static int _access_endpoint(struct libusb_transfer *);
88
89 static int _bus_open(int);
90
91
92 const struct usbi_os_backend openbsd_backend = {
93 "Synchronous OpenBSD backend",
94 0,
95 NULL, /* init() */
96 NULL, /* exit() */
97 obsd_get_device_list,
98 NULL, /* hotplug_poll */
99 obsd_open,
100 obsd_close,
101
102 obsd_get_device_descriptor,
103 obsd_get_active_config_descriptor,
104 obsd_get_config_descriptor,
105 NULL, /* get_config_descriptor_by_value() */
106
107 obsd_get_configuration,
108 obsd_set_configuration,
109
110 obsd_claim_interface,
111 obsd_release_interface,
112
113 obsd_set_interface_altsetting,
114 obsd_clear_halt,
115 obsd_reset_device,
116
117 NULL, /* alloc_streams */
118 NULL, /* free_streams */
119
120 NULL, /* dev_mem_alloc() */
121 NULL, /* dev_mem_free() */
122
123 NULL, /* kernel_driver_active() */
124 NULL, /* detach_kernel_driver() */
125 NULL, /* attach_kernel_driver() */
126
127 obsd_destroy_device,
128
129 obsd_submit_transfer,
130 obsd_cancel_transfer,
131 obsd_clear_transfer_priv,
132
133 NULL, /* handle_events() */
134 obsd_handle_transfer_completion,
135
136 obsd_clock_gettime,
137 sizeof(struct device_priv),
138 sizeof(struct handle_priv),
139 0, /* transfer_priv_size */
140 };
141
142 #define DEVPATH "/dev/"
143 #define USBDEV DEVPATH "usb"
144
145 int
obsd_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)146 obsd_get_device_list(struct libusb_context * ctx,
147 struct discovered_devs **discdevs)
148 {
149 struct discovered_devs *ddd;
150 struct libusb_device *dev;
151 struct device_priv *dpriv;
152 struct usb_device_info di;
153 struct usb_device_ddesc dd;
154 unsigned long session_id;
155 char devices[USB_MAX_DEVICES];
156 char busnode[16];
157 char *udevname;
158 int fd, addr, i, j;
159
160 usbi_dbg("");
161
162 for (i = 0; i < 8; i++) {
163 snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
164
165 if ((fd = open(busnode, O_RDWR)) < 0) {
166 if (errno != ENOENT && errno != ENXIO)
167 usbi_err(ctx, "could not open %s", busnode);
168 continue;
169 }
170
171 bzero(devices, sizeof(devices));
172 for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
173 if (devices[addr])
174 continue;
175
176 di.udi_addr = addr;
177 if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
178 continue;
179
180 /*
181 * XXX If ugen(4) is attached to the USB device
182 * it will be used.
183 */
184 udevname = NULL;
185 for (j = 0; j < USB_MAX_DEVNAMES; j++)
186 if (!strncmp("ugen", di.udi_devnames[j], 4)) {
187 udevname = strdup(di.udi_devnames[j]);
188 break;
189 }
190
191 session_id = (di.udi_bus << 8 | di.udi_addr);
192 dev = usbi_get_device_by_session_id(ctx, session_id);
193
194 if (dev == NULL) {
195 dev = usbi_alloc_device(ctx, session_id);
196 if (dev == NULL) {
197 close(fd);
198 return (LIBUSB_ERROR_NO_MEM);
199 }
200
201 dev->bus_number = di.udi_bus;
202 dev->device_address = di.udi_addr;
203 dev->speed = di.udi_speed;
204
205 dpriv = (struct device_priv *)dev->os_priv;
206 dpriv->fd = -1;
207 dpriv->cdesc = NULL;
208 dpriv->devname = udevname;
209
210 dd.udd_bus = di.udi_bus;
211 dd.udd_addr = di.udi_addr;
212 if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
213 libusb_unref_device(dev);
214 continue;
215 }
216 dpriv->ddesc = dd.udd_desc;
217
218 if (_cache_active_config_descriptor(dev)) {
219 libusb_unref_device(dev);
220 continue;
221 }
222
223 if (usbi_sanitize_device(dev)) {
224 libusb_unref_device(dev);
225 continue;
226 }
227 }
228
229 ddd = discovered_devs_append(*discdevs, dev);
230 if (ddd == NULL) {
231 close(fd);
232 return (LIBUSB_ERROR_NO_MEM);
233 }
234 libusb_unref_device(dev);
235
236 *discdevs = ddd;
237 devices[addr] = 1;
238 }
239
240 close(fd);
241 }
242
243 return (LIBUSB_SUCCESS);
244 }
245
246 int
obsd_open(struct libusb_device_handle * handle)247 obsd_open(struct libusb_device_handle *handle)
248 {
249 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
250 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
251 char devnode[16];
252
253 if (dpriv->devname) {
254 /*
255 * Only open ugen(4) attached devices read-write, all
256 * read-only operations are done through the bus node.
257 */
258 snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
259 dpriv->devname);
260 dpriv->fd = open(devnode, O_RDWR);
261 if (dpriv->fd < 0)
262 return _errno_to_libusb(errno);
263
264 usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
265 }
266
267 return (LIBUSB_SUCCESS);
268 }
269
270 void
obsd_close(struct libusb_device_handle * handle)271 obsd_close(struct libusb_device_handle *handle)
272 {
273 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
274 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
275
276 if (dpriv->devname) {
277 usbi_dbg("close: fd %d", dpriv->fd);
278
279 close(dpriv->fd);
280 dpriv->fd = -1;
281 }
282 }
283
284 int
obsd_get_device_descriptor(struct libusb_device * dev,unsigned char * buf,int * host_endian)285 obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
286 int *host_endian)
287 {
288 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
289
290 usbi_dbg("");
291
292 memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
293
294 *host_endian = 0;
295
296 return (LIBUSB_SUCCESS);
297 }
298
299 int
obsd_get_active_config_descriptor(struct libusb_device * dev,unsigned char * buf,size_t len,int * host_endian)300 obsd_get_active_config_descriptor(struct libusb_device *dev,
301 unsigned char *buf, size_t len, int *host_endian)
302 {
303 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
304 usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
305
306 len = MIN(len, UGETW(ucd->wTotalLength));
307
308 usbi_dbg("len %d", len);
309
310 memcpy(buf, dpriv->cdesc, len);
311
312 *host_endian = 0;
313
314 return (len);
315 }
316
317 int
obsd_get_config_descriptor(struct libusb_device * dev,uint8_t idx,unsigned char * buf,size_t len,int * host_endian)318 obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
319 unsigned char *buf, size_t len, int *host_endian)
320 {
321 struct usb_device_fdesc udf;
322 int fd, err;
323
324 if ((fd = _bus_open(dev->bus_number)) < 0)
325 return _errno_to_libusb(errno);
326
327 udf.udf_bus = dev->bus_number;
328 udf.udf_addr = dev->device_address;
329 udf.udf_config_index = idx;
330 udf.udf_size = len;
331 udf.udf_data = buf;
332
333 usbi_dbg("index %d, len %d", udf.udf_config_index, len);
334
335 if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
336 err = errno;
337 close(fd);
338 return _errno_to_libusb(err);
339 }
340 close(fd);
341
342 *host_endian = 0;
343
344 return (len);
345 }
346
347 int
obsd_get_configuration(struct libusb_device_handle * handle,int * config)348 obsd_get_configuration(struct libusb_device_handle *handle, int *config)
349 {
350 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
351 usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
352
353 *config = ucd->bConfigurationValue;
354
355 usbi_dbg("bConfigurationValue %d", *config);
356
357 return (LIBUSB_SUCCESS);
358 }
359
360 int
obsd_set_configuration(struct libusb_device_handle * handle,int config)361 obsd_set_configuration(struct libusb_device_handle *handle, int config)
362 {
363 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
364
365 if (dpriv->devname == NULL)
366 return (LIBUSB_ERROR_NOT_SUPPORTED);
367
368 usbi_dbg("bConfigurationValue %d", config);
369
370 if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
371 return _errno_to_libusb(errno);
372
373 return _cache_active_config_descriptor(handle->dev);
374 }
375
376 int
obsd_claim_interface(struct libusb_device_handle * handle,int iface)377 obsd_claim_interface(struct libusb_device_handle *handle, int iface)
378 {
379 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
380 int i;
381
382 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
383 hpriv->endpoints[i] = -1;
384
385 return (LIBUSB_SUCCESS);
386 }
387
388 int
obsd_release_interface(struct libusb_device_handle * handle,int iface)389 obsd_release_interface(struct libusb_device_handle *handle, int iface)
390 {
391 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
392 int i;
393
394 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
395 if (hpriv->endpoints[i] >= 0)
396 close(hpriv->endpoints[i]);
397
398 return (LIBUSB_SUCCESS);
399 }
400
401 int
obsd_set_interface_altsetting(struct libusb_device_handle * handle,int iface,int altsetting)402 obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
403 int altsetting)
404 {
405 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
406 struct usb_alt_interface intf;
407
408 if (dpriv->devname == NULL)
409 return (LIBUSB_ERROR_NOT_SUPPORTED);
410
411 usbi_dbg("iface %d, setting %d", iface, altsetting);
412
413 memset(&intf, 0, sizeof(intf));
414
415 intf.uai_interface_index = iface;
416 intf.uai_alt_no = altsetting;
417
418 if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
419 return _errno_to_libusb(errno);
420
421 return (LIBUSB_SUCCESS);
422 }
423
424 int
obsd_clear_halt(struct libusb_device_handle * handle,unsigned char endpoint)425 obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
426 {
427 struct usb_ctl_request req;
428 int fd, err;
429
430 if ((fd = _bus_open(handle->dev->bus_number)) < 0)
431 return _errno_to_libusb(errno);
432
433 usbi_dbg("");
434
435 req.ucr_addr = handle->dev->device_address;
436 req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
437 req.ucr_request.bRequest = UR_CLEAR_FEATURE;
438 USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
439 USETW(req.ucr_request.wIndex, endpoint);
440 USETW(req.ucr_request.wLength, 0);
441
442 if (ioctl(fd, USB_REQUEST, &req) < 0) {
443 err = errno;
444 close(fd);
445 return _errno_to_libusb(err);
446 }
447 close(fd);
448
449 return (LIBUSB_SUCCESS);
450 }
451
452 int
obsd_reset_device(struct libusb_device_handle * handle)453 obsd_reset_device(struct libusb_device_handle *handle)
454 {
455 usbi_dbg("");
456
457 return (LIBUSB_ERROR_NOT_SUPPORTED);
458 }
459
460 void
obsd_destroy_device(struct libusb_device * dev)461 obsd_destroy_device(struct libusb_device *dev)
462 {
463 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
464
465 usbi_dbg("");
466
467 free(dpriv->cdesc);
468 free(dpriv->devname);
469 }
470
471 int
obsd_submit_transfer(struct usbi_transfer * itransfer)472 obsd_submit_transfer(struct usbi_transfer *itransfer)
473 {
474 struct libusb_transfer *transfer;
475 struct handle_priv *hpriv;
476 int err = 0;
477
478 usbi_dbg("");
479
480 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
481 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
482
483 switch (transfer->type) {
484 case LIBUSB_TRANSFER_TYPE_CONTROL:
485 err = _sync_control_transfer(itransfer);
486 break;
487 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
488 if (IS_XFEROUT(transfer)) {
489 /* Isochronous write is not supported */
490 err = LIBUSB_ERROR_NOT_SUPPORTED;
491 break;
492 }
493 err = _sync_gen_transfer(itransfer);
494 break;
495 case LIBUSB_TRANSFER_TYPE_BULK:
496 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
497 if (IS_XFEROUT(transfer) &&
498 transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
499 err = LIBUSB_ERROR_NOT_SUPPORTED;
500 break;
501 }
502 err = _sync_gen_transfer(itransfer);
503 break;
504 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
505 err = LIBUSB_ERROR_NOT_SUPPORTED;
506 break;
507 }
508
509 if (err)
510 return (err);
511
512 usbi_signal_transfer_completion(itransfer);
513
514 return (LIBUSB_SUCCESS);
515 }
516
517 int
obsd_cancel_transfer(struct usbi_transfer * itransfer)518 obsd_cancel_transfer(struct usbi_transfer *itransfer)
519 {
520 usbi_dbg("");
521
522 return (LIBUSB_ERROR_NOT_SUPPORTED);
523 }
524
525 void
obsd_clear_transfer_priv(struct usbi_transfer * itransfer)526 obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
527 {
528 usbi_dbg("");
529
530 /* Nothing to do */
531 }
532
533 int
obsd_handle_transfer_completion(struct usbi_transfer * itransfer)534 obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
535 {
536 return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
537 }
538
539 int
obsd_clock_gettime(int clkid,struct timespec * tp)540 obsd_clock_gettime(int clkid, struct timespec *tp)
541 {
542 usbi_dbg("clock %d", clkid);
543
544 if (clkid == USBI_CLOCK_REALTIME)
545 return clock_gettime(CLOCK_REALTIME, tp);
546
547 if (clkid == USBI_CLOCK_MONOTONIC)
548 return clock_gettime(CLOCK_MONOTONIC, tp);
549
550 return (LIBUSB_ERROR_INVALID_PARAM);
551 }
552
553 int
_errno_to_libusb(int err)554 _errno_to_libusb(int err)
555 {
556 usbi_dbg("error: %s (%d)", strerror(err), err);
557
558 switch (err) {
559 case EIO:
560 return (LIBUSB_ERROR_IO);
561 case EACCES:
562 return (LIBUSB_ERROR_ACCESS);
563 case ENOENT:
564 return (LIBUSB_ERROR_NO_DEVICE);
565 case ENOMEM:
566 return (LIBUSB_ERROR_NO_MEM);
567 case ETIMEDOUT:
568 return (LIBUSB_ERROR_TIMEOUT);
569 }
570
571 return (LIBUSB_ERROR_OTHER);
572 }
573
574 int
_cache_active_config_descriptor(struct libusb_device * dev)575 _cache_active_config_descriptor(struct libusb_device *dev)
576 {
577 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
578 struct usb_device_cdesc udc;
579 struct usb_device_fdesc udf;
580 unsigned char* buf;
581 int fd, len, err;
582
583 if ((fd = _bus_open(dev->bus_number)) < 0)
584 return _errno_to_libusb(errno);
585
586 usbi_dbg("fd %d, addr %d", fd, dev->device_address);
587
588 udc.udc_bus = dev->bus_number;
589 udc.udc_addr = dev->device_address;
590 udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
591 if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
592 err = errno;
593 close(fd);
594 return _errno_to_libusb(errno);
595 }
596
597 usbi_dbg("active bLength %d", udc.udc_desc.bLength);
598
599 len = UGETW(udc.udc_desc.wTotalLength);
600 buf = malloc(len);
601 if (buf == NULL)
602 return (LIBUSB_ERROR_NO_MEM);
603
604 udf.udf_bus = dev->bus_number;
605 udf.udf_addr = dev->device_address;
606 udf.udf_config_index = udc.udc_config_index;
607 udf.udf_size = len;
608 udf.udf_data = buf;
609
610 usbi_dbg("index %d, len %d", udf.udf_config_index, len);
611
612 if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
613 err = errno;
614 close(fd);
615 free(buf);
616 return _errno_to_libusb(err);
617 }
618 close(fd);
619
620 if (dpriv->cdesc)
621 free(dpriv->cdesc);
622 dpriv->cdesc = buf;
623
624 return (LIBUSB_SUCCESS);
625 }
626
627 int
_sync_control_transfer(struct usbi_transfer * itransfer)628 _sync_control_transfer(struct usbi_transfer *itransfer)
629 {
630 struct libusb_transfer *transfer;
631 struct libusb_control_setup *setup;
632 struct device_priv *dpriv;
633 struct usb_ctl_request req;
634
635 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
636 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
637 setup = (struct libusb_control_setup *)transfer->buffer;
638
639 usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
640 setup->bmRequestType, setup->bRequest,
641 libusb_le16_to_cpu(setup->wValue),
642 libusb_le16_to_cpu(setup->wIndex),
643 libusb_le16_to_cpu(setup->wLength), transfer->timeout);
644
645 req.ucr_addr = transfer->dev_handle->dev->device_address;
646 req.ucr_request.bmRequestType = setup->bmRequestType;
647 req.ucr_request.bRequest = setup->bRequest;
648 /* Don't use USETW, libusb already deals with the endianness */
649 (*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
650 (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
651 (*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
652 req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
653
654 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
655 req.ucr_flags = USBD_SHORT_XFER_OK;
656
657 if (dpriv->devname == NULL) {
658 /*
659 * XXX If the device is not attached to ugen(4) it is
660 * XXX still possible to submit a control transfer but
661 * XXX with the default timeout only.
662 */
663 int fd, err;
664
665 if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
666 return _errno_to_libusb(errno);
667
668 if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
669 err = errno;
670 close(fd);
671 return _errno_to_libusb(err);
672 }
673 close(fd);
674 } else {
675 if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
676 return _errno_to_libusb(errno);
677
678 if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
679 return _errno_to_libusb(errno);
680 }
681
682 itransfer->transferred = req.ucr_actlen;
683
684 usbi_dbg("transferred %d", itransfer->transferred);
685
686 return (0);
687 }
688
689 int
_access_endpoint(struct libusb_transfer * transfer)690 _access_endpoint(struct libusb_transfer *transfer)
691 {
692 struct handle_priv *hpriv;
693 struct device_priv *dpriv;
694 char devnode[16];
695 int fd, endpt;
696 mode_t mode;
697
698 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
699 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
700
701 endpt = UE_GET_ADDR(transfer->endpoint);
702 mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
703
704 usbi_dbg("endpoint %d mode %d", endpt, mode);
705
706 if (hpriv->endpoints[endpt] < 0) {
707 /* Pick the right endpoint node */
708 snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
709 dpriv->devname, endpt);
710
711 /* We may need to read/write to the same endpoint later. */
712 if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
713 if ((fd = open(devnode, mode)) < 0)
714 return (-1);
715
716 hpriv->endpoints[endpt] = fd;
717 }
718
719 return (hpriv->endpoints[endpt]);
720 }
721
722 int
_sync_gen_transfer(struct usbi_transfer * itransfer)723 _sync_gen_transfer(struct usbi_transfer *itransfer)
724 {
725 struct libusb_transfer *transfer;
726 struct device_priv *dpriv;
727 int fd, nr = 1;
728
729 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
730 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
731
732 if (dpriv->devname == NULL)
733 return (LIBUSB_ERROR_NOT_SUPPORTED);
734
735 /*
736 * Bulk, Interrupt or Isochronous transfer depends on the
737 * endpoint and thus the node to open.
738 */
739 if ((fd = _access_endpoint(transfer)) < 0)
740 return _errno_to_libusb(errno);
741
742 if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
743 return _errno_to_libusb(errno);
744
745 if (IS_XFERIN(transfer)) {
746 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
747 if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
748 return _errno_to_libusb(errno);
749
750 nr = read(fd, transfer->buffer, transfer->length);
751 } else {
752 nr = write(fd, transfer->buffer, transfer->length);
753 }
754
755 if (nr < 0)
756 return _errno_to_libusb(errno);
757
758 itransfer->transferred = nr;
759
760 return (0);
761 }
762
763 int
_bus_open(int number)764 _bus_open(int number)
765 {
766 char busnode[16];
767
768 snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
769
770 return open(busnode, O_RDWR);
771 }
772