diff --git a/Cargo.toml b/Cargo.toml index 24eeb17..9bade20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT" name = "adb_client" readme = "README.md" repository = "https://github.com/cocool97/adb_client" -version = "0.4.0" +version = "0.4.1" [lib] name = "adb_client" diff --git a/README.md b/README.md index d138245..feceec1 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ connexion.devices(); This crate also provides a lightweight binary based on the `adb_client` crate. You can install it by running the following command : ```shell -cargo install adb_client +cargo install adb_client --example adb_cli ``` ## Missing features diff --git a/examples/adb_cli.rs b/examples/adb_cli.rs index 1ce5912..f25f763 100644 --- a/examples/adb_cli.rs +++ b/examples/adb_cli.rs @@ -1,7 +1,7 @@ use std::net::Ipv4Addr; +use adb_client::{AdbTcpConnexion, Device, RebootType, RustADBError}; use clap::Parser; -use adb_client::{AdbTcpConnexion, Device, RustADBError}; #[derive(Parser, Debug)] #[clap(about, version, author)] @@ -36,6 +36,32 @@ pub enum Command { HostFeatures, /// Run 'command' in a shell on the device, and return its output and error streams. Shell { command: Vec }, + /// Reboots the device + Reboot { + #[clap(subcommand)] + sub_command: RebootTypeCommand, + }, +} + +#[derive(Parser, Debug)] +pub enum RebootTypeCommand { + System, + Bootloader, + Recovery, + Sideload, + SideloadAutoReboot, +} + +impl From for RebootType { + fn from(value: RebootTypeCommand) -> Self { + match value { + RebootTypeCommand::System => RebootType::System, + RebootTypeCommand::Bootloader => RebootType::Bootloader, + RebootTypeCommand::Recovery => RebootType::Recovery, + RebootTypeCommand::Sideload => RebootType::Sideload, + RebootTypeCommand::SideloadAutoReboot => RebootType::SideloadAutoReboot, + } + } } fn main() -> Result<(), RustADBError> { @@ -86,6 +112,10 @@ fn main() -> Result<(), RustADBError> { println!("- {}", feature); } } + Command::Reboot { sub_command } => { + println!("Reboots device"); + connexion.reboot(opt.serial, sub_command.into())? + } } Ok(()) diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 6450c81..7c4007a 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,6 +1,7 @@ mod devices; mod host_features; mod kill; +mod reboot; mod shell; mod transport; mod version; diff --git a/src/commands/reboot.rs b/src/commands/reboot.rs new file mode 100644 index 0000000..1ad4727 --- /dev/null +++ b/src/commands/reboot.rs @@ -0,0 +1,19 @@ +use crate::{ + models::{AdbCommand, RebootType}, + AdbTcpConnexion, Result, +}; + +impl AdbTcpConnexion { + /// Reboots the device + pub fn reboot(&mut self, serial: Option, reboot_type: RebootType) -> Result<()> { + match serial { + None => Self::send_adb_request(&mut self.tcp_stream, AdbCommand::TransportAny)?, + Some(serial) => { + Self::send_adb_request(&mut self.tcp_stream, AdbCommand::TransportSerial(serial))? + } + } + + self.proxy_connexion(AdbCommand::Reboot(reboot_type), false) + .map(|_| ()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 634b997..7d9b930 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,4 +11,4 @@ mod error; mod models; pub use adb_tcp_connexion::AdbTcpConnexion; pub use error::{Result, RustADBError}; -pub use models::{AdbVersion, Device, DeviceLong, DeviceState}; +pub use models::{AdbVersion, Device, DeviceLong, DeviceState, RebootType}; diff --git a/src/models/adb_command.rs b/src/models/adb_command.rs index 04d0bd8..9889ac2 100644 --- a/src/models/adb_command.rs +++ b/src/models/adb_command.rs @@ -1,3 +1,5 @@ +use super::RebootType; + pub enum AdbCommand { Version, Kill, @@ -39,7 +41,8 @@ pub enum AdbCommand { // JDWP(u32), // TrackJDWP, // Sync, - // Reverse(String) + // Reverse(String), + Reboot(RebootType), } impl ToString for AdbCommand { @@ -51,16 +54,19 @@ impl ToString for AdbCommand { AdbCommand::DevicesLong => "host:devices-l".into(), AdbCommand::TrackDevices => "host:track-devices".into(), AdbCommand::TransportAny => "host:transport-any".into(), - AdbCommand::TransportSerial(serial) => format!("host:transport:{}", serial), + AdbCommand::TransportSerial(serial) => format!("host:transport:{serial}"), AdbCommand::ShellCommand(command) => match std::env::var("TERM") { - Ok(term) => format!("shell,TERM={},raw:{}", term, command), - Err(_) => format!("shell,raw:{}", command), + Ok(term) => format!("shell,TERM={term},raw:{command}"), + Err(_) => format!("shell,raw:{command}"), }, AdbCommand::Shell => match std::env::var("TERM") { - Ok(term) => format!("shell,TERM={},raw:", term), + Ok(term) => format!("shell,TERM={term},raw:"), Err(_) => "shell,raw:".into(), }, AdbCommand::HostFeatures => "host:features".into(), + AdbCommand::Reboot(reboot_type) => { + format!("reboot:{reboot_type}") + } } } } diff --git a/src/models/host_features.rs b/src/models/host_features.rs index dc4b057..85fc22d 100644 --- a/src/models/host_features.rs +++ b/src/models/host_features.rs @@ -22,7 +22,7 @@ impl TryFrom<&[u8]> for HostFeatures { match value { b"shell_v2" => Ok(Self::ShellV2), b"cmd" => Ok(Self::Cmd), - _ => Err(format!("Unknown value {:?}", value)), + _ => Err(format!("Unknown value {value:?}")), } } } diff --git a/src/models/mod.rs b/src/models/mod.rs index 43f02aa..c533f40 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -5,6 +5,7 @@ mod device; mod device_long; mod device_state; mod host_features; +mod reboot_type; pub use adb_command::AdbCommand; pub use adb_request_status::AdbRequestStatus; @@ -13,3 +14,4 @@ pub use device::Device; pub use device_long::DeviceLong; pub use device_state::DeviceState; pub use host_features::HostFeatures; +pub use reboot_type::RebootType; diff --git a/src/models/reboot_type.rs b/src/models/reboot_type.rs new file mode 100644 index 0000000..e340889 --- /dev/null +++ b/src/models/reboot_type.rs @@ -0,0 +1,28 @@ +use std::fmt::Display; + +#[derive(Debug)] +/// Type of reboot needed. +pub enum RebootType { + /// "Classic" device reboot + System, + /// Reboots to bootloader + Bootloader, + /// Reboots to recovery + Recovery, + /// Reboots into recovery and automatically starts sideload mode + Sideload, + /// Same as `Sideload` but reboots after sideloading + SideloadAutoReboot, +} + +impl Display for RebootType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RebootType::System => write!(f, ""), + RebootType::Bootloader => write!(f, "bootloader"), + RebootType::Recovery => write!(f, "recovery"), + RebootType::Sideload => write!(f, "sideload"), + RebootType::SideloadAutoReboot => write!(f, "sideload-auto-reboot"), + } + } +}