Add serial subcommand to installer

This commit is contained in:
Sashanoraa
2025-04-26 20:57:51 -04:00
committed by Cooper Quintin
parent bbcf23899e
commit 60015e0ff6
2 changed files with 50 additions and 6 deletions
+42 -1
View File
@@ -1,4 +1,4 @@
use anyhow::{Context, Error};
use anyhow::{Context, Error, bail};
use clap::{Parser, Subcommand};
mod orbic;
@@ -20,6 +20,8 @@ enum Command {
Orbic(InstallOrbic),
/// Install rayhunter on the TP-Link M7350.
Tplink(InstallTpLink),
/// Developer utilities.
Util(Util),
}
#[derive(Parser, Debug)]
@@ -37,12 +39,51 @@ struct InstallTpLink {
#[derive(Parser, Debug)]
struct InstallOrbic {}
#[derive(Parser, Debug)]
struct Util {
#[command(subcommand)]
command: UntilSubCommand,
}
#[derive(Subcommand, Debug)]
enum UntilSubCommand {
/// Send a serial command to the Orbic.
Serial(Serial),
}
#[derive(Parser, Debug)]
struct Serial {
#[arg(long)]
root: bool,
command: Vec<String>,
}
async fn run_function() -> Result<(), Error> {
let Args { command } = Args::parse();
match command {
Command::Tplink(tplink) => tplink::main_tplink(tplink).await.context("Failed to install rayhunter on the TP-Link M7350. Make sure your computer is connected to the hotspot using USB tethering or WiFi. Currently only Hardware Revision v3 is supported.")?,
Command::Orbic(_) => orbic::install().await.context("Failed to install rayhunter on the Orbic RC400L")?,
Command::Util(subcommand) => match subcommand.command {
UntilSubCommand::Serial(serial_cmd) => {
if serial_cmd.root {
if !serial_cmd.command.is_empty() {
eprintln!("You cannot use --root and specify a command at the same time");
std::process::exit(64);
}
orbic::enable_command_mode()?;
} else if serial_cmd.command.is_empty() {
eprintln!("Command cannot be an empty string");
std::process::exit(64);
} else {
let cmd = serial_cmd.command.join(" ");
match orbic::open_orbic()? {
Some(interface) => orbic::send_serial_cmd(&interface, &cmd).await?,
None => bail!(orbic::ORBIC_NOT_FOUND),
}
}
}
}
}
Ok(())
+8 -5
View File
@@ -13,7 +13,7 @@ use tokio_stream::StreamExt;
use crate::{CONFIG_TOML, RAYHUNTER_DAEMON_INIT};
const ORBIC_NOT_FOUND: &str = r#"No Orbic device found.
pub const ORBIC_NOT_FOUND: &str = r#"No Orbic device found.
Make sure your device is plugged in and turned on.
If you're sure you've plugged in an Orbic device via USB, there may be a bug in
@@ -303,13 +303,16 @@ async fn wait_for_usb_device(vendor_id: u16, product_id: u16) -> Result<()> {
}
}
async fn at_syscmd(interface: &Interface, command: &str) -> Result<()> {
send_serial_cmd(interface, &format!("AT+SYSCMD={command}")).await
}
/// Sends an AT command to the usb device over the serial port
///
/// First establish a USB handle and context by calling `open_orbic(<T>)
async fn at_syscmd(interface: &Interface, command: &str) -> Result<()> {
pub async fn send_serial_cmd(interface: &Interface, command: &str) -> Result<()> {
let mut data = String::new();
data.push_str("\r\n");
data.push_str(&format!("AT+SYSCMD={command}"));
data.push_str(command);
data.push_str("\r\n");
let timeout = Duration::from_secs(2);
@@ -362,7 +365,7 @@ async fn at_syscmd(interface: &Interface, command: &str) -> Result<()> {
/// Send a command to switch the device into generic mode, exposing serial
///
/// If the device reboots while the command is still executing you may get a pipe error here, not sure what to do about this race condition.
fn enable_command_mode() -> Result<()> {
pub fn enable_command_mode() -> Result<()> {
if open_orbic()?.is_some() {
println!("Device already in command mode. Doing nothing...");
return Ok(());
@@ -396,7 +399,7 @@ fn enable_command_mode() -> Result<()> {
}
/// Get an Interface for the orbic device
fn open_orbic() -> Result<Option<Interface>> {
pub fn open_orbic() -> Result<Option<Interface>> {
// Device after initial mode switch
if let Some(device) = open_usb_device(VENDOR_ID, PRODUCT_ID)? {
let interface = device