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