Skip to content
Permalink
Browse files

darwin: Retry IOCreatePlugInInterfaceForService on failure

We have a case where a device might not be detected by libusb if we plug
it after initializing the library. We were able to reproduce this issue
pretty consistently on a Mac Mini and several MacBook Pros running very
recent macOS versions (Mojave) using the Balena Fin board
(https://www.balena.io/fin/). I don't know if this happens with other
USB devices.

Enabling debug output revealed the following:

```
[ 7.901582] [00004f07] libusb: debug [darwin_get_cached_device] finding cached device for sessionID 0x2a9b5279f04
[ 7.901764] [00004f07] libusb: debug [darwin_get_cached_device] matching sessionID 0x2a9b5279f04 against cached device with sessionID 0x17dbd029b6a
[ 7.901798] [00004f07] libusb: debug [darwin_get_cached_device] matching sessionID 0x2a9b5279f04 against cached device with sessionID 0x1688763269f
[ 7.901818] [00004f07] libusb: debug [darwin_get_cached_device] matching sessionID 0x2a9b5279f04 against cached device with sessionID 0x4c0aefaa
[ 7.901831] [00004f07] libusb: debug [darwin_get_cached_device] matching sessionID 0x2a9b5279f04 against cached device with sessionID 0x0
[ 7.901845] [00004f07] libusb: debug [darwin_get_cached_device] caching new device with sessionID 0x2a9b5279f04
[ 7.903377] [00004f07] libusb: debug [darwin_device_from_service] could not set up plugin for service: out of resources
[ 8.029152] [00000307] libusb: debug [libusb_get_device_list]
```

The "out of resources" error comes from
`IOCreatePlugInInterfaceForService` which will apparently return this
error if the `Start` method of the interface is not success (see
https://github.com/opensource-apple/IOKitUser/blob/b80a5cbc0ebfb5c4954ef6d757918db0e4dc4b7f/IOCFPlugIn.c#L232).

Retrying `IOCreatePlugInInterfaceForService` makes it work for me.

Closes #542

Signed-off-by: Juan Cruz Viotti <juan@balena.io>
Signed-off-by: Nathan Hjelm <hjelmn@me.com>
  • Loading branch information...
jviotti authored and hjelmn committed Mar 20, 2019
1 parent 7997e32 commit 0b381a81bed9051bfac7a4f5a16358182c7e7f9a
Showing with 18 additions and 4 deletions.
  1. +17 −3 libusb/os/darwin_usb.c
  2. +1 −1 libusb/version_nano.h
@@ -297,10 +297,24 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
usb_device_t **device;
IOReturn kresult;
SInt32 score;
const int max_retries = 5;

/* The IOCreatePlugInInterfaceForService function might consistently return
an "out of resources" error with certain USB devices the first time we run
it. The reason is still unclear, but retrying fixes the problem */
for (int count = 0; count < max_retries; count++) {
kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &plugInInterface,
&score);
if (kIOReturnSuccess == kresult && plugInInterface) {
break;
}

kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &plugInInterface,
&score);
usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));

/* sleep for a little while before trying again */
nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
}

if (kIOReturnSuccess != kresult || !plugInInterface) {
usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
@@ -1 +1 @@
#define LIBUSB_NANO 11361
#define LIBUSB_NANO 11362

0 comments on commit 0b381a8

Please sign in to comment.
You can’t perform that action at this time.