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

Rust-native HackRf Driver #9

Closed
TroyNeubauer opened this issue Sep 2, 2024 · 4 comments · Fixed by #10
Closed

Rust-native HackRf Driver #9

TroyNeubauer opened this issue Sep 2, 2024 · 4 comments · Fixed by #10

Comments

@TroyNeubauer
Copy link
Contributor

Hi,
Thanks for your work on FutureSDR and seify!

Looking to contribute a rust based driver for the HackRF One, and wanted to make double check the approach.
I'm assuming following what the rtl sdr does would be reasonable?

So:

  1. Create new repo for the driver impl (which doesn't depend on seify)
  2. Add feature flag for hackrf one, pull in dependency if set
  3. Add relevant variants to seify::Error and seify::Driver (also feature gated)
  4. Implement DeviceTrait on a new struct which wraps the dependency's hackrf type
  5. Test
@bastibl
Copy link
Member

bastibl commented Sep 2, 2024

Yes, that sounds like the way to go.

I'm not sure, if you already implemented the driver. Just recently, I also thought about implementing more Rust drivers and found nusb, which does not depend on libusb and is, therefore, easier to cross-compile (and maybe more efficient). But the main advantage is that there is now also cross_usb, which is a small abstraction layer that compiles to native code with nusb and WebUSB. I did not try this yet, but with cross_usb a single driver would work for all native targets and the web. I think this would be absolutely awesome.

@TroyNeubauer
Copy link
Contributor Author

Yes I have the driver implemented using rusb. I took a look at those crates and they look great!
The trouble is that my usecase runs entierly on android, and it looks like nusb lacks android support.

I dug in to see how difficult it would be to add, and its basically the same as libusb_wrap_sys_device, but in Rust (i.e: obtain busnum and devnum from the file descriptor provided by the UsbManager API, then open the corresponding usbfs file, then the rest should work).

I have ported over wrap_sys_device's approach into rust, but currently I am stuck on an access denied error when reading the rust equivalent of this simlink: https://github.com/libusb/libusb/blob/467b6a8896daea3d104958bf0887312c5d14d150/libusb/os/linux_usbfs.c#L604-L605. Its unclear why this fails in Rust, maybe I missed some setup that libusb does?

It looks like theres some prior art in FutureSDR for android. Have you seen anything like this before?

In any case, I am very interested in solving this and using nusb to take advantage of their easy async API to maximize throughput without having to muck around with libusb's async transfer API. It looks like cross_usb doesn't support an async / Queue based API. I dont know the specifics of how usb stuff works on the browser, but I dont see a reason why they couldnt essentially wrap nusb's Queue, and provide a serial implementation for wasm, and the full async one on desktop. Assuming we could get this upstreamed, switching to cross_usb to add wasm support for hackrf would be trivial since the API's are very similar.

Anyway I'll keep cracking away at this and let you know what I can find.

@bastibl
Copy link
Member

bastibl commented Sep 11, 2024

Cool, great that you're looking into this topic!

I was experimenting with Android before libusb added Android support. So this is not the nice, recommended way to do it: I opened the USB device, using the Android UsbManager in Java/Kotlin domain and forwarded the path and file descriptor through environment variables to the Rust flowgraph:

https://github.com/FutureSDR/FutureSDR/blob/main/examples/android-hw/FutureSDR/app/src/main/java/net/bastibl/futuresdrhw/MainActivity.kt#L97-L115

https://github.com/FutureSDR/FutureSDR/blob/main/examples/android-hw/src/lib.rs#L73-L93

Some ideas about things that maybe required (it's some time that I looked into Android):

Regarding the APIs of nusb and cross_usb: with WebUSB everything is async, since there are no blocking calls in the browser. Usually, libusb-based drivers only provide a blocking interface. I don't think that any SDR driver uses the async API of libusb. So until now, there was no easy way to unify these domains, since sync and async APIs typically require different Rust traits. But since nusb provides an async API, this should be easier, and I think this is what cross_usb does. My understanding is that there are no queues but it's just the call to the bulk or control transfer that is async (and not a blocking function call):

https://docs.rs/cross_usb/latest/cross_usb/struct.Interface.html#impl-UsbInterface%3C'a%3E-for-Interface

@TroyNeubauer
Copy link
Contributor Author

Good to know, thanks!

I have this working on android with my some changes to nusb. In the fm-receiver example, the AudioSink just works out of the box an android!

Just opened a PR in nusb for the changes I needed to get this working: kevinmehall/nusb#80

Whats remaining on my plate before opening a PR to seify:

Hope to have these done in a few days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants