summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Hjelm <hjelmn@google.com>2021-07-21 11:49:37 -0600
committerNathan Hjelm <hjelmn@cs.unm.edu>2021-07-21 23:07:17 -0600
commitf8dc6af91607d5d2202c47b3b62e107df9197184 (patch)
treef5b2069045b6329f405df9d09cc517cb5213aaf3
parent42f9c3b43f49f22a3b10ed452f500f6f50c093df (diff)
downloadlibusb-f8dc6af91607d5d2202c47b3b62e107df9197184.tar.gz
darwin: use the IO registry to detect if a kernel driver is attached to an interface
The implementation of libusb_kernel_driver_active was attempting to open the interface to check if a driver is attached. This may have side effects (like configuring the device) that may be unexpected to the user. This commit updates the code to find the interface's IO registry entry (either IOUSBHostInterface or the legacy IOUSBInterface) and check if the entry has a child entry. A child entry indicates that a driver is currently attached. Signed-off-by: Nathan Hjelm <hjelmn@google.com>
-rw-r--r--configure.ac1
-rw-r--r--libusb/os/darwin_usb.c45
-rw-r--r--libusb/os/darwin_usb.h12
-rw-r--r--libusb/version_nano.h2
4 files changed, 55 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index 5899fc2..4302b53 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,7 @@ case $backend in
darwin)
AC_CHECK_FUNCS([pthread_threadid_np])
LIBS="${LIBS} -lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation -Wl,-framework,Security"
+ AC_CHECK_HEADERS([IOKit/usb/IOUSBHostFamilyDefinitions.h])
;;
haiku)
LIBS="${LIBS} -lbe"
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index afa13c2..85ca1e8 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -1815,12 +1815,49 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
}
}
+static io_service_t usb_find_interface_matching_location (const io_name_t class_name, UInt8 interface_number, UInt32 location) {
+ CFMutableDictionaryRef matchingDict = IOServiceMatching (class_name);
+ CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
+ CFTypeRef interfaceCF = CFNumberCreate (NULL, kCFNumberSInt8Type, &interface_number);
+
+ CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
+ CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
+ CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBHostMatchingPropertyInterfaceNumber), interfaceCF);
+
+ CFRelease (interfaceCF);
+ CFRelease (locationCF);
+ CFRelease (propertyMatchDict);
+
+ return IOServiceGetMatchingService (kIOMasterPortDefault, matchingDict);
+}
+
static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, uint8_t interface) {
- enum libusb_error ret = darwin_claim_interface (dev_handle, interface);
- if (ret == LIBUSB_SUCCESS) {
- darwin_release_interface (dev_handle, interface);
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
+ io_service_t usb_interface, child = IO_OBJECT_NULL;
+
+ /* locate the IO registry entry for this interface */
+ usb_interface = usb_find_interface_matching_location (kIOUSBHostInterfaceClassName, interface, dpriv->location);
+ if (0 == usb_interface) {
+ /* check for the legacy class entry */
+ usb_interface = usb_find_interface_matching_location (kIOUSBInterfaceClassName, interface, dpriv->location);
+ if (0 == usb_interface) {
+ return LIBUSB_ERROR_NOT_FOUND;
+ }
+ }
+
+ /* if the IO object has a child entry in the IO Registry it has a kernel driver attached */
+ (void) IORegistryEntryGetChildEntry (usb_interface, kIOServicePlane, &child);
+ IOObjectRelease (usb_interface);
+ if (IO_OBJECT_NULL != child) {
+ IOObjectRelease (child);
+ return 1;
}
- return (ret == LIBUSB_ERROR_ACCESS);
+
+ /* no driver */
+ return 0;
}
static void darwin_destroy_device(struct libusb_device *dev) {
diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h
index 9021266..7b72fff 100644
--- a/libusb/os/darwin_usb.h
+++ b/libusb/os/darwin_usb.h
@@ -30,6 +30,10 @@
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
+#if defined(HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H)
+#include <IOKit/usb/IOUSBHostFamilyDefinitions.h>
+#endif
+
/* IOUSBInterfaceInferface */
/* New in OS 10.12.0. */
@@ -144,6 +148,14 @@
#endif
+#if !defined(kIOUSBHostInterfaceClassName)
+#define kIOUSBHostInterfaceClassName "IOUSBHostInterface"
+#endif
+
+#if !defined(kUSBHostMatchingPropertyInterfaceNumber)
+#define kUSBHostMatchingPropertyInterfaceNumber "bInterfaceNumber"
+#endif
+
#if !defined(IO_OBJECT_NULL)
#define IO_OBJECT_NULL ((io_object_t) 0)
#endif
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 374ee65..8dd74ce 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11642
+#define LIBUSB_NANO 11643