Skip to content

feat: expose custom transport API via from_transport()#126

Merged
benma merged 2 commits into
BitBoxSwiss:masterfrom
frijolo:custom-transport
Jul 18, 2026
Merged

feat: expose custom transport API via from_transport()#126
benma merged 2 commits into
BitBoxSwiss:masterfrom
frijolo:custom-transport

Conversation

@frijolo

@frijolo frijolo commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a public BitBox::from_transport() constructor that accepts any communication::ReadWrite implementation and performs the U2F-HID framing internally. This lets callers delegate raw USB I/O to platform-specific code, instead of relying on hidapi.

Two small changes:

  • Make the communication module public, exposing the ReadWrite trait and Error.
  • Remove the feature gate on FIRMWARE_CMD so from_transport (available without the usb/wasm/simulator features) can perform the framing.

Motivation

We want to drive a BitBox02 from Android, where USB access must go through the Java UsbManager API and hidapi is not available. The existing constructors (from_hid_device, usb::get_any_bitbox02) all assume hidapi, so there is currently no way to connect on such platforms.

With from_transport(), a caller implements only the ReadWrite trait over their platform's transport (on Android, a channel bridged to the Java USB stack) and gets a fully functional BitBox — the U2F-HID framing is handled by the library, exactly as it is for the USB path. Desktop/hidapi callers are unaffected.

This mirrors how the official BitBoxApp already drives the device on Android: its GoViewModel.java opens the device through UsbManager/UsbDeviceConnection, performs the bulkTransfer() I/O in Java, and hands a ReadWriteCloser to the Go backend (no hidapi on Android). from_transport() is simply the Rust/bitbox-api equivalent of that pattern.

What changed

  • src/lib.rs: new pub async fn from_transport(transport: Box<dyn communication::ReadWrite>, noise_config: Box<dyn NoiseConfig>) -> Result<BitBox<R>, Error>; mod communicationpub mod communication.
  • src/communication.rs: FIRMWARE_CMD is no longer gated behind usb/wasm/simulator, since from_transport needs it without those features.

No existing API changes; this is purely additive.

Testing

  • Builds with and without the usb feature.
  • Downstream: an Android app connects to and signs with a physical BitBox02 through a channel-based ReadWrite transport built on from_transport() — pairing, xpub export, wallet/policy registration, and PSBT signing (singlesig + multisig) all verified on-device.

@frijolo frijolo closed this Jul 10, 2026
@frijolo frijolo reopened this Jul 14, 2026
@frijolo
frijolo force-pushed the custom-transport branch from 5ddf6ee to f2f9922 Compare July 14, 2026 09:25
Comment thread src/lib.rs Outdated
Comment on lines 118 to 122

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could reuse Self::from_transport here and in from_simulator below

Comment thread src/lib.rs Outdated

mod antiklepto;
mod communication;
pub mod communication;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about pub use comminucation::ReadWrite instead, to keep the public API surface smaller?

@frijolo

frijolo commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Applied both suggestions:

  • from_hid_device/from_simulator now reuse from_transport() internally.
  • communication module stays private; re-exporting ReadWrite (and Error,
    which its methods return) from the crate root instead.

Built and verified successfully in our downstream app on both desktop
(Linux) and Android — the latter being what exercises from_transport(),
the core of this PR. Full on-device BitBox02 validation is still
pending on my end (no physical hardware until next week); will follow
up once that's done.

frijolo and others added 2 commits July 18, 2026 03:29
Add a public BitBox::from_transport() that accepts any communication::ReadWrite
implementation and performs the U2F-HID framing internally. This lets callers
delegate raw USB I/O to platform-specific code (e.g. Android, where USB access
requires Java APIs unavailable to hidapi) by implementing only the ReadWrite
trait over their transport.

- Make the communication module public to expose the ReadWrite trait and Error.
- Remove the feature gate on FIRMWARE_CMD so from_transport (available without
  the usb/wasm/simulator features) can perform the framing.
@benma
benma force-pushed the custom-transport branch from bced586 to 7ce956c Compare July 18, 2026 01:32
@benma
benma merged commit eea4d23 into BitBoxSwiss:master Jul 18, 2026
3 checks passed
@benma

benma commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Applied both suggestions:

* from_hid_device/from_simulator now reuse from_transport() internally.

* communication module stays private; re-exporting ReadWrite (and Error,
  which its methods return) from the crate root instead.

Built and verified successfully in our downstream app on both desktop (Linux) and Android — the latter being what exercises from_transport(), the core of this PR. Full on-device BitBox02 validation is still pending on my end (no physical hardware until next week); will follow up once that's done.

@frijolo I squashed your two commits, added a version-bump commit and published this change as v0.13.0.

@frijolo

frijolo commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review and for cutting the release!

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