Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pigdef/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ std = ["serde/std"]
serde = { version = "1.0.228", default-features = false, features = ["derive"] }

# Optional Dependencies for "no_std" case
heapless = { version = "0.9.1", default-features = false, features = ["serde", "defmt"], optional = true }
heapless = { version = "0.9.2", default-features = false, features = ["serde", "defmt"], optional = true }
embassy-time = { version = "0.5.0", default-features = false, features = ["defmt", "defmt-timestamp-uptime"], optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion pignet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async-std = "1.13.2"

iroh = { version = "0.95.1", default-features = false, optional = true }
tokio = { version = "1.48.0", default-features = false, features = ["time"], optional = true }
nusb = { version = "0.1.14", default-features = false, optional = true }
nusb = { version = "0.2.1", default-features = false, optional = true }
serde = { version = "1.0.228", default-features = false, features = ["derive"], optional = true }
rand = { version = "0.9.2", default-features = false, features = ["std", "std_rng"], optional = true }
rand_core = { version = "0.6.4", optional = true }
51 changes: 32 additions & 19 deletions pignet/src/usb_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ use crate::discovery::DiscoveryMethod::USBRaw;
#[cfg(all(feature = "usb", feature = "discovery"))]
use crate::HardwareConnection;
use anyhow::{anyhow, Error};
use nusb::transfer::{ControlIn, ControlOut, ControlType, Recipient, RequestBuffer};
use nusb::transfer::Buffer;
use nusb::transfer::In;
use nusb::transfer::Interrupt;
use nusb::transfer::{ControlIn, ControlOut, ControlType, Recipient};
use nusb::Interface;
use nusb::MaybeFuture;
use pigdef::config::HardwareConfigMessage::Disconnect;
use pigdef::config::{HardwareConfig, HardwareConfigMessage};
#[cfg(feature = "discovery")]
Expand All @@ -30,6 +34,9 @@ use std::collections::HashMap;
use std::net::IpAddr;
use std::time::Duration;

const CONTROL_IN_TIMEOUT: Duration = Duration::from_secs(10);
const CONTROL_OUT_TIMEOUT: Duration = Duration::from_secs(10);

/// [ControlIn] "command" to request the [HardwareDescription]
const GET_HARDWARE_DESCRIPTION: ControlIn = ControlIn {
control_type: ControlType::Vendor,
Expand Down Expand Up @@ -77,9 +84,8 @@ async fn receive_control_in<T>(porky: &Interface, control_in: ControlIn) -> Resu
where
T: for<'a> Deserialize<'a>,
{
let response = porky.control_in(control_in).await;
response.status?;
let data = response.data;
let response = porky.control_in(control_in, CONTROL_IN_TIMEOUT).await;
let data = response?;
let length = data.len();
Ok(postcard::from_bytes(&data[0..length])?)
}
Expand Down Expand Up @@ -115,20 +121,21 @@ pub async fn get_wifi_details(porky: &Interface) -> Result<WiFiDetails, Error> {

/// Generic request to send data to device over USB [ControlOut]
async fn send_control_out(porky: &Interface, control_out: ControlOut<'_>) -> Result<(), Error> {
Ok(porky.control_out(control_out).await.status?)
Ok(porky.control_out(control_out, CONTROL_OUT_TIMEOUT).await?)
}

/// Get the [Interface] of a specific USB device using its [SerialNumber]
/// NOTE: The `target_serial` could be a partial serial number, to make life easier
async fn interface_from_serial(target_serial: &SerialNumber) -> Result<Interface, Error> {
for device_info in
nusb::list_devices()?.filter(|d| d.vendor_id() == 0xbabe && d.product_id() == 0xface)
for device_info in nusb::list_devices()
.wait()?
.filter(|d| d.vendor_id() == 0xbabe && d.product_id() == 0xface)
{
if let Some(serial_number) = device_info.serial_number() {
if serial_number.contains(target_serial) {
let device = device_info.open()?;
let interface = device.claim_interface(0)?;
interface.set_alt_setting(1)?;
let device = device_info.open().wait()?;
let interface = device.claim_interface(0).wait()?;
interface.set_alt_setting(1).wait()?;
return Ok(interface);
}
}
Expand Down Expand Up @@ -174,11 +181,16 @@ pub async fn wait_for_remote_message<T>(porky: &UsbConnection) -> Result<T, Erro
where
T: DeserializeOwned,
{
// Ideally create this once on initialization, so maybe lift it out of a loop,
// or keep it in a field of `porky`. It's not too expensive to create every time if
// necessary, but only one instance can exist at a time for a given endpoint address.
let mut endpoint = porky.interface.endpoint::<Interrupt, In>(0x81)?;

loop {
let buf = RequestBuffer::new(1024);
let bytes = porky.interface.interrupt_in(0x81, buf).await;
if bytes.status.is_ok() {
let msg = postcard::from_bytes(&bytes.data)?;
endpoint.submit(Buffer::new(1024));
let completion = endpoint.next_complete().await;
if completion.status.is_ok() {
let msg = postcard::from_bytes(&completion.buffer)?;
return Ok(msg);
}
tokio::time::sleep(Duration::from_secs(1)).await;
Expand Down Expand Up @@ -227,7 +239,8 @@ pub async fn connect(
/// Return a Vec of the [SerialNumber] of all compatible connected devices
#[cfg(all(feature = "usb", feature = "discovery"))]
pub async fn get_serials() -> Result<Vec<SerialNumber>, Error> {
Ok(nusb::list_devices()?
Ok(nusb::list_devices()
.wait()?
.filter(|d| d.vendor_id() == 0xbabe && d.product_id() == 0xface)
.filter_map(|device_info| {
device_info
Expand All @@ -242,17 +255,17 @@ pub async fn get_serials() -> Result<Vec<SerialNumber>, Error> {
pub async fn get_details(
serial_numbers: &[SerialNumber],
) -> Result<HashMap<SerialNumber, DiscoveredDevice>, Error> {
let device_list = nusb::list_devices()?;
let device_list = nusb::list_devices().wait()?;
let mut devices = HashMap::<SerialNumber, DiscoveredDevice>::new();

for device_info in device_list.filter(|d| d.vendor_id() == 0xbabe && d.product_id() == 0xface) {
let serial_number = device_info
.serial_number()
.ok_or(anyhow!("Could not get device serial_number"))?;
if serial_numbers.contains(&serial_number.to_string()) {
let device = device_info.open()?;
let interface = device.claim_interface(0)?;
interface.set_alt_setting(1)?;
let device = device_info.open().wait()?;
let interface = device.claim_interface(0).wait()?;
interface.set_alt_setting(1).wait()?;
let hardware_details = get_hardware_details(&interface).await?;

let wifi_details = if hardware_details.wifi {
Expand Down
10 changes: 5 additions & 5 deletions porky/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion porky/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ faster-hex = { version = "0.10.0", default-features = false }

serde = { version = "1.0.208", default-features = false, features = ["derive"] }
postcard = { version = "1.0.10", default-features = false, features = ["heapless"] }
heapless = { version = "0.9.1", default-features = false, features = ["serde", "defmt"] }
heapless = { version = "0.9.2", default-features = false, features = ["serde", "defmt"] }

edge-mdns = { version = "0.5.0", default-features = false, optional = true, features = ["io"] } #TODO check out "embassy" https://github.com/ivmarkov/edge-net/issues/63
edge-nal-embassy = { version = "0.5.0", default-features = false, optional = true }
Expand Down