From db853ed67ae6f084d30068170e0cc6a71e4a0d80 Mon Sep 17 00:00:00 2001 From: Corentin LIAUD Date: Wed, 27 Aug 2025 21:00:11 +0200 Subject: [PATCH] breaking(feature): add usb feature --- adb_client/Cargo.toml | 8 ++++++-- adb_client/README.md | 17 +++++++++-------- adb_client/src/device/adb_transport_message.rs | 4 ---- adb_client/src/device/adb_usb_device.rs | 14 +++++--------- adb_client/src/device/mod.rs | 17 +++++++++++++---- adb_client/src/device/models/mod.rs | 4 ++++ adb_client/src/error.rs | 6 ++++++ adb_client/src/lib.rs | 11 ++++++++++- adb_client/src/transports/mod.rs | 6 ++++++ adb_client/src/transports/tcp_transport.rs | 5 ++--- adb_client/src/utils.rs | 13 ++++++++++++- 11 files changed, 73 insertions(+), 32 deletions(-) diff --git a/adb_client/Cargo.toml b/adb_client/Cargo.toml index e8a18fd..80c55d5 100644 --- a/adb_client/Cargo.toml +++ b/adb_client/Cargo.toml @@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = [] mdns = ["dep:mdns-sd"] +usb = ["dep:rsa", "dep:rusb"] [dependencies] base64 = { version = "0.22.1" } @@ -35,8 +36,6 @@ rcgen = { version = "0.13.2", default-features = false, features = [ "pem", ] } regex = { version = "1.12.2", features = ["perf", "std", "unicode"] } -rsa = { version = "0.9.8" } -rusb = { version = "0.9.4", features = ["vendored"] } rustls = { version = "0.23.33" } rustls-pki-types = { version = "1.12.0" } serde = { version = "1.0.228", features = ["derive"] } @@ -50,6 +49,11 @@ mdns-sd = { version = "0.13.11", default-features = false, features = [ "logging", ], optional = true } ######### +######### +# USB-only dependencies +rsa = { version = "0.9.7", optional = true } +rusb = { version = "0.9.4", features = ["vendored"], optional = true } +######### [dev-dependencies] anyhow = { version = "1.0.100" } diff --git a/adb_client/README.md b/adb_client/README.md index d284cca..87cd518 100644 --- a/adb_client/README.md +++ b/adb_client/README.md @@ -18,9 +18,10 @@ adb_client = "*" ## Crate features -|Feature|Description|Default?| -|:-----:|:---------:|:-----:| -|`mdns`|Enables mDNS device discovery on local network.|No| +| Feature | Description | Default? | +| :-----: | :---------------------------------------------: | :------: | +| `mdns` | Enables mDNS device discovery on local network. | No | +| `usb` | Enables interactions with USB devices. | No | To deactivate some features you can use the `default-features = false` option in your `Cargo.toml` file and manually specify the features you want to activate: @@ -37,11 +38,11 @@ Benchmarks run on `v2.0.6`, on a **Samsung S10 SM-G973F** device and an **Intel `ADBServerDevice` performs all operations by using adb server as a bridge. -|File size|Sample size|`ADBServerDevice`|`adb`|Difference| -|:-------:|:---------:|:----------:|:---:|:-----:| -|10 MB|100|350,79 ms|356,30 ms|
-1,57 %
| -|500 MB|50|15,60 s|15,64 s|
-0,25 %
| -|1 GB|20|31,09 s|31,12 s|
-0,10 %
| +| File size | Sample size | `ADBServerDevice` | `adb` | Difference | +| :-------: | :---------: | :---------------: | :-------: | :------------------------------------: | +| 10 MB | 100 | 350,79 ms | 356,30 ms |
-1,57 %
| +| 500 MB | 50 | 15,60 s | 15,64 s |
-0,25 %
| +| 1 GB | 20 | 31,09 s | 31,12 s |
-0,10 %
| ## Examples diff --git a/adb_client/src/device/adb_transport_message.rs b/adb_client/src/device/adb_transport_message.rs index 56a8753..93cd297 100644 --- a/adb_client/src/device/adb_transport_message.rs +++ b/adb_client/src/device/adb_transport_message.rs @@ -4,10 +4,6 @@ use crate::{Result, RustADBError}; use super::models::MessageCommand; -pub const AUTH_TOKEN: u32 = 1; -pub const AUTH_SIGNATURE: u32 = 2; -pub const AUTH_RSAPUBLICKEY: u32 = 3; - #[derive(Debug)] pub struct ADBTransportMessage { header: ADBTransportMessageHeader, diff --git a/adb_client/src/device/adb_usb_device.rs b/adb_client/src/device/adb_usb_device.rs index 83ee812..c213202 100644 --- a/adb_client/src/device/adb_usb_device.rs +++ b/adb_client/src/device/adb_usb_device.rs @@ -15,9 +15,13 @@ use super::{ADBRsaKey, ADBTransportMessage}; use crate::ADBDeviceExt; use crate::ADBMessageTransport; use crate::ADBTransport; -use crate::device::adb_transport_message::{AUTH_RSAPUBLICKEY, AUTH_SIGNATURE, AUTH_TOKEN}; +use crate::utils::get_default_adb_key_path; use crate::{Result, RustADBError, USBTransport}; +const AUTH_TOKEN: u32 = 1; +const AUTH_SIGNATURE: u32 = 2; +const AUTH_RSAPUBLICKEY: u32 = 3; + pub fn read_adb_private_key>(private_key_path: P) -> Result> { // Try to read the private key file from given path // If the file is not found, return None @@ -92,14 +96,6 @@ pub fn is_adb_device(device: &Device, des: &DeviceDescriptor) false } -pub fn get_default_adb_key_path() -> Result { - homedir::my_home() - .ok() - .flatten() - .map(|home| home.join(".android").join("adbkey")) - .ok_or(RustADBError::NoHomeDirectory) -} - /// Represent a device reached and available over USB. #[derive(Debug)] pub struct ADBUSBDevice { diff --git a/adb_client/src/device/mod.rs b/adb_client/src/device/mod.rs index a34b6a1..d9bbf06 100644 --- a/adb_client/src/device/mod.rs +++ b/adb_client/src/device/mod.rs @@ -2,6 +2,9 @@ mod adb_message_device; mod adb_message_device_commands; mod adb_tcp_device; mod adb_transport_message; + +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] mod adb_usb_device; mod commands; mod message_writer; @@ -11,9 +14,15 @@ mod shell_message_writer; use adb_message_device::ADBMessageDevice; pub use adb_tcp_device::ADBTcpDevice; pub use adb_transport_message::{ADBTransportMessage, ADBTransportMessageHeader}; -pub use adb_usb_device::{ - ADBUSBDevice, get_default_adb_key_path, is_adb_device, search_adb_devices, -}; + +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] +pub use adb_usb_device::{ADBUSBDevice, is_adb_device, search_adb_devices}; + pub use message_writer::MessageWriter; -pub use models::{ADBRsaKey, MessageCommand, MessageSubcommand}; +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] +pub use models::ADBRsaKey; + +pub use models::{MessageCommand, MessageSubcommand}; pub use shell_message_writer::ShellMessageWriter; diff --git a/adb_client/src/device/models/mod.rs b/adb_client/src/device/models/mod.rs index 7f97ceb..da632e9 100644 --- a/adb_client/src/device/models/mod.rs +++ b/adb_client/src/device/models/mod.rs @@ -1,5 +1,9 @@ +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] mod adb_rsa_key; mod message_commands; +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] pub use adb_rsa_key::ADBRsaKey; pub use message_commands::{MessageCommand, MessageSubcommand}; diff --git a/adb_client/src/error.rs b/adb_client/src/error.rs index 6b3af98..19032fa 100644 --- a/adb_client/src/error.rs +++ b/adb_client/src/error.rs @@ -70,6 +70,8 @@ pub enum RustADBError { #[error("Cannot get home directory")] NoHomeDirectory, /// Generic USB error + #[cfg(feature = "usb")] + #[cfg_attr(docsrs, doc(cfg(feature = "usb")))] #[error("USB Error: {0}")] UsbError(#[from] rusb::Error), /// USB device not found @@ -88,6 +90,8 @@ pub enum RustADBError { #[error(transparent)] Base64EncodeError(#[from] base64::EncodeSliceError), /// An error occurred with RSA engine + #[cfg(feature = "usb")] + #[cfg_attr(docsrs, doc(cfg(feature = "usb")))] #[error(transparent)] RSAError(#[from] rsa::errors::Error), /// Cannot convert given data from slice @@ -97,6 +101,8 @@ pub enum RustADBError { #[error("wrong file extension: {0}")] WrongFileExtension(String), /// An error occurred with PKCS8 data + #[cfg(feature = "usb")] + #[cfg_attr(docsrs, doc(cfg(feature = "usb")))] #[error("error with pkcs8: {0}")] RsaPkcs8Error(#[from] rsa::pkcs8::Error), /// Error during certificate generation diff --git a/adb_client/src/lib.rs b/adb_client/src/lib.rs index 06dfd4a..7b41eee 100644 --- a/adb_client/src/lib.rs +++ b/adb_client/src/lib.rs @@ -14,9 +14,11 @@ mod constants; mod device; mod emulator_device; mod error; + #[cfg(feature = "mdns")] #[cfg_attr(docsrs, doc(cfg(feature = "mdns")))] mod mdns; + mod models; mod server; mod server_device; @@ -24,12 +26,19 @@ mod transports; mod utils; pub use adb_device_ext::ADBDeviceExt; -pub use device::{ADBTcpDevice, ADBUSBDevice, is_adb_device, search_adb_devices}; +pub use device::ADBTcpDevice; + +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] +pub use device::{ADBUSBDevice, is_adb_device, search_adb_devices}; + pub use emulator_device::ADBEmulatorDevice; pub use error::{Result, RustADBError}; + #[cfg(feature = "mdns")] #[cfg_attr(docsrs, doc(cfg(feature = "mdns")))] pub use mdns::*; + pub use models::{AdbStatResponse, RebootType}; pub use server::*; pub use server_device::ADBServerDevice; diff --git a/adb_client/src/transports/mod.rs b/adb_client/src/transports/mod.rs index 28e89a0..da50c1f 100644 --- a/adb_client/src/transports/mod.rs +++ b/adb_client/src/transports/mod.rs @@ -2,10 +2,16 @@ mod tcp_emulator_transport; mod tcp_server_transport; mod tcp_transport; mod traits; + +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] mod usb_transport; pub use tcp_emulator_transport::TCPEmulatorTransport; pub use tcp_server_transport::TCPServerTransport; pub use tcp_transport::TcpTransport; pub use traits::{ADBMessageTransport, ADBTransport}; + +#[cfg(feature = "usb")] +#[cfg_attr(docsrs, doc(cfg(feature = "usb")))] pub use usb_transport::USBTransport; diff --git a/adb_client/src/transports/tcp_transport.rs b/adb_client/src/transports/tcp_transport.rs index d420b28..cb572a5 100644 --- a/adb_client/src/transports/tcp_transport.rs +++ b/adb_client/src/transports/tcp_transport.rs @@ -8,9 +8,8 @@ use rustls::{ use super::{ADBMessageTransport, ADBTransport}; use crate::{ Result, RustADBError, - device::{ - ADBTransportMessage, ADBTransportMessageHeader, MessageCommand, get_default_adb_key_path, - }, + device::{ADBTransportMessage, ADBTransportMessageHeader, MessageCommand}, + utils::get_default_adb_key_path, }; use std::{ fs::read_to_string, diff --git a/adb_client/src/utils.rs b/adb_client/src/utils.rs index d91041d..4b58dea 100644 --- a/adb_client/src/utils.rs +++ b/adb_client/src/utils.rs @@ -1,4 +1,7 @@ -use std::{ffi::OsStr, path::Path}; +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, +}; use crate::{Result, RustADBError}; @@ -16,3 +19,11 @@ pub fn check_extension_is_apk>(path: P) -> Result<()> { Ok(()) } + +pub fn get_default_adb_key_path() -> Result { + homedir::my_home() + .ok() + .flatten() + .map(|home| home.join(".android").join("adbkey")) + .ok_or(RustADBError::NoHomeDirectory) +}