• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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 devnode[16];
37 	int fd;
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 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_transfer_completion(struct usbi_transfer *);
78 static int netbsd_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 *, int);
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 const struct usbi_os_backend netbsd_backend = {
90 	"Synchronous NetBSD backend",
91 	0,
92 	NULL,				/* init() */
93 	NULL,				/* exit() */
94 	netbsd_get_device_list,
95 	NULL,				/* hotplug_poll */
96 	netbsd_open,
97 	netbsd_close,
98 
99 	netbsd_get_device_descriptor,
100 	netbsd_get_active_config_descriptor,
101 	netbsd_get_config_descriptor,
102 	NULL,				/* get_config_descriptor_by_value() */
103 
104 	netbsd_get_configuration,
105 	netbsd_set_configuration,
106 
107 	netbsd_claim_interface,
108 	netbsd_release_interface,
109 
110 	netbsd_set_interface_altsetting,
111 	netbsd_clear_halt,
112 	netbsd_reset_device,
113 
114 	NULL,				/* alloc_streams */
115 	NULL,				/* free_streams */
116 
117 	NULL,				/* dev_mem_alloc() */
118 	NULL,				/* dev_mem_free() */
119 
120 	NULL,				/* kernel_driver_active() */
121 	NULL,				/* detach_kernel_driver() */
122 	NULL,				/* attach_kernel_driver() */
123 
124 	netbsd_destroy_device,
125 
126 	netbsd_submit_transfer,
127 	netbsd_cancel_transfer,
128 	netbsd_clear_transfer_priv,
129 
130 	NULL,				/* handle_events() */
131 	netbsd_handle_transfer_completion,
132 
133 	netbsd_clock_gettime,
134 	sizeof(struct device_priv),
135 	sizeof(struct handle_priv),
136 	0,				/* transfer_priv_size */
137 };
138 
139 int
netbsd_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)140 netbsd_get_device_list(struct libusb_context * ctx,
141 	struct discovered_devs **discdevs)
142 {
143 	struct libusb_device *dev;
144 	struct device_priv *dpriv;
145 	struct usb_device_info di;
146 	unsigned long session_id;
147 	char devnode[16];
148 	int fd, err, i;
149 
150 	usbi_dbg("");
151 
152 	/* Only ugen(4) is supported */
153 	for (i = 0; i < USB_MAX_DEVICES; i++) {
154 		/* Control endpoint is always .00 */
155 		snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
156 
157 		if ((fd = open(devnode, O_RDONLY)) < 0) {
158 			if (errno != ENOENT && errno != ENXIO)
159 				usbi_err(ctx, "could not open %s", devnode);
160 			continue;
161 		}
162 
163 		if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
164 			continue;
165 
166 		session_id = (di.udi_bus << 8 | di.udi_addr);
167 		dev = usbi_get_device_by_session_id(ctx, session_id);
168 
169 		if (dev == NULL) {
170 			dev = usbi_alloc_device(ctx, session_id);
171 			if (dev == NULL)
172 				return (LIBUSB_ERROR_NO_MEM);
173 
174 			dev->bus_number = di.udi_bus;
175 			dev->device_address = di.udi_addr;
176 			dev->speed = di.udi_speed;
177 
178 			dpriv = (struct device_priv *)dev->os_priv;
179 			strlcpy(dpriv->devnode, devnode, sizeof(devnode));
180 			dpriv->fd = -1;
181 
182 			if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
183 				err = errno;
184 				goto error;
185 			}
186 
187 			dpriv->cdesc = NULL;
188 			if (_cache_active_config_descriptor(dev, fd)) {
189 				err = errno;
190 				goto error;
191 			}
192 
193 			if ((err = usbi_sanitize_device(dev)))
194 				goto error;
195 		}
196 		close(fd);
197 
198 		if (discovered_devs_append(*discdevs, dev) == NULL)
199 			return (LIBUSB_ERROR_NO_MEM);
200 
201 		libusb_unref_device(dev);
202 	}
203 
204 	return (LIBUSB_SUCCESS);
205 
206 error:
207 	close(fd);
208 	libusb_unref_device(dev);
209 	return _errno_to_libusb(err);
210 }
211 
212 int
netbsd_open(struct libusb_device_handle * handle)213 netbsd_open(struct libusb_device_handle *handle)
214 {
215 	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
216 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
217 
218 	dpriv->fd = open(dpriv->devnode, O_RDWR);
219 	if (dpriv->fd < 0) {
220 		dpriv->fd = open(dpriv->devnode, O_RDONLY);
221 		if (dpriv->fd < 0)
222 			return _errno_to_libusb(errno);
223 	}
224 
225 	usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
226 
227 	return (LIBUSB_SUCCESS);
228 }
229 
230 void
netbsd_close(struct libusb_device_handle * handle)231 netbsd_close(struct libusb_device_handle *handle)
232 {
233 	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
234 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
235 
236 	usbi_dbg("close: fd %d", dpriv->fd);
237 
238 	close(dpriv->fd);
239 	dpriv->fd = -1;
240 }
241 
242 int
netbsd_get_device_descriptor(struct libusb_device * dev,unsigned char * buf,int * host_endian)243 netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
244     int *host_endian)
245 {
246 	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
247 
248 	usbi_dbg("");
249 
250 	memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
251 
252 	*host_endian = 0;
253 
254 	return (LIBUSB_SUCCESS);
255 }
256 
257 int
netbsd_get_active_config_descriptor(struct libusb_device * dev,unsigned char * buf,size_t len,int * host_endian)258 netbsd_get_active_config_descriptor(struct libusb_device *dev,
259     unsigned char *buf, size_t len, int *host_endian)
260 {
261 	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
262 	usb_config_descriptor_t *ucd;
263 
264 	ucd = (usb_config_descriptor_t *) dpriv->cdesc;
265 	len = MIN(len, UGETW(ucd->wTotalLength));
266 
267 	usbi_dbg("len %d", len);
268 
269 	memcpy(buf, dpriv->cdesc, len);
270 
271 	*host_endian = 0;
272 
273 	return len;
274 }
275 
276 int
netbsd_get_config_descriptor(struct libusb_device * dev,uint8_t idx,unsigned char * buf,size_t len,int * host_endian)277 netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
278     unsigned char *buf, size_t len, int *host_endian)
279 {
280 	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
281 	struct usb_full_desc ufd;
282 	int fd, err;
283 
284 	usbi_dbg("index %d, len %d", idx, len);
285 
286 	/* A config descriptor may be requested before opening the device */
287 	if (dpriv->fd >= 0) {
288 		fd = dpriv->fd;
289 	} else {
290 		fd = open(dpriv->devnode, O_RDONLY);
291 		if (fd < 0)
292 			return _errno_to_libusb(errno);
293 	}
294 
295 	ufd.ufd_config_index = idx;
296 	ufd.ufd_size = len;
297 	ufd.ufd_data = buf;
298 
299 	if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
300 		err = errno;
301 		if (dpriv->fd < 0)
302 			close(fd);
303 		return _errno_to_libusb(err);
304 	}
305 
306 	if (dpriv->fd < 0)
307 		close(fd);
308 
309 	*host_endian = 0;
310 
311 	return len;
312 }
313 
314 int
netbsd_get_configuration(struct libusb_device_handle * handle,int * config)315 netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
316 {
317 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
318 
319 	usbi_dbg("");
320 
321 	if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
322 		return _errno_to_libusb(errno);
323 
324 	usbi_dbg("configuration %d", *config);
325 
326 	return (LIBUSB_SUCCESS);
327 }
328 
329 int
netbsd_set_configuration(struct libusb_device_handle * handle,int config)330 netbsd_set_configuration(struct libusb_device_handle *handle, int config)
331 {
332 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
333 
334 	usbi_dbg("configuration %d", config);
335 
336 	if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
337 		return _errno_to_libusb(errno);
338 
339 	return _cache_active_config_descriptor(handle->dev, dpriv->fd);
340 }
341 
342 int
netbsd_claim_interface(struct libusb_device_handle * handle,int iface)343 netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
344 {
345 	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
346 	int i;
347 
348 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
349 		hpriv->endpoints[i] = -1;
350 
351 	return (LIBUSB_SUCCESS);
352 }
353 
354 int
netbsd_release_interface(struct libusb_device_handle * handle,int iface)355 netbsd_release_interface(struct libusb_device_handle *handle, int iface)
356 {
357 	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
358 	int i;
359 
360 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
361 		if (hpriv->endpoints[i] >= 0)
362 			close(hpriv->endpoints[i]);
363 
364 	return (LIBUSB_SUCCESS);
365 }
366 
367 int
netbsd_set_interface_altsetting(struct libusb_device_handle * handle,int iface,int altsetting)368 netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
369     int altsetting)
370 {
371 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
372 	struct usb_alt_interface intf;
373 
374 	usbi_dbg("iface %d, setting %d", iface, altsetting);
375 
376 	memset(&intf, 0, sizeof(intf));
377 
378 	intf.uai_interface_index = iface;
379 	intf.uai_alt_no = altsetting;
380 
381 	if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
382 		return _errno_to_libusb(errno);
383 
384 	return (LIBUSB_SUCCESS);
385 }
386 
387 int
netbsd_clear_halt(struct libusb_device_handle * handle,unsigned char endpoint)388 netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
389 {
390 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
391 	struct usb_ctl_request req;
392 
393 	usbi_dbg("");
394 
395 	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
396 	req.ucr_request.bRequest = UR_CLEAR_FEATURE;
397 	USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
398 	USETW(req.ucr_request.wIndex, endpoint);
399 	USETW(req.ucr_request.wLength, 0);
400 
401 	if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
402 		return _errno_to_libusb(errno);
403 
404 	return (LIBUSB_SUCCESS);
405 }
406 
407 int
netbsd_reset_device(struct libusb_device_handle * handle)408 netbsd_reset_device(struct libusb_device_handle *handle)
409 {
410 	usbi_dbg("");
411 
412 	return (LIBUSB_ERROR_NOT_SUPPORTED);
413 }
414 
415 void
netbsd_destroy_device(struct libusb_device * dev)416 netbsd_destroy_device(struct libusb_device *dev)
417 {
418 	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
419 
420 	usbi_dbg("");
421 
422 	free(dpriv->cdesc);
423 }
424 
425 int
netbsd_submit_transfer(struct usbi_transfer * itransfer)426 netbsd_submit_transfer(struct usbi_transfer *itransfer)
427 {
428 	struct libusb_transfer *transfer;
429 	struct handle_priv *hpriv;
430 	int err = 0;
431 
432 	usbi_dbg("");
433 
434 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
435 	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
436 
437 	switch (transfer->type) {
438 	case LIBUSB_TRANSFER_TYPE_CONTROL:
439 		err = _sync_control_transfer(itransfer);
440 		break;
441 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
442 		if (IS_XFEROUT(transfer)) {
443 			/* Isochronous write is not supported */
444 			err = LIBUSB_ERROR_NOT_SUPPORTED;
445 			break;
446 		}
447 		err = _sync_gen_transfer(itransfer);
448 		break;
449 	case LIBUSB_TRANSFER_TYPE_BULK:
450 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
451 		if (IS_XFEROUT(transfer) &&
452 		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
453 			err = LIBUSB_ERROR_NOT_SUPPORTED;
454 			break;
455 		}
456 		err = _sync_gen_transfer(itransfer);
457 		break;
458 	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
459 		err = LIBUSB_ERROR_NOT_SUPPORTED;
460 		break;
461 	}
462 
463 	if (err)
464 		return (err);
465 
466 	usbi_signal_transfer_completion(itransfer);
467 
468 	return (LIBUSB_SUCCESS);
469 }
470 
471 int
netbsd_cancel_transfer(struct usbi_transfer * itransfer)472 netbsd_cancel_transfer(struct usbi_transfer *itransfer)
473 {
474 	usbi_dbg("");
475 
476 	return (LIBUSB_ERROR_NOT_SUPPORTED);
477 }
478 
479 void
netbsd_clear_transfer_priv(struct usbi_transfer * itransfer)480 netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
481 {
482 	usbi_dbg("");
483 
484 	/* Nothing to do */
485 }
486 
487 int
netbsd_handle_transfer_completion(struct usbi_transfer * itransfer)488 netbsd_handle_transfer_completion(struct usbi_transfer *itransfer)
489 {
490 	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
491 }
492 
493 int
netbsd_clock_gettime(int clkid,struct timespec * tp)494 netbsd_clock_gettime(int clkid, struct timespec *tp)
495 {
496 	usbi_dbg("clock %d", clkid);
497 
498 	if (clkid == USBI_CLOCK_REALTIME)
499 		return clock_gettime(CLOCK_REALTIME, tp);
500 
501 	if (clkid == USBI_CLOCK_MONOTONIC)
502 		return clock_gettime(CLOCK_MONOTONIC, tp);
503 
504 	return (LIBUSB_ERROR_INVALID_PARAM);
505 }
506 
507 int
_errno_to_libusb(int err)508 _errno_to_libusb(int err)
509 {
510 	switch (err) {
511 	case EIO:
512 		return (LIBUSB_ERROR_IO);
513 	case EACCES:
514 		return (LIBUSB_ERROR_ACCESS);
515 	case ENOENT:
516 		return (LIBUSB_ERROR_NO_DEVICE);
517 	case ENOMEM:
518 		return (LIBUSB_ERROR_NO_MEM);
519 	}
520 
521 	usbi_dbg("error: %s", strerror(err));
522 
523 	return (LIBUSB_ERROR_OTHER);
524 }
525 
526 int
_cache_active_config_descriptor(struct libusb_device * dev,int fd)527 _cache_active_config_descriptor(struct libusb_device *dev, int fd)
528 {
529 	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
530 	struct usb_config_desc ucd;
531 	struct usb_full_desc ufd;
532 	unsigned char* buf;
533 	int len;
534 
535 	usbi_dbg("fd %d", fd);
536 
537 	ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
538 
539 	if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
540 		return _errno_to_libusb(errno);
541 
542 	usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
543 
544 	len = UGETW(ucd.ucd_desc.wTotalLength);
545 	buf = malloc(len);
546 	if (buf == NULL)
547 		return (LIBUSB_ERROR_NO_MEM);
548 
549 	ufd.ufd_config_index = ucd.ucd_config_index;
550 	ufd.ufd_size = len;
551 	ufd.ufd_data = buf;
552 
553 	usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
554 
555 	if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
556 		free(buf);
557 		return _errno_to_libusb(errno);
558 	}
559 
560 	if (dpriv->cdesc)
561 		free(dpriv->cdesc);
562 	dpriv->cdesc = buf;
563 
564 	return (0);
565 }
566 
567 int
_sync_control_transfer(struct usbi_transfer * itransfer)568 _sync_control_transfer(struct usbi_transfer *itransfer)
569 {
570 	struct libusb_transfer *transfer;
571 	struct libusb_control_setup *setup;
572 	struct device_priv *dpriv;
573 	struct usb_ctl_request req;
574 
575 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
576 	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
577 	setup = (struct libusb_control_setup *)transfer->buffer;
578 
579 	usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
580 	    setup->bmRequestType, setup->bRequest,
581 	    libusb_le16_to_cpu(setup->wValue),
582 	    libusb_le16_to_cpu(setup->wIndex),
583 	    libusb_le16_to_cpu(setup->wLength), transfer->timeout);
584 
585 	req.ucr_request.bmRequestType = setup->bmRequestType;
586 	req.ucr_request.bRequest = setup->bRequest;
587 	/* Don't use USETW, libusb already deals with the endianness */
588 	(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
589 	(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
590 	(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
591 	req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
592 
593 	if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
594 		req.ucr_flags = USBD_SHORT_XFER_OK;
595 
596 	if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
597 		return _errno_to_libusb(errno);
598 
599 	if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
600 		return _errno_to_libusb(errno);
601 
602 	itransfer->transferred = req.ucr_actlen;
603 
604 	usbi_dbg("transferred %d", itransfer->transferred);
605 
606 	return (0);
607 }
608 
609 int
_access_endpoint(struct libusb_transfer * transfer)610 _access_endpoint(struct libusb_transfer *transfer)
611 {
612 	struct handle_priv *hpriv;
613 	struct device_priv *dpriv;
614 	char *s, devnode[16];
615 	int fd, endpt;
616 	mode_t mode;
617 
618 	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
619 	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
620 
621 	endpt = UE_GET_ADDR(transfer->endpoint);
622 	mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
623 
624 	usbi_dbg("endpoint %d mode %d", endpt, mode);
625 
626 	if (hpriv->endpoints[endpt] < 0) {
627 		/* Pick the right node given the control one */
628 		strlcpy(devnode, dpriv->devnode, sizeof(devnode));
629 		s = strchr(devnode, '.');
630 		snprintf(s, 4, ".%02d", endpt);
631 
632 		/* We may need to read/write to the same endpoint later. */
633 		if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
634 			if ((fd = open(devnode, mode)) < 0)
635 				return (-1);
636 
637 		hpriv->endpoints[endpt] = fd;
638 	}
639 
640 	return (hpriv->endpoints[endpt]);
641 }
642 
643 int
_sync_gen_transfer(struct usbi_transfer * itransfer)644 _sync_gen_transfer(struct usbi_transfer *itransfer)
645 {
646 	struct libusb_transfer *transfer;
647 	int fd, nr = 1;
648 
649 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
650 
651 	/*
652 	 * Bulk, Interrupt or Isochronous transfer depends on the
653 	 * endpoint and thus the node to open.
654 	 */
655 	if ((fd = _access_endpoint(transfer)) < 0)
656 		return _errno_to_libusb(errno);
657 
658 	if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
659 		return _errno_to_libusb(errno);
660 
661 	if (IS_XFERIN(transfer)) {
662 		if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
663 			if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
664 				return _errno_to_libusb(errno);
665 
666 		nr = read(fd, transfer->buffer, transfer->length);
667 	} else {
668 		nr = write(fd, transfer->buffer, transfer->length);
669 	}
670 
671 	if (nr < 0)
672 		return _errno_to_libusb(errno);
673 
674 	itransfer->transferred = nr;
675 
676 	return (0);
677 }
678