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

Port capture backend from rusb to nusb #89

Merged
merged 6 commits into from
May 14, 2024
Merged

Conversation

martinling
Copy link
Member

This PR rewrites the capture backend to use nusb instead of rusb.

Using nusb has the following advantages for us over rusb:

  • Eliminates a layer of indirection and a dependency on the libusb C library: nusb uses OS APIs directly.
  • Has an API that supports queuing multiple bulk transfers on one endpoint, maximising capture throughput.
  • Seems more likely to gain hotplug and RAW_IO support on Windows, both of which are long-stalled in libusb.

This PR includes the first usage of async in Packetry. I have tried to bring in a minimum of baggage with this:

The latter two crates are already in our dependency tree as they are used by the gio and glib crates.

Tested on Linux with Cynthion r1.4.

@martinling martinling force-pushed the nusb branch 2 times, most recently from c18ed05 to b287158 Compare February 8, 2024 00:24
@miek miek self-assigned this Feb 26, 2024
@miek
Copy link
Member

miek commented Feb 26, 2024

I just tried this out and I find it gets out of sync on capture start quite often, and gets stuck displaying malformed packets.

Currently, if errors occur during capture, the capture thread sends them
to the decoder thread, via the same channel used for packets.

This allows errors to be caught in the decoder thread and shown
immediately to the user, even when the the stop button has not yet been
pressed, and therefore the capture thread not yet joined.

This is unnecessarily complicated though, and can currently lead to some
errors being shown twice (where both sent to the decoder thread and
returned in the capture thread), or not being shown (where returned in
the capture thread, but not sent to the decoder thread).

Instead, let's just pass a handler function to LunaHandle::start(),
which will be called by the capture thread as it ends. If an error
occured, it is then signalled to the user immediately, without the
decoder thread needing to be involved.

When joining the capture thread, it is still necessary to check if the
thread panicked, but any normal error will already have been handled.

We can use the existing display_error() function, which already takes
care of accessing the UI from whichever thread it is called from.
Rather than the capture thread sending individual packets to the decoder
thread, send the contents of entire USB transfers, and do the work of
picking out individual packets in the decoder thread.
We need to end up with a new Vec for each transfer anyway, in order to
send it to the decoder thread. But we can save a copy by capturing
directly into that new Vec, rather than copying from an existing buffer.
@martinling
Copy link
Member Author

@miek I think I've fixed the issues with this now.

@miek miek merged commit fcf553a into greatscottgadgets:main May 14, 2024
6 checks passed
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 this pull request may close these issues.

2 participants