xref: /aosp_15_r20/external/libusb/libusb/os/openbsd_usb.c (revision 86b64dcb59b3a0b37502ecd56e119234366a6f7e)
1 /*
2  * Copyright © 2011-2013 Martin Pieuchot <[email protected]>
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 	usb_config_descriptor_t *cdesc;		/* active config descriptor */
40 };
41 
42 struct handle_priv {
43 	int endpoints[USB_MAX_ENDPOINTS];
44 };
45 
46 /*
47  * Backend functions
48  */
49 static int obsd_get_device_list(struct libusb_context *,
50     struct discovered_devs **);
51 static int obsd_open(struct libusb_device_handle *);
52 static void obsd_close(struct libusb_device_handle *);
53 
54 static int obsd_get_active_config_descriptor(struct libusb_device *,
55     void *, size_t);
56 static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
57     void *, size_t);
58 
59 static int obsd_get_configuration(struct libusb_device_handle *, uint8_t *);
60 static int obsd_set_configuration(struct libusb_device_handle *, int);
61 
62 static int obsd_claim_interface(struct libusb_device_handle *, uint8_t);
63 static int obsd_release_interface(struct libusb_device_handle *, uint8_t);
64 
65 static int obsd_set_interface_altsetting(struct libusb_device_handle *, uint8_t,
66     uint8_t);
67 static int obsd_clear_halt(struct libusb_device_handle *, unsigned char);
68 static void obsd_destroy_device(struct libusb_device *);
69 
70 static int obsd_submit_transfer(struct usbi_transfer *);
71 static int obsd_cancel_transfer(struct usbi_transfer *);
72 static int obsd_handle_transfer_completion(struct usbi_transfer *);
73 
74 /*
75  * Private functions
76  */
77 static int _errno_to_libusb(int);
78 static int _cache_active_config_descriptor(struct libusb_device *);
79 static int _sync_control_transfer(struct usbi_transfer *);
80 static int _sync_gen_transfer(struct usbi_transfer *);
81 static int _access_endpoint(struct libusb_transfer *);
82 
83 static int _bus_open(int);
84 
85 
86 const struct usbi_os_backend usbi_backend = {
87 	.name = "Synchronous OpenBSD backend",
88 	.get_device_list = obsd_get_device_list,
89 	.open = obsd_open,
90 	.close = obsd_close,
91 
92 	.get_active_config_descriptor = obsd_get_active_config_descriptor,
93 	.get_config_descriptor = obsd_get_config_descriptor,
94 
95 	.get_configuration = obsd_get_configuration,
96 	.set_configuration = obsd_set_configuration,
97 
98 	.claim_interface = obsd_claim_interface,
99 	.release_interface = obsd_release_interface,
100 
101 	.set_interface_altsetting = obsd_set_interface_altsetting,
102 	.clear_halt = obsd_clear_halt,
103 	.destroy_device = obsd_destroy_device,
104 
105 	.submit_transfer = obsd_submit_transfer,
106 	.cancel_transfer = obsd_cancel_transfer,
107 
108 	.handle_transfer_completion = obsd_handle_transfer_completion,
109 
110 	.device_priv_size = sizeof(struct device_priv),
111 	.device_handle_priv_size = sizeof(struct handle_priv),
112 };
113 
114 #define DEVPATH	"/dev/"
115 #define USBDEV	DEVPATH "usb"
116 
117 int
obsd_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)118 obsd_get_device_list(struct libusb_context * ctx,
119 	struct discovered_devs **discdevs)
120 {
121 	struct discovered_devs *ddd;
122 	struct libusb_device *dev;
123 	struct device_priv *dpriv;
124 	struct usb_device_info di;
125 	struct usb_device_ddesc dd;
126 	unsigned long session_id;
127 	char devices[USB_MAX_DEVICES];
128 	char busnode[16];
129 	char *udevname;
130 	int fd, addr, i, j;
131 
132 	usbi_dbg(ctx, " ");
133 
134 	for (i = 0; i < 8; i++) {
135 		snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
136 
137 		if ((fd = open(busnode, O_RDWR)) < 0) {
138 			if (errno != ENOENT && errno != ENXIO)
139 				usbi_err(ctx, "could not open %s", busnode);
140 			continue;
141 		}
142 
143 		bzero(devices, sizeof(devices));
144 		for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
145 			if (devices[addr])
146 				continue;
147 
148 			di.udi_addr = addr;
149 			if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
150 				continue;
151 
152 			/*
153 			 * XXX If ugen(4) is attached to the USB device
154 			 * it will be used.
155 			 */
156 			udevname = NULL;
157 			for (j = 0; j < USB_MAX_DEVNAMES; j++)
158 				if (!strncmp("ugen", di.udi_devnames[j], 4)) {
159 					udevname = strdup(di.udi_devnames[j]);
160 					break;
161 				}
162 
163 			session_id = (di.udi_bus << 8 | di.udi_addr);
164 			dev = usbi_get_device_by_session_id(ctx, session_id);
165 
166 			if (dev == NULL) {
167 				dev = usbi_alloc_device(ctx, session_id);
168 				if (dev == NULL) {
169 					close(fd);
170 					return LIBUSB_ERROR_NO_MEM;
171 				}
172 
173 				dev->bus_number = di.udi_bus;
174 				dev->device_address = di.udi_addr;
175 				dev->speed = di.udi_speed;
176 				dev->port_number = di.udi_port;
177 
178 				dpriv = usbi_get_device_priv(dev);
179 				dpriv->fd = -1;
180 				dpriv->devname = udevname;
181 
182 				dd.udd_bus = di.udi_bus;
183 				dd.udd_addr = di.udi_addr;
184 				if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
185 					libusb_unref_device(dev);
186 					continue;
187 				}
188 
189 				static_assert(sizeof(dev->device_descriptor) == sizeof(dd.udd_desc),
190 					      "mismatch between libusb and OS device descriptor sizes");
191 				memcpy(&dev->device_descriptor, &dd.udd_desc, LIBUSB_DT_DEVICE_SIZE);
192 				usbi_localize_device_descriptor(&dev->device_descriptor);
193 
194 				if (_cache_active_config_descriptor(dev)) {
195 					libusb_unref_device(dev);
196 					continue;
197 				}
198 
199 				if (usbi_sanitize_device(dev)) {
200 					libusb_unref_device(dev);
201 					continue;
202 				}
203 			}
204 
205 			ddd = discovered_devs_append(*discdevs, dev);
206 			if (ddd == NULL) {
207 				close(fd);
208 				return LIBUSB_ERROR_NO_MEM;
209 			}
210 			libusb_unref_device(dev);
211 
212 			*discdevs = ddd;
213 			devices[addr] = 1;
214 		}
215 
216 		close(fd);
217 	}
218 
219 	return LIBUSB_SUCCESS;
220 }
221 
222 int
obsd_open(struct libusb_device_handle * handle)223 obsd_open(struct libusb_device_handle *handle)
224 {
225 	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
226 	char devnode[16];
227 
228 	if (dpriv->devname) {
229 		int fd;
230 		/*
231 		 * Only open ugen(4) attached devices read-write, all
232 		 * read-only operations are done through the bus node.
233 		 */
234 		snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
235 		    dpriv->devname);
236 		fd = open(devnode, O_RDWR);
237 		if (fd < 0)
238 			return _errno_to_libusb(errno);
239 		dpriv->fd = fd;
240 
241 		usbi_dbg(HANDLE_CTX(handle), "open %s: fd %d", devnode, dpriv->fd);
242 	}
243 
244 	return LIBUSB_SUCCESS;
245 }
246 
247 void
obsd_close(struct libusb_device_handle * handle)248 obsd_close(struct libusb_device_handle *handle)
249 {
250 	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
251 
252 	if (dpriv->devname) {
253 		usbi_dbg(HANDLE_CTX(handle), "close: fd %d", dpriv->fd);
254 
255 		close(dpriv->fd);
256 		dpriv->fd = -1;
257 	}
258 }
259 
260 int
obsd_get_active_config_descriptor(struct libusb_device * dev,void * buf,size_t len)261 obsd_get_active_config_descriptor(struct libusb_device *dev,
262     void *buf, size_t len)
263 {
264 	struct device_priv *dpriv = usbi_get_device_priv(dev);
265 
266 	len = MIN(len, (size_t)UGETW(dpriv->cdesc->wTotalLength));
267 
268 	usbi_dbg(DEVICE_CTX(dev), "len %zu", len);
269 
270 	memcpy(buf, dpriv->cdesc, len);
271 
272 	return (int)len;
273 }
274 
275 int
obsd_get_config_descriptor(struct libusb_device * dev,uint8_t idx,void * buf,size_t len)276 obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
277     void *buf, size_t len)
278 {
279 	struct usb_device_fdesc udf;
280 	int fd, err;
281 
282 	if ((fd = _bus_open(dev->bus_number)) < 0)
283 		return _errno_to_libusb(errno);
284 
285 	udf.udf_bus = dev->bus_number;
286 	udf.udf_addr = dev->device_address;
287 	udf.udf_config_index = idx;
288 	udf.udf_size = len;
289 	udf.udf_data = buf;
290 
291 	usbi_dbg(DEVICE_CTX(dev), "index %d, len %zu", udf.udf_config_index, len);
292 
293 	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
294 		err = errno;
295 		close(fd);
296 		return _errno_to_libusb(err);
297 	}
298 	close(fd);
299 
300 	return (int)len;
301 }
302 
303 int
obsd_get_configuration(struct libusb_device_handle * handle,uint8_t * config)304 obsd_get_configuration(struct libusb_device_handle *handle, uint8_t *config)
305 {
306 	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
307 
308 	*config = dpriv->cdesc->bConfigurationValue;
309 
310 	usbi_dbg(HANDLE_CTX(handle), "bConfigurationValue %u", *config);
311 
312 	return LIBUSB_SUCCESS;
313 }
314 
315 int
obsd_set_configuration(struct libusb_device_handle * handle,int config)316 obsd_set_configuration(struct libusb_device_handle *handle, int config)
317 {
318 	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
319 
320 	if (dpriv->devname == NULL)
321 		return LIBUSB_ERROR_NOT_SUPPORTED;
322 
323 	usbi_dbg(HANDLE_CTX(handle), "bConfigurationValue %d", config);
324 
325 	if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
326 		return _errno_to_libusb(errno);
327 
328 	return _cache_active_config_descriptor(handle->dev);
329 }
330 
331 int
obsd_claim_interface(struct libusb_device_handle * handle,uint8_t iface)332 obsd_claim_interface(struct libusb_device_handle *handle, uint8_t iface)
333 {
334 	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
335 	int i;
336 
337 	UNUSED(iface);
338 
339 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
340 		hpriv->endpoints[i] = -1;
341 
342 	return LIBUSB_SUCCESS;
343 }
344 
345 int
obsd_release_interface(struct libusb_device_handle * handle,uint8_t iface)346 obsd_release_interface(struct libusb_device_handle *handle, uint8_t iface)
347 {
348 	struct handle_priv *hpriv = usbi_get_device_handle_priv(handle);
349 	int i;
350 
351 	UNUSED(iface);
352 
353 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
354 		if (hpriv->endpoints[i] >= 0)
355 			close(hpriv->endpoints[i]);
356 
357 	return LIBUSB_SUCCESS;
358 }
359 
360 int
obsd_set_interface_altsetting(struct libusb_device_handle * handle,uint8_t iface,uint8_t altsetting)361 obsd_set_interface_altsetting(struct libusb_device_handle *handle, uint8_t iface,
362     uint8_t altsetting)
363 {
364 	struct device_priv *dpriv = usbi_get_device_priv(handle->dev);
365 	struct usb_alt_interface intf;
366 
367 	if (dpriv->devname == NULL)
368 		return LIBUSB_ERROR_NOT_SUPPORTED;
369 
370 	usbi_dbg(HANDLE_CTX(handle), "iface %u, setting %u", iface, altsetting);
371 
372 	memset(&intf, 0, sizeof(intf));
373 
374 	intf.uai_interface_index = iface;
375 	intf.uai_alt_no = altsetting;
376 
377 	if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
378 		return _errno_to_libusb(errno);
379 
380 	return LIBUSB_SUCCESS;
381 }
382 
383 int
obsd_clear_halt(struct libusb_device_handle * handle,unsigned char endpoint)384 obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
385 {
386 	struct usb_ctl_request req;
387 	int fd, err;
388 
389 	if ((fd = _bus_open(handle->dev->bus_number)) < 0)
390 		return _errno_to_libusb(errno);
391 
392 	usbi_dbg(HANDLE_CTX(handle), " ");
393 
394 	req.ucr_addr = handle->dev->device_address;
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(fd, USB_REQUEST, &req) < 0) {
402 		err = errno;
403 		close(fd);
404 		return _errno_to_libusb(err);
405 	}
406 	close(fd);
407 
408 	return LIBUSB_SUCCESS;
409 }
410 
411 void
obsd_destroy_device(struct libusb_device * dev)412 obsd_destroy_device(struct libusb_device *dev)
413 {
414 	struct device_priv *dpriv = usbi_get_device_priv(dev);
415 
416 	usbi_dbg(DEVICE_CTX(dev), " ");
417 
418 	free(dpriv->cdesc);
419 	free(dpriv->devname);
420 }
421 
422 int
obsd_submit_transfer(struct usbi_transfer * itransfer)423 obsd_submit_transfer(struct usbi_transfer *itransfer)
424 {
425 	struct libusb_transfer *transfer;
426 	int err = 0;
427 
428 	usbi_dbg(ITRANSFER_CTX(itransfer), " ");
429 
430 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
431 
432 	switch (transfer->type) {
433 	case LIBUSB_TRANSFER_TYPE_CONTROL:
434 		err = _sync_control_transfer(itransfer);
435 		break;
436 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
437 		if (IS_XFEROUT(transfer)) {
438 			/* Isochronous write is not supported */
439 			err = LIBUSB_ERROR_NOT_SUPPORTED;
440 			break;
441 		}
442 		err = _sync_gen_transfer(itransfer);
443 		break;
444 	case LIBUSB_TRANSFER_TYPE_BULK:
445 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
446 		if (IS_XFEROUT(transfer) &&
447 		    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
448 			err = LIBUSB_ERROR_NOT_SUPPORTED;
449 			break;
450 		}
451 		err = _sync_gen_transfer(itransfer);
452 		break;
453 	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
454 		err = LIBUSB_ERROR_NOT_SUPPORTED;
455 		break;
456 	}
457 
458 	if (err)
459 		return err;
460 
461 	usbi_signal_transfer_completion(itransfer);
462 
463 	return LIBUSB_SUCCESS;
464 }
465 
466 int
obsd_cancel_transfer(struct usbi_transfer * itransfer)467 obsd_cancel_transfer(struct usbi_transfer *itransfer)
468 {
469 	UNUSED(itransfer);
470 
471 	usbi_dbg(ITRANSFER_CTX(itransfer), " ");
472 
473 	return LIBUSB_ERROR_NOT_SUPPORTED;
474 }
475 
476 int
obsd_handle_transfer_completion(struct usbi_transfer * itransfer)477 obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
478 {
479 	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
480 }
481 
482 int
_errno_to_libusb(int err)483 _errno_to_libusb(int err)
484 {
485 	usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
486 
487 	switch (err) {
488 	case EIO:
489 		return LIBUSB_ERROR_IO;
490 	case EACCES:
491 		return LIBUSB_ERROR_ACCESS;
492 	case ENOENT:
493 		return LIBUSB_ERROR_NO_DEVICE;
494 	case ENOMEM:
495 		return LIBUSB_ERROR_NO_MEM;
496 	case ETIMEDOUT:
497 		return LIBUSB_ERROR_TIMEOUT;
498 	default:
499 		return LIBUSB_ERROR_OTHER;
500 	}
501 }
502 
503 int
_cache_active_config_descriptor(struct libusb_device * dev)504 _cache_active_config_descriptor(struct libusb_device *dev)
505 {
506 	struct device_priv *dpriv = usbi_get_device_priv(dev);
507 	struct usb_device_cdesc udc;
508 	struct usb_device_fdesc udf;
509 	void *buf;
510 	int fd, len, err;
511 
512 	if ((fd = _bus_open(dev->bus_number)) < 0)
513 		return _errno_to_libusb(errno);
514 
515 	usbi_dbg(DEVICE_CTX(dev), "fd %d, addr %d", fd, dev->device_address);
516 
517 	udc.udc_bus = dev->bus_number;
518 	udc.udc_addr = dev->device_address;
519 	udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
520 	if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
521 		err = errno;
522 		close(fd);
523 		return _errno_to_libusb(errno);
524 	}
525 
526 	usbi_dbg(DEVICE_CTX(dev), "active bLength %d", udc.udc_desc.bLength);
527 
528 	len = UGETW(udc.udc_desc.wTotalLength);
529 	buf = malloc((size_t)len);
530 	if (buf == NULL)
531 		return LIBUSB_ERROR_NO_MEM;
532 
533 	udf.udf_bus = dev->bus_number;
534 	udf.udf_addr = dev->device_address;
535 	udf.udf_config_index = udc.udc_config_index;
536 	udf.udf_size = len;
537 	udf.udf_data = buf;
538 
539 	usbi_dbg(DEVICE_CTX(dev), "index %d, len %d", udf.udf_config_index, len);
540 
541 	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
542 		err = errno;
543 		close(fd);
544 		free(buf);
545 		return _errno_to_libusb(err);
546 	}
547 	close(fd);
548 
549 	if (dpriv->cdesc)
550 		free(dpriv->cdesc);
551 	dpriv->cdesc = buf;
552 
553 	return LIBUSB_SUCCESS;
554 }
555 
556 int
_sync_control_transfer(struct usbi_transfer * itransfer)557 _sync_control_transfer(struct usbi_transfer *itransfer)
558 {
559 	struct libusb_transfer *transfer;
560 	struct libusb_control_setup *setup;
561 	struct device_priv *dpriv;
562 	struct usb_ctl_request req;
563 
564 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
565 	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
566 	setup = (struct libusb_control_setup *)transfer->buffer;
567 
568 	usbi_dbg(ITRANSFER_CTX(itransfer), "type 0x%x request 0x%x value 0x%x index %d length %d timeout %d",
569 	    setup->bmRequestType, setup->bRequest,
570 	    libusb_le16_to_cpu(setup->wValue),
571 	    libusb_le16_to_cpu(setup->wIndex),
572 	    libusb_le16_to_cpu(setup->wLength), transfer->timeout);
573 
574 	req.ucr_addr = transfer->dev_handle->dev->device_address;
575 	req.ucr_request.bmRequestType = setup->bmRequestType;
576 	req.ucr_request.bRequest = setup->bRequest;
577 	/* Don't use USETW, libusb already deals with the endianness */
578 	(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
579 	(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
580 	(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
581 	req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
582 
583 	if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
584 		req.ucr_flags = USBD_SHORT_XFER_OK;
585 
586 	if (dpriv->devname == NULL) {
587 		/*
588 		 * XXX If the device is not attached to ugen(4) it is
589 		 * XXX still possible to submit a control transfer but
590 		 * XXX with the default timeout only.
591 		 */
592 		int fd, err;
593 
594 		if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
595 			return _errno_to_libusb(errno);
596 
597 		if (ioctl(fd, USB_REQUEST, &req) < 0) {
598 			err = errno;
599 			close(fd);
600 			return _errno_to_libusb(err);
601 		}
602 		close(fd);
603 	} else {
604 		if (ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout) < 0)
605 			return _errno_to_libusb(errno);
606 
607 		if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
608 			return _errno_to_libusb(errno);
609 	}
610 
611 	itransfer->transferred = req.ucr_actlen;
612 
613 	usbi_dbg(ITRANSFER_CTX(itransfer), "transferred %d", itransfer->transferred);
614 
615 	return 0;
616 }
617 
618 int
_access_endpoint(struct libusb_transfer * transfer)619 _access_endpoint(struct libusb_transfer *transfer)
620 {
621 	struct handle_priv *hpriv;
622 	struct device_priv *dpriv;
623 	char devnode[16];
624 	int fd, endpt;
625 	mode_t mode;
626 
627 	hpriv = usbi_get_device_handle_priv(transfer->dev_handle);
628 	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
629 
630 	endpt = UE_GET_ADDR(transfer->endpoint);
631 	mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
632 
633 	usbi_dbg(TRANSFER_CTX(transfer), "endpoint %d mode %d", endpt, mode);
634 
635 	if (hpriv->endpoints[endpt] < 0) {
636 		/* Pick the right endpoint node */
637 		snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
638 		    dpriv->devname, endpt);
639 
640 		/* We may need to read/write to the same endpoint later. */
641 		if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
642 			if ((fd = open(devnode, mode)) < 0)
643 				return -1;
644 
645 		hpriv->endpoints[endpt] = fd;
646 	}
647 
648 	return hpriv->endpoints[endpt];
649 }
650 
651 int
_sync_gen_transfer(struct usbi_transfer * itransfer)652 _sync_gen_transfer(struct usbi_transfer *itransfer)
653 {
654 	struct libusb_transfer *transfer;
655 	struct device_priv *dpriv;
656 	int fd, nr = 1;
657 
658 	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
659 	dpriv = usbi_get_device_priv(transfer->dev_handle->dev);
660 
661 	if (dpriv->devname == NULL)
662 		return LIBUSB_ERROR_NOT_SUPPORTED;
663 
664 	/*
665 	 * Bulk, Interrupt or Isochronous transfer depends on the
666 	 * endpoint and thus the node to open.
667 	 */
668 	if ((fd = _access_endpoint(transfer)) < 0)
669 		return _errno_to_libusb(errno);
670 
671 	if (ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout) < 0)
672 		return _errno_to_libusb(errno);
673 
674 	if (IS_XFERIN(transfer)) {
675 		if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
676 			if (ioctl(fd, USB_SET_SHORT_XFER, &nr) < 0)
677 				return _errno_to_libusb(errno);
678 
679 		nr = read(fd, transfer->buffer, transfer->length);
680 	} else {
681 		nr = write(fd, transfer->buffer, transfer->length);
682 	}
683 
684 	if (nr < 0)
685 		return _errno_to_libusb(errno);
686 
687 	itransfer->transferred = nr;
688 
689 	return 0;
690 }
691 
692 int
_bus_open(int number)693 _bus_open(int number)
694 {
695 	char busnode[16];
696 
697 	snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
698 
699 	return open(busnode, O_RDWR);
700 }
701