manuelbl / JavaDoesUSB

USB library for Java
MIT License
136 stars 10 forks source link

macOS: implement kernel driver detach #12

Closed sirthias closed 1 year ago

sirthias commented 1 year ago

I'm trying to use JavaDoesUSB to connect to an IT8951 controlling a Waveshare ePaper Display. In the end the application will run on Linux but it'd be great for faster dev turn-around if things also ran directly on my development Macbook.

While JavaDoesUSB appears to work in principle it suffers from the same issues that libusb suffers from, namely macOS hogging the device's USB interface with its own kernel drivers. There are countless discussions around this problem in the libusb tickets, but a key component to get it to work is this PR: https://github.com/libusb/libusb/pull/911 which add support for macOS's "kernel driver detach" feature.

I'd assume that JavaDoesUSB is pretty much useless for all but the most obscure USB devices under macOS, until this feature is also implemented. I can't really tell how hard it would be to "port" this patch from libusb to JavaDoesUSB. What's your take, Manuel?

manuelbl commented 1 year ago

JavaDoesUSB is indeed mainly targeted at devices with a custom protocol. But it can also work with some USB devices with standard classes, e.g. configuring webcams implementing the UVC standard.

Most standard classes are well-supported by the operating system with dedicated API:

Having said that, it would still be beneficial if USB devices implementing standard USB classes could be accessed as well. It works for Linux. I'm interested to implement it for macOS as well – if it's possible. From what I understand currently, it requires entitlements. And I don't know how one can add entitlements to a Java application... I'll investigate it further.

You mentioned the IT8951 and a Waveshare ePaper display. What USB protocol does the IT8951 use? Serial communication over USB?

sirthias commented 1 year ago

Entitlements are one way, another is to simply run as root, which would be no issue for my use case.

It works for Linux.

I also have issues from Linux, unfortunately, and might open another ticket for these later. The IT8951 implements SCSI over USB and emulates a mass storage device, which macOS is especially picky about allowing low-level access from user space. :-/

sirthias commented 1 year ago

Update: I just tried talking to the IT8951 from a libusb-based rust example (https://github.com/faassen/rust-it8951) on macOS, and this works fine if I run it as root. That example does rely on device_handle.set_auto_detach_kernel_driver(true), i.e. the libusb feature implemented with the patch I linked to in the ticket description above.

So it seems that a transcription of the the patch would indeed help.

manuelbl commented 1 year ago

Thanks for the information. I'll look into it.

manuelbl commented 1 year ago

The main branch has a new feature for macOS: detachStandardDrivers() and attachStandardDrivers() can be used to gain access to USB devices that have been claimed by the operating system. They only have an effect if they are run as root.

On Linux, these functions must now also be called to get access to USB devices claimed by the OS. However, no special privileges are needed.

A new example projects implements drawing to an e-paper/e-ink display with an IT8951 driver and shows the use of detachStandardDrivers() and attachStandardDrivers(). It depends on version 0.5.1, which has not been released yet. So to build it, first create version 0.5.1 locally:

cd java-does-usb
mvn clean install
sirthias commented 1 year ago

Awesome, you're the man, Manual! :) I'll give your additions a spin ASAP...

sirthias commented 1 year ago

A quick update: The new stuff runs exactly as you promised! Thank you so much, Manuel! This was unexpectedly quick and I am now faced with two possible ways forward, "Rust + libusb" or "Scala + JavaDoesUSB", which is awesome!

Is there a chance, that you could package the current main branch into a release, so we can close this ticket?

manuelbl commented 1 year ago

I will officially release it later this week.

manuelbl commented 1 year ago

Version 0.5.1 has been published on Maven Central.