Skip to content

Commit

Permalink
os/darwin: switch from using ResetDevice to USBDeviceReEnumerate
Browse files Browse the repository at this point in the history
In newer versions of macOS the ResetDevice function does nothing. For
these systems we have to use USBDeviceReEnumerate. This should also
work for older versions os MacOS X.

Fixes #455

Signed-off-by: Nathan Hjelm <hjelmn@lanl.gov>
  • Loading branch information
hjelmn committed Jul 26, 2018
1 parent 5912d56 commit c14ab5f
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
7 changes: 4 additions & 3 deletions libusb/os/darwin_usb.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* -*- Mode: C; indent-tabs-mode:nil -*- */
/*
* darwin backend for libusb 1.0
* Copyright © 2008-2017 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright © 2008-2018 Nathan Hjelm <hjelmn@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -1498,9 +1498,10 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
IOReturn kresult;
int i;

kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
/* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
if (kresult) {
usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult));
usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
return darwin_to_libusb (kresult);
}

Expand Down
2 changes: 1 addition & 1 deletion libusb/version_nano.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define LIBUSB_NANO 11314
#define LIBUSB_NANO 11315

5 comments on commit c14ab5f

@rob-the-dude
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using libusb with BTStack, and I noticed that the use of "USBDeviceReEnumerate" seems to violate it's expectation of what "reset device" does. They typically open and then reset the device, which I assume works on other platforms (I'm going to try NetBSD and Linux, but haven't yet). But on Mac OS X, the "reset device" call (which now calls "USBDeviceReEnumerate" seems to always result in the IO kit device being invalidated (and according to Apple's docs, that's to be expected). The calls to load the descriptor ignore the return value, but for me, that value is always an error that indicates the device has been closed (again, consistent with Apple's docs).

I tried to modify the call a little bit to close and re-open the device, but that didn't work -- the close "worked" (internally, it cleaned up the libusb data structures, although it got an error back from the OS that the device was not open). But the second "open" failed, and it appeared to fail because the old device information was incorrect. I'm guessing that when it was virtually detached and re-attached (as re-enumerate claims to do), it ended up with some different parameters that libusb needs to process, and since I'm inside a call to "reset device", it hasn't had a chance to do that yet. I didn't try to track it down further yet.

@hjelmn
Copy link
Member Author

@hjelmn hjelmn commented on c14ab5f Mar 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. BTStack developer's must have not read the documentation for libusb_reset_device:

Perform a USB port reset to reinitialize a device. The system will attempt
to restore the previous configuration and alternate settings after the
reset has completed.

If the reset fails, the descriptors change, or the previous state cannot be
restored, the device will appear to be disconnected and reconnected. This
means that the device handle is no longer valid (you should close it) and
rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates
when this is the case.

So, they MUST close and re-open the device. From what I can tell they should still be able to use the libusb_device. Let me read through the documentation. If the libusb_device must remain valid then I can update the backend to re-use the libusb_device after reset/re-enumeration.

@hjelmn
Copy link
Member Author

@hjelmn hjelmn commented on c14ab5f Mar 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, or maybe I am reading that wrong. Maybe the handle should also remain valid. That would require me to update reset to wait until the handle is valid again. Not a big deal but need to make sure the API is followed.

@hjelmn
Copy link
Member Author

@hjelmn hjelmn commented on c14ab5f Mar 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, definitely need to return LIBUSB_ERROR_NOT_FOUND at a minimum. Because it is essentially a re-plug now.

@hjelmn
Copy link
Member Author

@hjelmn hjelmn commented on c14ab5f Mar 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it is already returning the correct value in the backend. Is BTStack getting LIBUSB_ERROR_NOT_FOUND?

Please sign in to comment.