2 * Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org>
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.
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.
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
22 #include <sys/types.h>
31 #include <dev/usb/usb.h>
36 char *devname; /* name of the ugen(4) node */
37 int fd; /* device file descriptor */
39 unsigned char *cdesc; /* active config descriptor */
40 usb_device_descriptor_t ddesc; /* usb device descriptor */
44 int endpoints[USB_MAX_ENDPOINTS];
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 *);
55 static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *,
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 *);
62 static int obsd_get_configuration(struct libusb_device_handle *, int *);
63 static int obsd_set_configuration(struct libusb_device_handle *, int);
65 static int obsd_claim_interface(struct libusb_device_handle *, int);
66 static int obsd_release_interface(struct libusb_device_handle *, int);
68 static int obsd_set_interface_altsetting(struct libusb_device_handle *, 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 *);
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 *);
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 *);
89 static int _bus_open(int);
92 const struct usbi_os_backend usbi_backend = {
93 "Synchronous OpenBSD backend",
98 NULL, /* hotplug_poll */
102 obsd_get_device_descriptor,
103 obsd_get_active_config_descriptor,
104 obsd_get_config_descriptor,
105 NULL, /* get_config_descriptor_by_value() */
107 obsd_get_configuration,
108 obsd_set_configuration,
110 obsd_claim_interface,
111 obsd_release_interface,
113 obsd_set_interface_altsetting,
117 NULL, /* alloc_streams */
118 NULL, /* free_streams */
120 NULL, /* dev_mem_alloc() */
121 NULL, /* dev_mem_free() */
123 NULL, /* kernel_driver_active() */
124 NULL, /* detach_kernel_driver() */
125 NULL, /* attach_kernel_driver() */
129 obsd_submit_transfer,
130 obsd_cancel_transfer,
131 obsd_clear_transfer_priv,
133 NULL, /* handle_events() */
134 obsd_handle_transfer_completion,
137 0, /* context_priv_size */
138 sizeof(struct device_priv),
139 sizeof(struct handle_priv),
140 0, /* transfer_priv_size */
143 #define DEVPATH "/dev/"
144 #define USBDEV DEVPATH "usb"
147 obsd_get_device_list(struct libusb_context * ctx,
148 struct discovered_devs **discdevs)
150 struct discovered_devs *ddd;
151 struct libusb_device *dev;
152 struct device_priv *dpriv;
153 struct usb_device_info di;
154 struct usb_device_ddesc dd;
155 unsigned long session_id;
156 char devices[USB_MAX_DEVICES];
163 for (i = 0; i < 8; i++) {
164 snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
166 if ((fd = open(busnode, O_RDWR)) < 0) {
167 if (errno != ENOENT && errno != ENXIO)
168 usbi_err(ctx, "could not open %s", busnode);
172 bzero(devices, sizeof(devices));
173 for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
178 if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
182 * XXX If ugen(4) is attached to the USB device
186 for (j = 0; j < USB_MAX_DEVNAMES; j++)
187 if (!strncmp("ugen", di.udi_devnames[j], 4)) {
188 udevname = strdup(di.udi_devnames[j]);
192 session_id = (di.udi_bus << 8 | di.udi_addr);
193 dev = usbi_get_device_by_session_id(ctx, session_id);
196 dev = usbi_alloc_device(ctx, session_id);
199 return (LIBUSB_ERROR_NO_MEM);
202 dev->bus_number = di.udi_bus;
203 dev->device_address = di.udi_addr;
204 dev->speed = di.udi_speed;
206 dpriv = (struct device_priv *)dev->os_priv;
209 dpriv->devname = udevname;
211 dd.udd_bus = di.udi_bus;
212 dd.udd_addr = di.udi_addr;
213 if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
214 libusb_unref_device(dev);
217 dpriv->ddesc = dd.udd_desc;
219 if (_cache_active_config_descriptor(dev)) {
220 libusb_unref_device(dev);
224 if (usbi_sanitize_device(dev)) {
225 libusb_unref_device(dev);
230 ddd = discovered_devs_append(*discdevs, dev);
233 return (LIBUSB_ERROR_NO_MEM);
235 libusb_unref_device(dev);
244 return (LIBUSB_SUCCESS);
248 obsd_open(struct libusb_device_handle *handle)
250 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
251 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
254 if (dpriv->devname) {
256 * Only open ugen(4) attached devices read-write, all
257 * read-only operations are done through the bus node.
259 snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
261 dpriv->fd = open(devnode, O_RDWR);
263 return _errno_to_libusb(errno);
265 usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
268 return (LIBUSB_SUCCESS);
272 obsd_close(struct libusb_device_handle *handle)
274 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
275 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
277 if (dpriv->devname) {
278 usbi_dbg("close: fd %d", dpriv->fd);
286 obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
289 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
293 memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
297 return (LIBUSB_SUCCESS);
301 obsd_get_active_config_descriptor(struct libusb_device *dev,
302 unsigned char *buf, size_t len, int *host_endian)
304 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
305 usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
307 len = MIN(len, UGETW(ucd->wTotalLength));
309 usbi_dbg("len %d", len);
311 memcpy(buf, dpriv->cdesc, len);
319 obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
320 unsigned char *buf, size_t len, int *host_endian)
322 struct usb_device_fdesc udf;
325 if ((fd = _bus_open(dev->bus_number)) < 0)
326 return _errno_to_libusb(errno);
328 udf.udf_bus = dev->bus_number;
329 udf.udf_addr = dev->device_address;
330 udf.udf_config_index = idx;
334 usbi_dbg("index %d, len %d", udf.udf_config_index, len);
336 if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
339 return _errno_to_libusb(err);
349 obsd_get_configuration(struct libusb_device_handle *handle, int *config)
351 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
352 usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
354 *config = ucd->bConfigurationValue;
356 usbi_dbg("bConfigurationValue %d", *config);
358 return (LIBUSB_SUCCESS);
362 obsd_set_configuration(struct libusb_device_handle *handle, int config)
364 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
366 if (dpriv->devname == NULL)
367 return (LIBUSB_ERROR_NOT_SUPPORTED);
369 usbi_dbg("bConfigurationValue %d", config);
371 if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
372 return _errno_to_libusb(errno);
374 return _cache_active_config_descriptor(handle->dev);
378 obsd_claim_interface(struct libusb_device_handle *handle, int iface)
380 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
383 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
384 hpriv->endpoints[i] = -1;
386 return (LIBUSB_SUCCESS);
390 obsd_release_interface(struct libusb_device_handle *handle, int iface)
392 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
395 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
396 if (hpriv->endpoints[i] >= 0)
397 close(hpriv->endpoints[i]);
399 return (LIBUSB_SUCCESS);
403 obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
406 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
407 struct usb_alt_interface intf;
409 if (dpriv->devname == NULL)
410 return (LIBUSB_ERROR_NOT_SUPPORTED);
412 usbi_dbg("iface %d, setting %d", iface, altsetting);
414 memset(&intf, 0, sizeof(intf));
416 intf.uai_interface_index = iface;
417 intf.uai_alt_no = altsetting;
419 if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
420 return _errno_to_libusb(errno);
422 return (LIBUSB_SUCCESS);
426 obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
428 struct usb_ctl_request req;
431 if ((fd = _bus_open(handle->dev->bus_number)) < 0)
432 return _errno_to_libusb(errno);
436 req.ucr_addr = handle->dev->device_address;
437 req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
438 req.ucr_request.bRequest = UR_CLEAR_FEATURE;
439 USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
440 USETW(req.ucr_request.wIndex, endpoint);
441 USETW(req.ucr_request.wLength, 0);
443 if (ioctl(fd, USB_REQUEST, &req) < 0) {
446 return _errno_to_libusb(err);
450 return (LIBUSB_SUCCESS);
454 obsd_reset_device(struct libusb_device_handle *handle)
458 return (LIBUSB_ERROR_NOT_SUPPORTED);
462 obsd_destroy_device(struct libusb_device *dev)
464 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
469 free(dpriv->devname);
473 obsd_submit_transfer(struct usbi_transfer *itransfer)
475 struct libusb_transfer *transfer;
476 struct handle_priv *hpriv;
481 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
482 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
484 switch (transfer->type) {
485 case LIBUSB_TRANSFER_TYPE_CONTROL:
486 err = _sync_control_transfer(itransfer);
488 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
489 if (IS_XFEROUT(transfer)) {
490 /* Isochronous write is not supported */
491 err = LIBUSB_ERROR_NOT_SUPPORTED;
494 err = _sync_gen_transfer(itransfer);
496 case LIBUSB_TRANSFER_TYPE_BULK:
497 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
498 if (IS_XFEROUT(transfer) &&
499 transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
500 err = LIBUSB_ERROR_NOT_SUPPORTED;
503 err = _sync_gen_transfer(itransfer);
505 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
506 err = LIBUSB_ERROR_NOT_SUPPORTED;
513 usbi_signal_transfer_completion(itransfer);
515 return (LIBUSB_SUCCESS);
519 obsd_cancel_transfer(struct usbi_transfer *itransfer)
523 return (LIBUSB_ERROR_NOT_SUPPORTED);
527 obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
535 obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
537 return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
541 obsd_clock_gettime(int clkid, struct timespec *tp)
543 usbi_dbg("clock %d", clkid);
545 if (clkid == USBI_CLOCK_REALTIME)
546 return clock_gettime(CLOCK_REALTIME, tp);
548 if (clkid == USBI_CLOCK_MONOTONIC)
549 return clock_gettime(CLOCK_MONOTONIC, tp);
551 return (LIBUSB_ERROR_INVALID_PARAM);
555 _errno_to_libusb(int err)
557 usbi_dbg("error: %s (%d)", strerror(err), err);
561 return (LIBUSB_ERROR_IO);
563 return (LIBUSB_ERROR_ACCESS);
565 return (LIBUSB_ERROR_NO_DEVICE);
567 return (LIBUSB_ERROR_NO_MEM);
569 return (LIBUSB_ERROR_TIMEOUT);
572 return (LIBUSB_ERROR_OTHER);
576 _cache_active_config_descriptor(struct libusb_device *dev)
578 struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
579 struct usb_device_cdesc udc;
580 struct usb_device_fdesc udf;
584 if ((fd = _bus_open(dev->bus_number)) < 0)
585 return _errno_to_libusb(errno);
587 usbi_dbg("fd %d, addr %d", fd, dev->device_address);
589 udc.udc_bus = dev->bus_number;
590 udc.udc_addr = dev->device_address;
591 udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
592 if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
595 return _errno_to_libusb(errno);
598 usbi_dbg("active bLength %d", udc.udc_desc.bLength);
600 len = UGETW(udc.udc_desc.wTotalLength);
603 return (LIBUSB_ERROR_NO_MEM);
605 udf.udf_bus = dev->bus_number;
606 udf.udf_addr = dev->device_address;
607 udf.udf_config_index = udc.udc_config_index;
611 usbi_dbg("index %d, len %d", udf.udf_config_index, len);
613 if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
617 return _errno_to_libusb(err);
625 return (LIBUSB_SUCCESS);
629 _sync_control_transfer(struct usbi_transfer *itransfer)
631 struct libusb_transfer *transfer;
632 struct libusb_control_setup *setup;
633 struct device_priv *dpriv;
634 struct usb_ctl_request req;
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;
640 usbi_dbg("type %x request %x value %x 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);
646 req.ucr_addr = transfer->dev_handle->dev->device_address;
647 req.ucr_request.bmRequestType = setup->bmRequestType;
648 req.ucr_request.bRequest = setup->bRequest;
649 /* Don't use USETW, libusb already deals with the endianness */
650 (*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
651 (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
652 (*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
653 req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
655 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
656 req.ucr_flags = USBD_SHORT_XFER_OK;
658 if (dpriv->devname == NULL) {
660 * XXX If the device is not attached to ugen(4) it is
661 * XXX still possible to submit a control transfer but
662 * XXX with the default timeout only.
666 if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
667 return _errno_to_libusb(errno);
669 if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
672 return _errno_to_libusb(err);
676 if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
677 return _errno_to_libusb(errno);
679 if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
680 return _errno_to_libusb(errno);
683 itransfer->transferred = req.ucr_actlen;
685 usbi_dbg("transferred %d", itransfer->transferred);
691 _access_endpoint(struct libusb_transfer *transfer)
693 struct handle_priv *hpriv;
694 struct device_priv *dpriv;
699 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
700 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
702 endpt = UE_GET_ADDR(transfer->endpoint);
703 mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
705 usbi_dbg("endpoint %d mode %d", endpt, mode);
707 if (hpriv->endpoints[endpt] < 0) {
708 /* Pick the right endpoint node */
709 snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
710 dpriv->devname, endpt);
712 /* We may need to read/write to the same endpoint later. */
713 if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
714 if ((fd = open(devnode, mode)) < 0)
717 hpriv->endpoints[endpt] = fd;
720 return (hpriv->endpoints[endpt]);
724 _sync_gen_transfer(struct usbi_transfer *itransfer)
726 struct libusb_transfer *transfer;
727 struct device_priv *dpriv;
730 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
731 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
733 if (dpriv->devname == NULL)
734 return (LIBUSB_ERROR_NOT_SUPPORTED);
737 * Bulk, Interrupt or Isochronous transfer depends on the
738 * endpoint and thus the node to open.
740 if ((fd = _access_endpoint(transfer)) < 0)
741 return _errno_to_libusb(errno);
743 if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
744 return _errno_to_libusb(errno);
746 if (IS_XFERIN(transfer)) {
747 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
748 if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
749 return _errno_to_libusb(errno);
751 nr = read(fd, transfer->buffer, transfer->length);
753 nr = write(fd, transfer->buffer, transfer->length);
757 return _errno_to_libusb(errno);
759 itransfer->transferred = nr;
765 _bus_open(int number)
769 snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
771 return open(busnode, O_RDWR);