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
20 #include <sys/types.h>
29 #include <dev/usb/usb.h>
35 char *devname
; /* name of the ugen(4) node */
36 int fd
; /* device file descriptor */
38 unsigned char *cdesc
; /* active config descriptor */
39 usb_device_descriptor_t ddesc
; /* usb device descriptor */
43 int pipe
[2]; /* for event notification */
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_events(struct libusb_context
*ctx
, struct pollfd
*,
79 static int obsd_clock_gettime(int, struct timespec
*);
84 static int _errno_to_libusb(int);
85 static int _cache_active_config_descriptor(struct libusb_device
*);
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
*);
90 static int _bus_open(int);
93 const struct usbi_os_backend openbsd_backend
= {
94 "Synchronous OpenBSD backend",
99 NULL
, /* hotplug_poll */
103 obsd_get_device_descriptor
,
104 obsd_get_active_config_descriptor
,
105 obsd_get_config_descriptor
,
106 NULL
, /* get_config_descriptor_by_value() */
108 obsd_get_configuration
,
109 obsd_set_configuration
,
111 obsd_claim_interface
,
112 obsd_release_interface
,
114 obsd_set_interface_altsetting
,
118 NULL
, /* kernel_driver_active() */
119 NULL
, /* detach_kernel_driver() */
120 NULL
, /* attach_kernel_driver() */
124 obsd_submit_transfer
,
125 obsd_cancel_transfer
,
126 obsd_clear_transfer_priv
,
131 sizeof(struct device_priv
),
132 sizeof(struct handle_priv
),
133 0, /* transfer_priv_size */
134 0, /* add_iso_packet_size */
137 #define DEVPATH "/dev/"
138 #define USBDEV DEVPATH "usb"
141 obsd_get_device_list(struct libusb_context
* ctx
,
142 struct discovered_devs
**discdevs
)
144 struct discovered_devs
*ddd
;
145 struct libusb_device
*dev
;
146 struct device_priv
*dpriv
;
147 struct usb_device_info di
;
148 struct usb_device_ddesc dd
;
149 unsigned long session_id
;
150 char devices
[USB_MAX_DEVICES
];
157 for (i
= 0; i
< 8; i
++) {
158 snprintf(busnode
, sizeof(busnode
), USBDEV
"%d", i
);
160 if ((fd
= open(busnode
, O_RDWR
)) < 0) {
161 if (errno
!= ENOENT
&& errno
!= ENXIO
)
162 usbi_err(ctx
, "could not open %s", busnode
);
166 bzero(devices
, sizeof(devices
));
167 for (addr
= 1; addr
< USB_MAX_DEVICES
; addr
++) {
172 if (ioctl(fd
, USB_DEVICEINFO
, &di
) < 0)
176 * XXX If ugen(4) is attached to the USB device
180 for (j
= 0; j
< USB_MAX_DEVNAMES
; j
++)
181 if (!strncmp("ugen", di
.udi_devnames
[j
], 4)) {
182 udevname
= strdup(di
.udi_devnames
[j
]);
186 session_id
= (di
.udi_bus
<< 8 | di
.udi_addr
);
187 dev
= usbi_get_device_by_session_id(ctx
, session_id
);
190 dev
= usbi_alloc_device(ctx
, session_id
);
193 return (LIBUSB_ERROR_NO_MEM
);
196 dev
->bus_number
= di
.udi_bus
;
197 dev
->device_address
= di
.udi_addr
;
198 dev
->speed
= di
.udi_speed
;
200 dpriv
= (struct device_priv
*)dev
->os_priv
;
203 dpriv
->devname
= udevname
;
205 dd
.udd_bus
= di
.udi_bus
;
206 dd
.udd_addr
= di
.udi_addr
;
207 if (ioctl(fd
, USB_DEVICE_GET_DDESC
, &dd
) < 0) {
208 libusb_unref_device(dev
);
211 dpriv
->ddesc
= dd
.udd_desc
;
213 if (_cache_active_config_descriptor(dev
)) {
214 libusb_unref_device(dev
);
218 if (usbi_sanitize_device(dev
)) {
219 libusb_unref_device(dev
);
224 ddd
= discovered_devs_append(*discdevs
, dev
);
227 return (LIBUSB_ERROR_NO_MEM
);
229 libusb_unref_device(dev
);
238 return (LIBUSB_SUCCESS
);
242 obsd_open(struct libusb_device_handle
*handle
)
244 struct handle_priv
*hpriv
= (struct handle_priv
*)handle
->os_priv
;
245 struct device_priv
*dpriv
= (struct device_priv
*)handle
->dev
->os_priv
;
248 if (dpriv
->devname
) {
250 * Only open ugen(4) attached devices read-write, all
251 * read-only operations are done through the bus node.
253 snprintf(devnode
, sizeof(devnode
), DEVPATH
"%s.00",
255 dpriv
->fd
= open(devnode
, O_RDWR
);
257 return _errno_to_libusb(errno
);
259 usbi_dbg("open %s: fd %d", devnode
, dpriv
->fd
);
262 if (pipe(hpriv
->pipe
) < 0)
263 return _errno_to_libusb(errno
);
265 return usbi_add_pollfd(HANDLE_CTX(handle
), hpriv
->pipe
[0], POLLIN
);
269 obsd_close(struct libusb_device_handle
*handle
)
271 struct handle_priv
*hpriv
= (struct handle_priv
*)handle
->os_priv
;
272 struct device_priv
*dpriv
= (struct device_priv
*)handle
->dev
->os_priv
;
274 if (dpriv
->devname
) {
275 usbi_dbg("close: fd %d", dpriv
->fd
);
281 usbi_remove_pollfd(HANDLE_CTX(handle
), hpriv
->pipe
[0]);
283 close(hpriv
->pipe
[0]);
284 close(hpriv
->pipe
[1]);
288 obsd_get_device_descriptor(struct libusb_device
*dev
, unsigned char *buf
,
291 struct device_priv
*dpriv
= (struct device_priv
*)dev
->os_priv
;
295 memcpy(buf
, &dpriv
->ddesc
, DEVICE_DESC_LENGTH
);
299 return (LIBUSB_SUCCESS
);
303 obsd_get_active_config_descriptor(struct libusb_device
*dev
,
304 unsigned char *buf
, size_t len
, int *host_endian
)
306 struct device_priv
*dpriv
= (struct device_priv
*)dev
->os_priv
;
307 usb_config_descriptor_t
*ucd
= (usb_config_descriptor_t
*)dpriv
->cdesc
;
309 len
= MIN(len
, UGETW(ucd
->wTotalLength
));
311 usbi_dbg("len %d", len
);
313 memcpy(buf
, dpriv
->cdesc
, len
);
321 obsd_get_config_descriptor(struct libusb_device
*dev
, uint8_t idx
,
322 unsigned char *buf
, size_t len
, int *host_endian
)
324 struct usb_device_fdesc udf
;
327 if ((fd
= _bus_open(dev
->bus_number
)) < 0)
328 return _errno_to_libusb(errno
);
330 udf
.udf_bus
= dev
->bus_number
;
331 udf
.udf_addr
= dev
->device_address
;
332 udf
.udf_config_index
= idx
;
336 usbi_dbg("index %d, len %d", udf
.udf_config_index
, len
);
338 if (ioctl(fd
, USB_DEVICE_GET_FDESC
, &udf
) < 0) {
341 return _errno_to_libusb(err
);
351 obsd_get_configuration(struct libusb_device_handle
*handle
, int *config
)
353 struct device_priv
*dpriv
= (struct device_priv
*)handle
->dev
->os_priv
;
354 usb_config_descriptor_t
*ucd
= (usb_config_descriptor_t
*)dpriv
->cdesc
;
356 *config
= ucd
->bConfigurationValue
;
358 usbi_dbg("bConfigurationValue %d", *config
);
360 return (LIBUSB_SUCCESS
);
364 obsd_set_configuration(struct libusb_device_handle
*handle
, int config
)
366 struct device_priv
*dpriv
= (struct device_priv
*)handle
->dev
->os_priv
;
368 if (dpriv
->devname
== NULL
)
369 return (LIBUSB_ERROR_NOT_SUPPORTED
);
371 usbi_dbg("bConfigurationValue %d", config
);
373 if (ioctl(dpriv
->fd
, USB_SET_CONFIG
, &config
) < 0)
374 return _errno_to_libusb(errno
);
376 return _cache_active_config_descriptor(handle
->dev
);
380 obsd_claim_interface(struct libusb_device_handle
*handle
, int iface
)
382 struct handle_priv
*hpriv
= (struct handle_priv
*)handle
->os_priv
;
385 for (i
= 0; i
< USB_MAX_ENDPOINTS
; i
++)
386 hpriv
->endpoints
[i
] = -1;
388 return (LIBUSB_SUCCESS
);
392 obsd_release_interface(struct libusb_device_handle
*handle
, int iface
)
394 struct handle_priv
*hpriv
= (struct handle_priv
*)handle
->os_priv
;
397 for (i
= 0; i
< USB_MAX_ENDPOINTS
; i
++)
398 if (hpriv
->endpoints
[i
] >= 0)
399 close(hpriv
->endpoints
[i
]);
401 return (LIBUSB_SUCCESS
);
405 obsd_set_interface_altsetting(struct libusb_device_handle
*handle
, int iface
,
408 struct device_priv
*dpriv
= (struct device_priv
*)handle
->dev
->os_priv
;
409 struct usb_alt_interface intf
;
411 if (dpriv
->devname
== NULL
)
412 return (LIBUSB_ERROR_NOT_SUPPORTED
);
414 usbi_dbg("iface %d, setting %d", iface
, altsetting
);
416 memset(&intf
, 0, sizeof(intf
));
418 intf
.uai_interface_index
= iface
;
419 intf
.uai_alt_no
= altsetting
;
421 if (ioctl(dpriv
->fd
, USB_SET_ALTINTERFACE
, &intf
) < 0)
422 return _errno_to_libusb(errno
);
424 return (LIBUSB_SUCCESS
);
428 obsd_clear_halt(struct libusb_device_handle
*handle
, unsigned char endpoint
)
430 struct usb_ctl_request req
;
433 if ((fd
= _bus_open(handle
->dev
->bus_number
)) < 0)
434 return _errno_to_libusb(errno
);
438 req
.ucr_addr
= handle
->dev
->device_address
;
439 req
.ucr_request
.bmRequestType
= UT_WRITE_ENDPOINT
;
440 req
.ucr_request
.bRequest
= UR_CLEAR_FEATURE
;
441 USETW(req
.ucr_request
.wValue
, UF_ENDPOINT_HALT
);
442 USETW(req
.ucr_request
.wIndex
, endpoint
);
443 USETW(req
.ucr_request
.wLength
, 0);
445 if (ioctl(fd
, USB_REQUEST
, &req
) < 0) {
448 return _errno_to_libusb(err
);
452 return (LIBUSB_SUCCESS
);
456 obsd_reset_device(struct libusb_device_handle
*handle
)
460 return (LIBUSB_ERROR_NOT_SUPPORTED
);
464 obsd_destroy_device(struct libusb_device
*dev
)
466 struct device_priv
*dpriv
= (struct device_priv
*)dev
->os_priv
;
471 free(dpriv
->devname
);
475 obsd_submit_transfer(struct usbi_transfer
*itransfer
)
477 struct libusb_transfer
*transfer
;
478 struct handle_priv
*hpriv
;
483 transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
484 hpriv
= (struct handle_priv
*)transfer
->dev_handle
->os_priv
;
486 switch (transfer
->type
) {
487 case LIBUSB_TRANSFER_TYPE_CONTROL
:
488 err
= _sync_control_transfer(itransfer
);
490 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
491 if (IS_XFEROUT(transfer
)) {
492 /* Isochronous write is not supported */
493 err
= LIBUSB_ERROR_NOT_SUPPORTED
;
496 err
= _sync_gen_transfer(itransfer
);
498 case LIBUSB_TRANSFER_TYPE_BULK
:
499 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
500 if (IS_XFEROUT(transfer
) &&
501 transfer
->flags
& LIBUSB_TRANSFER_ADD_ZERO_PACKET
) {
502 err
= LIBUSB_ERROR_NOT_SUPPORTED
;
505 err
= _sync_gen_transfer(itransfer
);
512 if (write(hpriv
->pipe
[1], &itransfer
, sizeof(itransfer
)) < 0)
513 return _errno_to_libusb(errno
);
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_events(struct libusb_context
*ctx
, struct pollfd
*fds
, nfds_t nfds
,
538 struct libusb_device_handle
*handle
;
539 struct handle_priv
*hpriv
= NULL
;
540 struct usbi_transfer
*itransfer
;
541 struct pollfd
*pollfd
;
546 pthread_mutex_lock(&ctx
->open_devs_lock
);
547 for (i
= 0; i
< nfds
&& num_ready
> 0; i
++) {
550 if (!pollfd
->revents
)
555 list_for_each_entry(handle
, &ctx
->open_devs
, list
,
556 struct libusb_device_handle
) {
557 hpriv
= (struct handle_priv
*)handle
->os_priv
;
559 if (hpriv
->pipe
[0] == pollfd
->fd
)
566 usbi_dbg("fd %d is not an event pipe!", pollfd
->fd
);
571 if (pollfd
->revents
& POLLERR
) {
572 usbi_remove_pollfd(HANDLE_CTX(handle
), hpriv
->pipe
[0]);
573 usbi_handle_disconnect(handle
);
577 if (read(hpriv
->pipe
[0], &itransfer
, sizeof(itransfer
)) < 0) {
582 if ((err
= usbi_handle_transfer_completion(itransfer
,
583 LIBUSB_TRANSFER_COMPLETED
)))
586 pthread_mutex_unlock(&ctx
->open_devs_lock
);
589 return _errno_to_libusb(err
);
591 return (LIBUSB_SUCCESS
);
595 obsd_clock_gettime(int clkid
, struct timespec
*tp
)
597 usbi_dbg("clock %d", clkid
);
599 if (clkid
== USBI_CLOCK_REALTIME
)
600 return clock_gettime(CLOCK_REALTIME
, tp
);
602 if (clkid
== USBI_CLOCK_MONOTONIC
)
603 return clock_gettime(CLOCK_MONOTONIC
, tp
);
605 return (LIBUSB_ERROR_INVALID_PARAM
);
609 _errno_to_libusb(int err
)
611 usbi_dbg("error: %s (%d)", strerror(err
), err
);
615 return (LIBUSB_ERROR_IO
);
617 return (LIBUSB_ERROR_ACCESS
);
619 return (LIBUSB_ERROR_NO_DEVICE
);
621 return (LIBUSB_ERROR_NO_MEM
);
623 return (LIBUSB_ERROR_TIMEOUT
);
626 return (LIBUSB_ERROR_OTHER
);
630 _cache_active_config_descriptor(struct libusb_device
*dev
)
632 struct device_priv
*dpriv
= (struct device_priv
*)dev
->os_priv
;
633 struct usb_device_cdesc udc
;
634 struct usb_device_fdesc udf
;
638 if ((fd
= _bus_open(dev
->bus_number
)) < 0)
639 return _errno_to_libusb(errno
);
641 usbi_dbg("fd %d, addr %d", fd
, dev
->device_address
);
643 udc
.udc_bus
= dev
->bus_number
;
644 udc
.udc_addr
= dev
->device_address
;
645 udc
.udc_config_index
= USB_CURRENT_CONFIG_INDEX
;
646 if (ioctl(fd
, USB_DEVICE_GET_CDESC
, &udc
) < 0) {
649 return _errno_to_libusb(errno
);
652 usbi_dbg("active bLength %d", udc
.udc_desc
.bLength
);
654 len
= UGETW(udc
.udc_desc
.wTotalLength
);
657 return (LIBUSB_ERROR_NO_MEM
);
659 udf
.udf_bus
= dev
->bus_number
;
660 udf
.udf_addr
= dev
->device_address
;
661 udf
.udf_config_index
= udc
.udc_config_index
;
665 usbi_dbg("index %d, len %d", udf
.udf_config_index
, len
);
667 if (ioctl(fd
, USB_DEVICE_GET_FDESC
, &udf
) < 0) {
671 return _errno_to_libusb(err
);
679 return (LIBUSB_SUCCESS
);
683 _sync_control_transfer(struct usbi_transfer
*itransfer
)
685 struct libusb_transfer
*transfer
;
686 struct libusb_control_setup
*setup
;
687 struct device_priv
*dpriv
;
688 struct usb_ctl_request req
;
690 transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
691 dpriv
= (struct device_priv
*)transfer
->dev_handle
->dev
->os_priv
;
692 setup
= (struct libusb_control_setup
*)transfer
->buffer
;
694 usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
695 setup
->bmRequestType
, setup
->bRequest
,
696 libusb_le16_to_cpu(setup
->wValue
),
697 libusb_le16_to_cpu(setup
->wIndex
),
698 libusb_le16_to_cpu(setup
->wLength
), transfer
->timeout
);
700 req
.ucr_addr
= transfer
->dev_handle
->dev
->device_address
;
701 req
.ucr_request
.bmRequestType
= setup
->bmRequestType
;
702 req
.ucr_request
.bRequest
= setup
->bRequest
;
703 /* Don't use USETW, libusbx already deals with the endianness */
704 (*(uint16_t *)req
.ucr_request
.wValue
) = setup
->wValue
;
705 (*(uint16_t *)req
.ucr_request
.wIndex
) = setup
->wIndex
;
706 (*(uint16_t *)req
.ucr_request
.wLength
) = setup
->wLength
;
707 req
.ucr_data
= transfer
->buffer
+ LIBUSB_CONTROL_SETUP_SIZE
;
709 if ((transfer
->flags
& LIBUSB_TRANSFER_SHORT_NOT_OK
) == 0)
710 req
.ucr_flags
= USBD_SHORT_XFER_OK
;
712 if (dpriv
->devname
== NULL
) {
714 * XXX If the device is not attached to ugen(4) it is
715 * XXX still possible to submit a control transfer but
716 * XXX with the default timeout only.
720 if ((fd
= _bus_open(transfer
->dev_handle
->dev
->bus_number
)) < 0)
721 return _errno_to_libusb(errno
);
723 if ((ioctl(fd
, USB_REQUEST
, &req
)) < 0) {
726 return _errno_to_libusb(err
);
730 if ((ioctl(dpriv
->fd
, USB_SET_TIMEOUT
, &transfer
->timeout
)) < 0)
731 return _errno_to_libusb(errno
);
733 if ((ioctl(dpriv
->fd
, USB_DO_REQUEST
, &req
)) < 0)
734 return _errno_to_libusb(errno
);
737 itransfer
->transferred
= req
.ucr_actlen
;
739 usbi_dbg("transferred %d", itransfer
->transferred
);
745 _access_endpoint(struct libusb_transfer
*transfer
)
747 struct handle_priv
*hpriv
;
748 struct device_priv
*dpriv
;
753 hpriv
= (struct handle_priv
*)transfer
->dev_handle
->os_priv
;
754 dpriv
= (struct device_priv
*)transfer
->dev_handle
->dev
->os_priv
;
756 endpt
= UE_GET_ADDR(transfer
->endpoint
);
757 mode
= IS_XFERIN(transfer
) ? O_RDONLY
: O_WRONLY
;
759 usbi_dbg("endpoint %d mode %d", endpt
, mode
);
761 if (hpriv
->endpoints
[endpt
] < 0) {
762 /* Pick the right endpoint node */
763 snprintf(devnode
, sizeof(devnode
), DEVPATH
"%s.%02d",
764 dpriv
->devname
, endpt
);
766 /* We may need to read/write to the same endpoint later. */
767 if (((fd
= open(devnode
, O_RDWR
)) < 0) && (errno
== ENXIO
))
768 if ((fd
= open(devnode
, mode
)) < 0)
771 hpriv
->endpoints
[endpt
] = fd
;
774 return (hpriv
->endpoints
[endpt
]);
778 _sync_gen_transfer(struct usbi_transfer
*itransfer
)
780 struct libusb_transfer
*transfer
;
781 struct device_priv
*dpriv
;
784 transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
785 dpriv
= (struct device_priv
*)transfer
->dev_handle
->dev
->os_priv
;
787 if (dpriv
->devname
== NULL
)
788 return (LIBUSB_ERROR_NOT_SUPPORTED
);
791 * Bulk, Interrupt or Isochronous transfer depends on the
792 * endpoint and thus the node to open.
794 if ((fd
= _access_endpoint(transfer
)) < 0)
795 return _errno_to_libusb(errno
);
797 if ((ioctl(fd
, USB_SET_TIMEOUT
, &transfer
->timeout
)) < 0)
798 return _errno_to_libusb(errno
);
800 if (IS_XFERIN(transfer
)) {
801 if ((transfer
->flags
& LIBUSB_TRANSFER_SHORT_NOT_OK
) == 0)
802 if ((ioctl(fd
, USB_SET_SHORT_XFER
, &nr
)) < 0)
803 return _errno_to_libusb(errno
);
805 nr
= read(fd
, transfer
->buffer
, transfer
->length
);
807 nr
= write(fd
, transfer
->buffer
, transfer
->length
);
811 return _errno_to_libusb(errno
);
813 itransfer
->transferred
= nr
;
819 _bus_open(int number
)
823 snprintf(busnode
, sizeof(busnode
), USBDEV
"%d", number
);
825 return open(busnode
, O_RDWR
);