ruabmbua / hidapi-rs

Rust bindings for the hidapi C library
MIT License
172 stars 81 forks source link

Async interface #51

Open NickeZ opened 4 years ago

NickeZ commented 4 years ago

I made an async interface to this crate. However, since there is no way to register to become awakened when there is data to read I have to create a thread and do blocking reads.

Reading through libhidapi (the C library) I realised that the libusb interface actually is asynchronous and that libhidapi conveniently (unfortunately) wraps away that using an internal thread. So the result feels incredible clunky with two threads and multiple mutexes / synchronization primitives.

I think the best approach actually is to skip hidapi and rewrite using the platform specific bindings from scratch. But before I start such a big effort I wanted to check in here if anyone else already is working on it.

Thanks

ruabmbua commented 4 years ago

Hi @NickeZ .

I was already working on a raw rust backend for this crate, which would skip hidapi (the C library), and use the os interfaces directly.

At the time I did this, I also wanted to add async support, but the rust async story was not really stable. I decided to wait, until async ecosystem / language integration catches up. I have not looked into async / await since then, but from what I heard, it might be ready

Regarding libusb, I do not plan on using it at all. All somewhat modern Linux systems should have the hidraw kernel interface.

I might be able to spend some time on this starting next week, but I have some other hobby projects going on.

https://github.com/ruabmbua/hidapi-rs/projects/1

ruabmbua commented 4 years ago

If you have any pointers, if I should try it with the tokio ecosystem, or async-std, please tell me. Maybe it`s possible to be runtime independent by just using mio, std::future and std::task?

NickeZ commented 4 years ago

I haven't looked close enough to know exactly what crates are needed, but I think you shouldn't need tokio. I think technically it should be enough with std::future, std::task and AsyncRead/Write from futures. However it would be great if we could reuse some platform specific code from mio to avoid reimplementing it. But it sounds to me like that depends on how usb works on the different platforms.

One caveat is that we may have to implement AsyncRead/Write from tokio as well to support that ecosystem. Currently it is in a bit of flux how the final std traits will look.

lnicola commented 4 years ago

Tokio will migrate to the version of the async traits that gets standardized, but until then it would be nice to support both, if possible.

NickeZ commented 4 years ago

So the plan would be to wrap these interfaces?

brokenthorn commented 4 years ago

So the plan would be to wrap these interfaces?

  • Windows (using hid.dll)
  • Linux (using the Kernel's hidraw driver)
  • Mac (using IOHidManager)

For Windows, there's winapi-rs which provides raw FFI bindings to all of Windows API.

Yamakaky commented 4 years ago

In the mean time, I think we could use https://docs.rs/smol as a hidapi async wrapper. The only thing we would need would be to make HidDevice AsRawFd (on linux at least). For testing, we can get the fd by casting the device handle as it is the first member (https://github.com/libusb/hidapi/blob/master/linux/hid.c#L65). A more robust solution would be to patch hidapi with a method returning the device specific fd.

brokenthorn commented 4 years ago

What about rust/winrt? Does it supersede this crate?

lnicola commented 4 years ago

@brokenthorn WinRT might have some USB functions, but it doesn't deprecate this crate which is portable across Windows, Linux and MacOS.

ruabmbua commented 4 years ago

Don`t forget BSD :P

timfish commented 2 years ago

Just dropping in here to mention that it looks like the winapi crate has effectively been superseded by the official Microsoft windows crate!

darkdragon-001 commented 2 years ago

Any news on async hidraw on Linux?

NickeZ commented 2 years ago

Nope sorry, I don't work with usb hardware right now so I'm not looking into it anymore.

brokenthorn commented 2 years ago

What about rust/winrt? Does it supersede this crate?

That crate has now been deprecated in favor of the windows crate which is wider reaching and might now expose more of the Windows APIs.

mcuee commented 1 year ago

Don`t forget BSD :P

It is interesting to see such efforts to bypass hidapi. :-)

In the case of FreeBSD, take note there is the new hidraw (similar to hidraw under Linux) for newer version of FreeBSD.

Reference: the following hidraw feature has been merged. https://reviews.freebsd.org/D27992

Another reference: https://github.com/Yubico/libfido2/blob/main/src/hid_freebsd.c

zardini123 commented 7 months ago

I came across this thread as I am also interested in async HID in Rust. Doing a search, I found someone created a async HID crate using platform-native bindings called async-hid. The library seems rather unknown (73 downloads all time), and entire commit history is 3 months (July 8th, 2023 to Oct 12, 2023). With that, I have no idea the state of support for the project.

Has anyone here given that project a shot?