Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: implement device capture to force unload of KEXT drivers #906

Closed
mcuee opened this issue Apr 6, 2021 · 3 comments
Closed

macOS: implement device capture to force unload of KEXT drivers #906

mcuee opened this issue Apr 6, 2021 · 3 comments
Labels

Comments

@mcuee
Copy link
Member

mcuee commented Apr 6, 2021

Pull request https://github.com/libusb/libusb/pull/893 has been closed but the idea seems to be pretty interesting.

From the author osy:
It's a well known issue on macOS that you cannot use libusb to attach to an interface already claimed by an KEXT for exclusive access. The common workaround is to do sudo kextunload or inject a codeless KEXT. Both require admin permissions, and does not work for all devices on latest macOS. Additionally, SIP has to be disabled to inject a codeless KEXT, making it a pain to work with USB devices.

This patch uses the kUSBReEnumerateCaptureDeviceBit introduced back in macOS 10.10 which will tell the kernel to unload all other drivers for you without needing any dirty hacks.

Unfortunately, a side effect is that it will reset (simulate unplug-replug) the device to do this and so I didn't want to make it the default behaviour of libusb_open as that may, for example, cause all USB devices to be reset if the application decides to read the product string of every device attached. I can't find a good way to change this without touching the API specs, so I introduced a new option LIBUSB_OPTION_FORCE_CAPTURE_OPEN that lets you toggle the "capture" behaviour.

Also, the way libusb_close works makes it a bit awkward to implement the "release" of the captured device because just closing the handle does not tell the KEXTs to start matching again and calling USBDeviceReEnumerate with kUSBReEnumerateReleaseDeviceBit will also cause the device to be reset which then makes the next call of libusb_open fetch a stale cached object and fail. However, calling darwin_reset_device to address the stale cache issue will cause the device to be opened again, which causes another "capture" and then the OS will never get the device back. So the workaround of this is as follows:

  1. When darwin_close is called, if the device is captured, then darwin_reset_device will first be called.
  2. darwin_reset_device_capture will call USBDeviceReEnumerate and release the capture.
  3. darwin_restore_state calls darwin_open indicating that capture should NOT be used.
  4. darwin_open succeeds and the device is re-opened without the capture bit.
  5. Call returns to darwin_close who calls USBDeviceClose on the non-captured device handle.
@mcuee mcuee added the macOS label Apr 6, 2021
@mcuee mcuee changed the title macOS: implement device capture to force unload of KEXT drivers #893 macOS: implement device capture to force unload of KEXT drivers Apr 6, 2021
@mcuee
Copy link
Member Author

mcuee commented Apr 26, 2021

New pull request #911

@supercairos
Copy link

Looking forward to this feature.

@mcuee
Copy link
Member Author

mcuee commented Jun 5, 2021

Close this now that #911 has been merged.

@mcuee mcuee closed this as completed Jun 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants