breaking(feature): add usb feature

This commit is contained in:
Corentin LIAUD
2025-08-27 21:00:11 +02:00
parent 38fead7101
commit db853ed67a
11 changed files with 73 additions and 32 deletions

View File

@@ -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" }

View File

@@ -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|<div style="color:green">-1,57 %</div>|
|500 MB|50|15,60 s|15,64 s|<div style="color:green">-0,25 %</div>|
|1 GB|20|31,09 s|31,12 s|<div style="color:green">-0,10 %</div>|
| File size | Sample size | `ADBServerDevice` | `adb` | Difference |
| :-------: | :---------: | :---------------: | :-------: | :------------------------------------: |
| 10 MB | 100 | 350,79 ms | 356,30 ms | <div style="color:green">-1,57 %</div> |
| 500 MB | 50 | 15,60 s | 15,64 s | <div style="color:green">-0,25 %</div> |
| 1 GB | 20 | 31,09 s | 31,12 s | <div style="color:green">-0,10 %</div> |
## Examples

View File

@@ -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,

View File

@@ -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<P: AsRef<Path>>(private_key_path: P) -> Result<Option<ADBRsaKey>> {
// 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<T: UsbContext>(device: &Device<T>, des: &DeviceDescriptor)
false
}
pub fn get_default_adb_key_path() -> Result<PathBuf> {
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 {

View File

@@ -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;

View File

@@ -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};

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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<P: AsRef<Path>>(path: P) -> Result<()> {
Ok(())
}
pub fn get_default_adb_key_path() -> Result<PathBuf> {
homedir::my_home()
.ok()
.flatten()
.map(|home| home.join(".android").join("adbkey"))
.ok_or(RustADBError::NoHomeDirectory)
}