This patch fixes my USB scanner. Tested with 'scanimage' from sane-backends.
While Sane searches for scanners to use it loops over multiple backends. Each backend attempts to open a ugen(4) device node. An open file descriptor for e.g. /dev/ugen0.00 is stored in the libusb handle's OS-specific part, called dpriv->fd in our case (see patch below). Once a backend succeeds in attaching a scanner, other backends may still probe the USB bus for additional scanners. This results in more attempts to open the same device node, all of which fail with EBUSY. When this happens, the current code will overwrite dpriv->fd with -1. Once Sane is done with identifying scanners, it will ask the backend which opened the device to scan an image. Access to the device node now fails with EBADF because libusb is passing -1 to the kernel instead of the open file descriptor for the device node. ok? diff 7fd6913f7aa70c6616d7835c31c8a7254173a028 /usr/ports blob - a3db2a0bd6a74ccc9505b6bf38fa2960b25d94ab file + devel/libusb1/Makefile --- devel/libusb1/Makefile +++ devel/libusb1/Makefile @@ -5,7 +5,7 @@ COMMENT = library for USB device access from userspac VERSION = 1.0.23 DISTNAME = libusb-${VERSION} PKGNAME = libusb1-${VERSION} -REVISION = 0 +REVISION = 1 SHARED_LIBS += usb-1.0 1.2 # 2.0 blob - 52378c80f3536f6fc0822553606bc1cd73af69db file + devel/libusb1/patches/patch-libusb_os_openbsd_usb_c --- devel/libusb1/patches/patch-libusb_os_openbsd_usb_c +++ devel/libusb1/patches/patch-libusb_os_openbsd_usb_c @@ -2,6 +2,10 @@ $OpenBSD: patch-libusb_os_openbsd_usb_c,v 1.8 2019/11/ Export port number, fix github #314. +Fix an OpenBSD backend bug where an existing open file descriptor is +overwritten if a libusb user attempts to open the same ugen(4) device +multiple times. This was observed with sane-backends and broke scanning. + Index: libusb/os/openbsd_usb.c --- libusb/os/openbsd_usb.c.orig +++ libusb/os/openbsd_usb.c @@ -13,3 +17,23 @@ Index: libusb/os/openbsd_usb.c dpriv = (struct device_priv *)dev->os_priv; dpriv->fd = -1; +@@ -232,15 +233,17 @@ obsd_open(struct libusb_device_handle *handle) + char devnode[16]; + + if (dpriv->devname) { ++ int fd; + /* + * Only open ugen(4) attached devices read-write, all + * read-only operations are done through the bus node. + */ + snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", + dpriv->devname); +- dpriv->fd = open(devnode, O_RDWR); +- if (dpriv->fd < 0) ++ fd = open(devnode, O_RDWR); ++ if (fd < 0) + return _errno_to_libusb(errno); ++ dpriv->fd = fd; + + usbi_dbg("open %s: fd %d", devnode, dpriv->fd); + }