From 871eb299b989bc0714391804a9d2fdb145a32ff5 Mon Sep 17 00:00:00 2001 From: tich Date: Mon, 13 Mar 2017 09:37:33 -0700 Subject: [PATCH] macOS Sierra: Fix detection of parent devices. This fixes the output of libusb_get_port_numbers(), where it used to merely return the port number of the device itself. Now that libusb properly detects parent devices, we get the entire port path of the device. For reference, here's the output of the 'listdevs' example before my changes: tich-mbp:libusb-1.0.21 tich$ ./examples/listdevs 0409:005a (bus 29, device 6) path: 1 05ac:8509 (bus 26, device 2) path: 1 05ac:821d (bus 29, device 7) path: 3 05ac:0252 (bus 29, device 5) path: 3 05ac:8242 (bus 29, device 4) path: 2 0a5c:4500 (bus 29, device 3) path: 1 0424:2513 (bus 29, device 2) path: 8 8087:0024 (bus 29, device 1) path: 1 8087:0024 (bus 26, device 1) path: 1 And here's the output after my changes: tich-mbp:libusb-1.0.21 tich$ ./examples/listdevs 0409:005a (bus 29, device 6) path: 1.1 05ac:8509 (bus 26, device 2) path: 1.1 05ac:821d (bus 29, device 7) path: 1.8.1.3 05ac:0252 (bus 29, device 5) path: 1.8.3 05ac:8242 (bus 29, device 4) path: 1.8.2 0a5c:4500 (bus 29, device 3) path: 1.8.1 0424:2513 (bus 29, device 2) path: 1.8 8087:0024 (bus 29, device 1) path: 1 8087:0024 (bus 26, device 1) path: 1 Since we're now using "IOUSBHostDevice" as the matching service (starting with El Capitan), we need to walk up the IOService plane to look for parents. You can manually walk up the IOService plane by executing "ioreg -p IOService -l -w 0 -x | less" and looking for your device. Notice that the parent device is always a parent in the tree, but it's not always the _immediate_ parent of the device. --- libusb/os/darwin_usb.c | 26 +++++++++++++++++++------- libusb/version_nano.h | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 68ed9b5..739644e 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -875,14 +875,29 @@ static int get_device_port (io_service_t service, UInt8 *port) { return ret; } +static int get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) { + kern_return_t result; + io_service_t parent; + + /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */ + parent = service; + while((result = IORegistryEntryGetParentEntry (parent, kIOServicePlane, &parent)) == kIOReturnSuccess) { + if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) { + /* Success */ + return 1; + } + } + + /* We ran out of parents */ + return 0; +} + static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out) { struct darwin_cached_device *new_device; UInt64 sessionID = 0, parent_sessionID = 0; int ret = LIBUSB_SUCCESS; usb_device_t **device; - io_service_t parent; - kern_return_t result; UInt8 port = 0; /* get some info from the io registry */ @@ -893,11 +908,8 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); - result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent); - - if (kIOReturnSuccess == result) { - (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID); - IOObjectRelease(parent); + if (get_device_parent_sessionID(service, &parent_sessionID)) { + usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID); } usbi_mutex_lock(&darwin_cached_devices_lock); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0c1b1c3..723c6c5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11193 +#define LIBUSB_NANO 11194 -- 2.7.4