core: Only interrupt event handlers as necessary during libusb_open()
[platform/upstream/libusb.git] / libusb / os / netbsd_usb.c
1 /*
2  * Copyright © 2011 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 <sys/time.h>
20 #include <sys/types.h>
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <dev/usb/usb.h>
30
31 #include "libusb.h"
32 #include "libusbi.h"
33
34 struct device_priv {
35         char devnode[16];
36         int fd;
37
38         unsigned char *cdesc;                   /* active config descriptor */
39         usb_device_descriptor_t ddesc;          /* usb device descriptor */
40 };
41
42 struct handle_priv {
43         int pipe[2];                            /* for event notification */
44         int endpoints[USB_MAX_ENDPOINTS];
45 };
46
47 /*
48  * Backend functions
49  */
50 static int netbsd_get_device_list(struct libusb_context *,
51     struct discovered_devs **);
52 static int netbsd_open(struct libusb_device_handle *);
53 static void netbsd_close(struct libusb_device_handle *);
54
55 static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *,
56     int *);
57 static int netbsd_get_active_config_descriptor(struct libusb_device *,
58     unsigned char *, size_t, int *);
59 static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
60     unsigned char *, size_t, int *);
61
62 static int netbsd_get_configuration(struct libusb_device_handle *, int *);
63 static int netbsd_set_configuration(struct libusb_device_handle *, int);
64
65 static int netbsd_claim_interface(struct libusb_device_handle *, int);
66 static int netbsd_release_interface(struct libusb_device_handle *, int);
67
68 static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int,
69     int);
70 static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char);
71 static int netbsd_reset_device(struct libusb_device_handle *);
72 static void netbsd_destroy_device(struct libusb_device *);
73
74 static int netbsd_submit_transfer(struct usbi_transfer *);
75 static int netbsd_cancel_transfer(struct usbi_transfer *);
76 static void netbsd_clear_transfer_priv(struct usbi_transfer *);
77 static int netbsd_handle_events(struct libusb_context *ctx, struct pollfd *,
78     nfds_t, int);
79 static int netbsd_clock_gettime(int, struct timespec *);
80
81 /*
82  * Private functions
83  */
84 static int _errno_to_libusb(int);
85 static int _cache_active_config_descriptor(struct libusb_device *, int);
86 static int _sync_control_transfer(struct usbi_transfer *);
87 static int _sync_gen_transfer(struct usbi_transfer *);
88 static int _access_endpoint(struct libusb_transfer *);
89
90 const struct usbi_os_backend netbsd_backend = {
91         "Synchronous NetBSD backend",
92         USBI_CAP_HAS_POLLABLE_DEVICE_FD,
93         NULL,                           /* init() */
94         NULL,                           /* exit() */
95         netbsd_get_device_list,
96         NULL,                           /* hotplug_poll */
97         netbsd_open,
98         netbsd_close,
99
100         netbsd_get_device_descriptor,
101         netbsd_get_active_config_descriptor,
102         netbsd_get_config_descriptor,
103         NULL,                           /* get_config_descriptor_by_value() */
104
105         netbsd_get_configuration,
106         netbsd_set_configuration,
107
108         netbsd_claim_interface,
109         netbsd_release_interface,
110
111         netbsd_set_interface_altsetting,
112         netbsd_clear_halt,
113         netbsd_reset_device,
114
115         NULL,                           /* alloc_streams */
116         NULL,                           /* free_streams */
117
118         NULL,                           /* kernel_driver_active() */
119         NULL,                           /* detach_kernel_driver() */
120         NULL,                           /* attach_kernel_driver() */
121
122         netbsd_destroy_device,
123
124         netbsd_submit_transfer,
125         netbsd_cancel_transfer,
126         netbsd_clear_transfer_priv,
127
128         netbsd_handle_events,
129
130         netbsd_clock_gettime,
131         sizeof(struct device_priv),
132         sizeof(struct handle_priv),
133         0,                              /* transfer_priv_size */
134         0,                              /* add_iso_packet_size */
135 };
136
137 int
138 netbsd_get_device_list(struct libusb_context * ctx,
139         struct discovered_devs **discdevs)
140 {
141         struct libusb_device *dev;
142         struct device_priv *dpriv;
143         struct usb_device_info di;
144         unsigned long session_id;
145         char devnode[16];
146         int fd, err, i;
147
148         usbi_dbg("");
149
150         /* Only ugen(4) is supported */
151         for (i = 0; i < USB_MAX_DEVICES; i++) {
152                 /* Control endpoint is always .00 */
153                 snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
154
155                 if ((fd = open(devnode, O_RDONLY)) < 0) {
156                         if (errno != ENOENT && errno != ENXIO)
157                                 usbi_err(ctx, "could not open %s", devnode);
158                         continue;
159                 }
160
161                 if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
162                         continue;
163
164                 session_id = (di.udi_bus << 8 | di.udi_addr);
165                 dev = usbi_get_device_by_session_id(ctx, session_id);
166
167                 if (dev == NULL) {
168                         dev = usbi_alloc_device(ctx, session_id);
169                         if (dev == NULL)
170                                 return (LIBUSB_ERROR_NO_MEM);
171
172                         dev->bus_number = di.udi_bus;
173                         dev->device_address = di.udi_addr;
174                         dev->speed = di.udi_speed;
175
176                         dpriv = (struct device_priv *)dev->os_priv;
177                         strlcpy(dpriv->devnode, devnode, sizeof(devnode));
178                         dpriv->fd = -1;
179
180                         if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
181                                 err = errno;
182                                 goto error;
183                         }
184
185                         dpriv->cdesc = NULL;
186                         if (_cache_active_config_descriptor(dev, fd)) {
187                                 err = errno;
188                                 goto error;
189                         }
190
191                         if ((err = usbi_sanitize_device(dev)))
192                                 goto error;
193                 }
194                 close(fd);
195
196                 if (discovered_devs_append(*discdevs, dev) == NULL)
197                         return (LIBUSB_ERROR_NO_MEM);
198
199                 libusb_unref_device(dev);
200         }
201
202         return (LIBUSB_SUCCESS);
203
204 error:
205         close(fd);
206         libusb_unref_device(dev);
207         return _errno_to_libusb(err);
208 }
209
210 int
211 netbsd_open(struct libusb_device_handle *handle)
212 {
213         struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
214         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
215
216         dpriv->fd = open(dpriv->devnode, O_RDWR);
217         if (dpriv->fd < 0) {
218                 dpriv->fd = open(dpriv->devnode, O_RDONLY);
219                 if (dpriv->fd < 0)
220                         return _errno_to_libusb(errno);
221         }
222
223         usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
224
225         if (pipe(hpriv->pipe) < 0)
226                 return _errno_to_libusb(errno);
227
228         return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
229 }
230
231 void
232 netbsd_close(struct libusb_device_handle *handle)
233 {
234         struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
235         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
236
237         usbi_dbg("close: fd %d", dpriv->fd);
238
239         close(dpriv->fd);
240         dpriv->fd = -1;
241
242         usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
243
244         close(hpriv->pipe[0]);
245         close(hpriv->pipe[1]);
246 }
247
248 int
249 netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
250     int *host_endian)
251 {
252         struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
253
254         usbi_dbg("");
255
256         memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
257
258         *host_endian = 0;
259
260         return (LIBUSB_SUCCESS);
261 }
262
263 int
264 netbsd_get_active_config_descriptor(struct libusb_device *dev,
265     unsigned char *buf, size_t len, int *host_endian)
266 {
267         struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
268         usb_config_descriptor_t *ucd;
269
270         ucd = (usb_config_descriptor_t *) dpriv->cdesc;
271         len = MIN(len, UGETW(ucd->wTotalLength));
272
273         usbi_dbg("len %d", len);
274
275         memcpy(buf, dpriv->cdesc, len);
276
277         *host_endian = 0;
278
279         return len;
280 }
281
282 int
283 netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
284     unsigned char *buf, size_t len, int *host_endian)
285 {
286         struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
287         struct usb_full_desc ufd;
288         int fd, err;
289
290         usbi_dbg("index %d, len %d", idx, len);
291
292         /* A config descriptor may be requested before opening the device */
293         if (dpriv->fd >= 0) {
294                 fd = dpriv->fd;
295         } else {
296                 fd = open(dpriv->devnode, O_RDONLY);
297                 if (fd < 0)
298                         return _errno_to_libusb(errno);
299         }
300
301         ufd.ufd_config_index = idx;
302         ufd.ufd_size = len;
303         ufd.ufd_data = buf;
304
305         if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
306                 err = errno;
307                 if (dpriv->fd < 0)
308                         close(fd);
309                 return _errno_to_libusb(err);
310         }
311
312         if (dpriv->fd < 0)
313                 close(fd);
314
315         *host_endian = 0;
316
317         return len;
318 }
319
320 int
321 netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
322 {
323         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
324
325         usbi_dbg("");
326
327         if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
328                 return _errno_to_libusb(errno);
329
330         usbi_dbg("configuration %d", *config);
331
332         return (LIBUSB_SUCCESS);
333 }
334
335 int
336 netbsd_set_configuration(struct libusb_device_handle *handle, int config)
337 {
338         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
339
340         usbi_dbg("configuration %d", config);
341
342         if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
343                 return _errno_to_libusb(errno);
344
345         return _cache_active_config_descriptor(handle->dev, dpriv->fd);
346 }
347
348 int
349 netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
350 {
351         struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
352         int i;
353
354         for (i = 0; i < USB_MAX_ENDPOINTS; i++)
355                 hpriv->endpoints[i] = -1;
356
357         return (LIBUSB_SUCCESS);
358 }
359
360 int
361 netbsd_release_interface(struct libusb_device_handle *handle, int iface)
362 {
363         struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
364         int i;
365
366         for (i = 0; i < USB_MAX_ENDPOINTS; i++)
367                 if (hpriv->endpoints[i] >= 0)
368                         close(hpriv->endpoints[i]);
369
370         return (LIBUSB_SUCCESS);
371 }
372
373 int
374 netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
375     int altsetting)
376 {
377         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
378         struct usb_alt_interface intf;
379
380         usbi_dbg("iface %d, setting %d", iface, altsetting);
381
382         memset(&intf, 0, sizeof(intf));
383
384         intf.uai_interface_index = iface;
385         intf.uai_alt_no = altsetting;
386
387         if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
388                 return _errno_to_libusb(errno);
389
390         return (LIBUSB_SUCCESS);
391 }
392
393 int
394 netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
395 {
396         struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
397         struct usb_ctl_request req;
398
399         usbi_dbg("");
400
401         req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
402         req.ucr_request.bRequest = UR_CLEAR_FEATURE;
403         USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
404         USETW(req.ucr_request.wIndex, endpoint);
405         USETW(req.ucr_request.wLength, 0);
406
407         if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
408                 return _errno_to_libusb(errno);
409
410         return (LIBUSB_SUCCESS);
411 }
412
413 int
414 netbsd_reset_device(struct libusb_device_handle *handle)
415 {
416         usbi_dbg("");
417
418         return (LIBUSB_ERROR_NOT_SUPPORTED);
419 }
420
421 void
422 netbsd_destroy_device(struct libusb_device *dev)
423 {
424         struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
425
426         usbi_dbg("");
427
428         free(dpriv->cdesc);
429 }
430
431 int
432 netbsd_submit_transfer(struct usbi_transfer *itransfer)
433 {
434         struct libusb_transfer *transfer;
435         struct handle_priv *hpriv;
436         int err = 0;
437
438         usbi_dbg("");
439
440         transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
441         hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
442
443         switch (transfer->type) {
444         case LIBUSB_TRANSFER_TYPE_CONTROL:
445                 err = _sync_control_transfer(itransfer);
446                 break;
447         case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
448                 if (IS_XFEROUT(transfer)) {
449                         /* Isochronous write is not supported */
450                         err = LIBUSB_ERROR_NOT_SUPPORTED;
451                         break;
452                 }
453                 err = _sync_gen_transfer(itransfer);
454                 break;
455         case LIBUSB_TRANSFER_TYPE_BULK:
456         case LIBUSB_TRANSFER_TYPE_INTERRUPT:
457                 if (IS_XFEROUT(transfer) &&
458                     transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
459                         err = LIBUSB_ERROR_NOT_SUPPORTED;
460                         break;
461                 }
462                 err = _sync_gen_transfer(itransfer);
463                 break;
464         case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
465                 err = LIBUSB_ERROR_NOT_SUPPORTED;
466                 break;
467         }
468
469         if (err)
470                 return (err);
471
472         if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0)
473                 return _errno_to_libusb(errno);
474
475         return (LIBUSB_SUCCESS);
476 }
477
478 int
479 netbsd_cancel_transfer(struct usbi_transfer *itransfer)
480 {
481         usbi_dbg("");
482
483         return (LIBUSB_ERROR_NOT_SUPPORTED);
484 }
485
486 void
487 netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
488 {
489         usbi_dbg("");
490
491         /* Nothing to do */
492 }
493
494 int
495 netbsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds,
496     int num_ready)
497 {
498         struct libusb_device_handle *handle;
499         struct handle_priv *hpriv = NULL;
500         struct usbi_transfer *itransfer;
501         struct pollfd *pollfd;
502         int i, err = 0;
503
504         usbi_dbg("");
505
506         pthread_mutex_lock(&ctx->open_devs_lock);
507         for (i = 0; i < nfds && num_ready > 0; i++) {
508                 pollfd = &fds[i];
509
510                 if (!pollfd->revents)
511                         continue;
512
513                 hpriv = NULL;
514                 num_ready--;
515                 list_for_each_entry(handle, &ctx->open_devs, list,
516                     struct libusb_device_handle) {
517                         hpriv = (struct handle_priv *)handle->os_priv;
518
519                         if (hpriv->pipe[0] == pollfd->fd)
520                                 break;
521
522                         hpriv = NULL;
523                 }
524
525                 if (NULL == hpriv) {
526                         usbi_dbg("fd %d is not an event pipe!", pollfd->fd);
527                         err = ENOENT;
528                         break;
529                 }
530
531                 if (pollfd->revents & POLLERR) {
532                         usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
533                         usbi_handle_disconnect(handle);
534                         continue;
535                 }
536
537                 if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) {
538                         err = errno;
539                         break;
540                 }
541
542                 if ((err = usbi_handle_transfer_completion(itransfer,
543                     LIBUSB_TRANSFER_COMPLETED)))
544                         break;
545         }
546         pthread_mutex_unlock(&ctx->open_devs_lock);
547
548         if (err)
549                 return _errno_to_libusb(err);
550
551         return (LIBUSB_SUCCESS);
552 }
553
554 int
555 netbsd_clock_gettime(int clkid, struct timespec *tp)
556 {
557         usbi_dbg("clock %d", clkid);
558
559         if (clkid == USBI_CLOCK_REALTIME)
560                 return clock_gettime(CLOCK_REALTIME, tp);
561
562         if (clkid == USBI_CLOCK_MONOTONIC)
563                 return clock_gettime(CLOCK_MONOTONIC, tp);
564
565         return (LIBUSB_ERROR_INVALID_PARAM);
566 }
567
568 int
569 _errno_to_libusb(int err)
570 {
571         switch (err) {
572         case EIO:
573                 return (LIBUSB_ERROR_IO);
574         case EACCES:
575                 return (LIBUSB_ERROR_ACCESS);
576         case ENOENT:
577                 return (LIBUSB_ERROR_NO_DEVICE);
578         case ENOMEM:
579                 return (LIBUSB_ERROR_NO_MEM);
580         }
581
582         usbi_dbg("error: %s", strerror(err));
583
584         return (LIBUSB_ERROR_OTHER);
585 }
586
587 int
588 _cache_active_config_descriptor(struct libusb_device *dev, int fd)
589 {
590         struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
591         struct usb_config_desc ucd;
592         struct usb_full_desc ufd;
593         unsigned char* buf;
594         int len;
595
596         usbi_dbg("fd %d", fd);
597
598         ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
599
600         if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
601                 return _errno_to_libusb(errno);
602
603         usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
604
605         len = UGETW(ucd.ucd_desc.wTotalLength);
606         buf = malloc(len);
607         if (buf == NULL)
608                 return (LIBUSB_ERROR_NO_MEM);
609
610         ufd.ufd_config_index = ucd.ucd_config_index;
611         ufd.ufd_size = len;
612         ufd.ufd_data = buf;
613
614         usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
615
616         if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
617                 free(buf);
618                 return _errno_to_libusb(errno);
619         }
620
621         if (dpriv->cdesc)
622                 free(dpriv->cdesc);
623         dpriv->cdesc = buf;
624
625         return (0);
626 }
627
628 int
629 _sync_control_transfer(struct usbi_transfer *itransfer)
630 {
631         struct libusb_transfer *transfer;
632         struct libusb_control_setup *setup;
633         struct device_priv *dpriv;
634         struct usb_ctl_request req;
635
636         transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
637         dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
638         setup = (struct libusb_control_setup *)transfer->buffer;
639
640         usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
641             setup->bmRequestType, setup->bRequest,
642             libusb_le16_to_cpu(setup->wValue),
643             libusb_le16_to_cpu(setup->wIndex),
644             libusb_le16_to_cpu(setup->wLength), transfer->timeout);
645
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 ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
658                 return _errno_to_libusb(errno);
659
660         if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
661                 return _errno_to_libusb(errno);
662
663         itransfer->transferred = req.ucr_actlen;
664
665         usbi_dbg("transferred %d", itransfer->transferred);
666
667         return (0);
668 }
669
670 int
671 _access_endpoint(struct libusb_transfer *transfer)
672 {
673         struct handle_priv *hpriv;
674         struct device_priv *dpriv;
675         char *s, devnode[16];
676         int fd, endpt;
677         mode_t mode;
678
679         hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
680         dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
681
682         endpt = UE_GET_ADDR(transfer->endpoint);
683         mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
684
685         usbi_dbg("endpoint %d mode %d", endpt, mode);
686
687         if (hpriv->endpoints[endpt] < 0) {
688                 /* Pick the right node given the control one */
689                 strlcpy(devnode, dpriv->devnode, sizeof(devnode));
690                 s = strchr(devnode, '.');
691                 snprintf(s, 4, ".%02d", endpt);
692
693                 /* We may need to read/write to the same endpoint later. */
694                 if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
695                         if ((fd = open(devnode, mode)) < 0)
696                                 return (-1);
697
698                 hpriv->endpoints[endpt] = fd;
699         }
700
701         return (hpriv->endpoints[endpt]);
702 }
703
704 int
705 _sync_gen_transfer(struct usbi_transfer *itransfer)
706 {
707         struct libusb_transfer *transfer;
708         int fd, nr = 1;
709
710         transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
711
712         /*
713          * Bulk, Interrupt or Isochronous transfer depends on the
714          * endpoint and thus the node to open.
715          */
716         if ((fd = _access_endpoint(transfer)) < 0)
717                 return _errno_to_libusb(errno);
718
719         if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
720                 return _errno_to_libusb(errno);
721
722         if (IS_XFERIN(transfer)) {
723                 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
724                         if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
725                                 return _errno_to_libusb(errno);
726
727                 nr = read(fd, transfer->buffer, transfer->length);
728         } else {
729                 nr = write(fd, transfer->buffer, transfer->length);
730         }
731
732         if (nr < 0)
733                 return _errno_to_libusb(errno);
734
735         itransfer->transferred = nr;
736
737         return (0);
738 }