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

feat(hil): Add button control cmd and timeout for cmd #281

Merged
merged 2 commits into from
Nov 27, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions hil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ libftd2xx = { version = "0.32.4", features = ["static"] }
nusb.workspace = true
orb-build-info.path = "../build-info"
orb-security-utils = { workspace = true, features = ["reqwest"] }
humantime = "2.1.0"
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] }
secrecy.workspace = true
tempfile = "3"
Expand Down
6 changes: 3 additions & 3 deletions hil/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use crate::ftdi::{FtdiGpio, OutputState};
use color_eyre::{eyre::WrapErr as _, Result};
use tracing::info;

const BUTTON_PIN: crate::ftdi::Pin = FtdiGpio::CTS_PIN;
const RECOVERY_PIN: crate::ftdi::Pin = FtdiGpio::RTS_PIN;
const NVIDIA_VENDOR_ID: u16 = 0x0955;
pub const BUTTON_PIN: crate::ftdi::Pin = FtdiGpio::CTS_PIN;
pub const RECOVERY_PIN: crate::ftdi::Pin = FtdiGpio::RTS_PIN;
pub const NVIDIA_VENDOR_ID: u16 = 0x0955;

pub fn is_recovery_mode_detected() -> Result<bool> {
let num_nvidia_devices = nusb::list_devices()
Expand Down
43 changes: 43 additions & 0 deletions hil/src/commands/button_ctrl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use clap::Parser;
use color_eyre::{eyre::WrapErr as _, Result};
use humantime::parse_duration;
use std::time::Duration;
use tracing::info;

use crate::boot::BUTTON_PIN;
use crate::ftdi::{FtdiGpio, OutputState};

#[derive(Debug, Parser)]
pub struct ButtonCtrl {
///Button press duration (e.g., "1s", "500ms")
#[arg(long, default_value = "1s", value_parser = parse_duration)]
press_duration: Duration,
}

impl ButtonCtrl {
pub async fn run(self) -> Result<()> {
fn make_ftdi() -> Result<FtdiGpio> {
FtdiGpio::builder()
.with_default_device()
.and_then(|b| b.configure())
.wrap_err("failed to create ftdi device")
}

info!(
"Holding button for {} seconds",
self.press_duration.as_secs_f32()
);
tokio::task::spawn_blocking(move || -> Result<_, color_eyre::Report> {
let mut ftdi = make_ftdi()?;
ftdi.set_pin(BUTTON_PIN, OutputState::Low)?;
std::thread::sleep(self.press_duration);
ftdi.set_pin(BUTTON_PIN, OutputState::High)?;
Ok(ftdi)
})
.await
.wrap_err("task panicked")??;
info!("Button released");

Ok(())
}
}
21 changes: 16 additions & 5 deletions hil/src/commands/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use color_eyre::{
Result,
};
use futures::{TryStream, TryStreamExt as _};
use humantime::parse_duration;
use tokio::{
io::{AsyncRead, AsyncWrite, AsyncWriteExt as _},
sync::broadcast,
Expand All @@ -21,11 +22,19 @@ const PATTERN_START: &str = "hil_pattern_start-";
const PATTERN_END: &str = "-hil_pattern_end";

#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
pub struct Cmd {
/// Command to execute
#[arg()]
cmd: String,

/// Path to the serial device
#[arg(long, default_value = crate::serial::DEFAULT_SERIAL_PATH)]
serial_path: PathBuf,

/// Timeout duration (e.g., "10s", "500ms")
#[arg(long, default_value = "10s", value_parser = parse_duration)]
timeout: Duration,
}

impl Cmd {
Expand All @@ -40,7 +49,7 @@ impl Cmd {
})?;
let (serial_reader, serial_writer) = tokio::io::split(serial);

run_inner(serial_reader, serial_writer, self.cmd).await
run_inner(serial_reader, serial_writer, self.cmd, self.timeout).await
}
}

Expand All @@ -50,6 +59,7 @@ async fn run_inner(
serial_reader: impl AsyncRead + Send + 'static,
serial_writer: impl AsyncWrite,
cmd: String,
timeout: Duration,
) -> Result<()> {
let mut serial_writer = pin!(serial_writer);
let (serial_tx, serial_rx) = broadcast::channel(64);
Expand All @@ -60,13 +70,13 @@ async fn run_inner(
// Type newline to force a prompt (helps make sure we are in the state we
// think we are in)
type_str(&mut serial_writer, "\n").await?;
wait_for_str(&mut serial_stream, "worldcoin@id")
wait_for_str(&mut serial_stream, "worldcoin@id", timeout)
.await
.wrap_err("failed while listening for prompt after newline")?;

// Run cmd
type_str(&mut serial_writer, &format!("stty -echo; {}\n\n", cmd)).await?;
wait_for_str(&mut serial_stream, "worldcoin@id")
wait_for_str(&mut serial_stream, "worldcoin@id", timeout)
.await
.wrap_err("failed while listening for prompt after command")?;

Expand All @@ -91,7 +101,7 @@ async fn run_inner(
};

tokio::select! {
result = tokio::time::timeout(Duration::from_secs(10), tty_fut) => result.wrap_err("command timed out")?.wrap_err("error while executing command")?,
result = tokio::time::timeout(timeout, tty_fut) => result.wrap_err("command timed out")?.wrap_err("error while executing command")?,
result = reader_task => result.wrap_err("serial reader panicked")?.wrap_err("error in serial reader task")?,
}

Expand Down Expand Up @@ -147,12 +157,13 @@ async fn type_str(mut serial_writer: impl AsyncWrite + Unpin, s: &str) -> Result
async fn wait_for_str<E>(
serial_stream: impl TryStream<Ok = Bytes, Error = E>,
pattern: &str,
timeout: Duration,
) -> Result<()>
where
E: std::error::Error + Send + Sync + 'static,
{
tokio::time::timeout(
Duration::from_millis(10000),
timeout,
crate::serial::wait_for_pattern(pattern.as_bytes().to_vec(), serial_stream),
)
.await
Expand Down
2 changes: 2 additions & 0 deletions hil/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! The various top-level commands of the cli.

mod button_ctrl;
mod cmd;
mod flash;
mod login;
mod reboot;

pub use self::button_ctrl::ButtonCtrl;
pub use self::cmd::Cmd;
pub use self::flash::Flash;
pub use self::login::Login;
Expand Down
8 changes: 5 additions & 3 deletions hil/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ struct Cli {

#[derive(Debug, Subcommand)]
enum Commands {
ButtonCtrl(crate::commands::ButtonCtrl),
Cmd(crate::commands::Cmd),
Flash(crate::commands::Flash),
Reboot(crate::commands::Reboot),
Login(crate::commands::Login),
Cmd(crate::commands::Cmd),
Reboot(crate::commands::Reboot),
}

fn current_dir() -> Utf8PathBuf {
Expand Down Expand Up @@ -58,10 +59,11 @@ async fn main() -> Result<()> {
let args = Cli::parse();
let run_fut = async {
match args.commands {
Commands::ButtonCtrl(c) => c.run().await,
Commands::Cmd(c) => c.run().await,
Commands::Flash(c) => c.run().await,
Commands::Login(c) => c.run().await,
Commands::Reboot(c) => c.run().await,
Commands::Cmd(c) => c.run().await,
}
};
tokio::select! {
Expand Down