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

refactor(serial): replace rusb with nusb #180

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

oopsbagel
Copy link
Contributor

@oopsbagel oopsbagel commented Mar 20, 2025

Description

nusb is a pure Rust library providing the same low level access to USB devices as rusb/libusb.

This branch removes rusb (and thus the dependence on libusb) and replaces it with nusb in the serial utility.

Notes

Addresses #176

nusb is a pure Rust library providing the same low level access to USB devices
that rusb/libusb provide.

This commit removes rusb (and thus the dependence on libusb) and replaces it
with nusb in the serial utility.

The only functional change is that nusb does not support timeouts for bulk data
commands. nusb is async. This commit contains a naïve implementation that simply
blocks on bulk reads and writes in send_command().
if let Err(e) = handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) {

if let Some(interface) = open_device(0x05c6, 0xf626) {
let enable_command_mode = Control {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these could always be inlined

@oopsbagel
Copy link
Contributor Author

Probably the best call for implementing timeouts is to just use https://docs.rs/tokio/latest/tokio/time/fn.timeout.html

Runtime memory on the Orbic is the key constraint, not disk size, so there's probably no reason not to use a small part of tokio here. The linker won't be including ALL of tokio anyways. <-- note to myself to get out of that 90s headspace

@wgreenberg
Copy link
Collaborator

no objections at all to using tokio, and reminder that serial is run on the user's computer, not the orbic itself! so no need to shave cpu cycles :P

Replace futures_lite::future::block_on (which will block indefinitely) with
tokio::time::timeout to restore the original behaviour of this utility, where
communication over USB interface bulk endpoints times out after 1 second.
@oopsbagel
Copy link
Contributor Author

Mmm true that, more of that late night logic creeping in :)

I've tested this branch with the Orbic using the serial binary built with cd serial && cargo build --release on Linux/amd64. I've also compared what usbmon captures with Wireshark between this version and the main branch.

I haven't tried the binary on Linux/arm64 or macOS/arm64 but I can later.

tokio::time::timeout(timeout, interface.bulk_out(0x2, data.as_bytes().to_vec()))
.await
.expect("Timed out writing command")
.into_result()
Copy link
Contributor Author

@oopsbagel oopsbagel Mar 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's other ways to style this statement (the double expect isn't gorgeous, nor is tokio::time::timeout(timeout, ...), but I went for the most minimal changes instead of putting my design fingerprints all over everything.


if let Some(interface) = open_device(0x05c6, 0xf626) {
let enable_command_mode = Control {
control_type: ControlType::Vendor,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really appreciated how instead of just writing the bmRequestType as a magic integer like rusb, this library uses enums to make the intent clearer.

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