Skip to content

Commit

Permalink
feat: add adb push over USB
Browse files Browse the repository at this point in the history
  • Loading branch information
cocool97 committed Oct 25, 2024
1 parent 73021b1 commit e82ba39
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 48 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ resolver = "2"

[workspace.package]
edition = "2021"
keywords = ["adb", "android", "tcp", "usb"]
license = "MIT"
repository = "https://github.com/cocool97/adb_client"
version = "1.0.7"
keywords = ["adb", "android"]

# To build locally when working on a new version
# To build locally when working on a new release
[patch.crates-io]
adb_client = { path = "./adb_client" }

Expand Down
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,30 @@
</p>
</p>

Main features :
Main features of this library:

- Full Rust, no need to use `adb *` shell commands
- Currently only support server TCP/IP protocol
- Full Rust, don't use `adb *` shell commands to interact with devices
- Supports:
- **TCP/IP** protocol, using ADB server as a proxy (standard behavior when using `adb` CLI)
- **USB** protocol, interacting directly with end devices
- Implements hidden `adb` features, like `framebuffer`
- Highly configurable
- Easy to use !

## adb_client

Rust library implementing ADB protocol and providing high-level abstraction over commands.
Rust library implementing both ADB protocols and providing a high-level abstraction over many supported commands.

Improved documentation [here](./adb_client/README.md).

## adb_cli

Rust binary providing an improved version of `adb` CLI, using `adb_client` library. Can be used as an usage example of the library.
Rust binary providing an improved version of official `adb` CLI, wrapping `adb_client` library. Can act as an usage example of the library.

Improved documentation [here](./adb_cli/README.md).

## Missing features

- USB protocol (Work in progress)

## Related publications

- [Diving into ADB protocol internals (1/2)](https://www.synacktiv.com/publications/diving-into-adb-protocol-internals-12)

All pull requests are welcome !
Some features may still be missing, all pull requests are welcome !
25 changes: 25 additions & 0 deletions adb_cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ cargo install adb_cli

Usage is quite simple, and tends to look like `adb`:

- To use ADB server as a proxy:

```bash
user@laptop ~/adb_client (main)> adb_cli --help
Rust ADB (Android Debug Bridge) CLI
Expand Down Expand Up @@ -49,3 +51,26 @@ Options:
-h, --help Print help
-V, --version Print version
```

- To interact directly with end devices

```bash
user@laptop ~/adb_client (main)> adb_cli usb --help
Device commands via USB, no server needed

Usage: adb_cli usb [OPTIONS] --vendor-id <VID> --product-id <PID> <COMMAND>

Commands:
shell Spawn an interactive shell or run a list of commands on the device
pull Pull a file from device
push Push a file on device
stat Stat a file on device
reboot Reboot the device
help Print this message or the help of the given subcommand(s)

Options:
-v, --vendor-id <VID> Hexadecimal vendor id of this USB device
-p, --product-id <PID> Hexadecimal product id of this USB device
-k, --private-key <PATH_TO_PRIVATE_KEY> Path to a custom private key to use for authentication
-h, --help Print help
```
2 changes: 2 additions & 0 deletions adb_cli/src/commands/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub enum UsbCommands {
Shell { commands: Vec<String> },
/// Pull a file from device
Pull { source: String, destination: String },
/// Push a file on device
Push { filename: String, path: String },
/// Stat a file on device
Stat { path: String },
/// Reboot the device
Expand Down
15 changes: 12 additions & 3 deletions adb_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn main() -> Result<()> {
}
LocalCommand::Push { filename, path } => {
let mut input = File::open(Path::new(&filename))?;
device.send(&mut input, &path)?;
device.push(&mut input, &path)?;
log::info!("Uploaded {filename} to {path}");
}
LocalCommand::List { path } => {
Expand Down Expand Up @@ -158,8 +158,12 @@ fn main() -> Result<()> {
}
}
Command::Usb(usb) => {
let mut device =
ADBUSBDevice::new(usb.vendor_id, usb.product_id, usb.path_to_private_key)?;
let mut device = match usb.path_to_private_key {
Some(pk) => {
ADBUSBDevice::new_with_custom_private_key(usb.vendor_id, usb.product_id, pk)?
}
None => ADBUSBDevice::new(usb.vendor_id, usb.product_id)?,
};

match usb.commands {
UsbCommands::Shell { commands } => {
Expand Down Expand Up @@ -197,6 +201,11 @@ fn main() -> Result<()> {
log::info!("Reboots device in mode {:?}", reboot_type);
device.reboot(reboot_type.into())?
}
UsbCommands::Push { filename, path } => {
let mut input = File::open(Path::new(&filename))?;
device.push(&mut input, &path)?;
log::info!("Uploaded {filename} to {path}");
}
}
}
}
Expand Down
55 changes: 42 additions & 13 deletions adb_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,6 @@ adb_client = "*"

## Examples

### Launch a command on device via ADB server

```rust no_run
use adb_client::{ADBServer, ADBDeviceExt};

let mut server = ADBServer::default();
let mut device = server.get_device().expect("cannot get device");
device.shell_command(["df", "-h"],std::io::stdout());
```

### Get available ADB devices

```rust no_run
Expand All @@ -41,7 +31,19 @@ let mut server = ADBServer::new(SocketAddrV4::new(server_ip, server_port));
server.devices();
```

### Push a file to the device
### Using ADB server as proxy

#### [TCP] Launch a command on device

```rust no_run
use adb_client::{ADBServer, ADBDeviceExt};

let mut server = ADBServer::default();
let mut device = server.get_device().expect("cannot get device");
device.shell_command(["df", "-h"],std::io::stdout());
```

#### [TCP] Push a file to the device

```rust no_run
use adb_client::ADBServer;
Expand All @@ -51,6 +53,33 @@ use std::path::Path;

let mut server = ADBServer::default();
let mut device = server.get_device().expect("cannot get device");
let mut input = File::open(Path::new("/tmp")).expect("Cannot open file");
device.send(&mut input, "/data/local/tmp");
let mut input = File::open(Path::new("/tmp/f")).expect("Cannot open file");
device.push(&mut input, "/data/local/tmp");
```

### Interacting directly with device

#### [USB] Launch a command on device

```rust no_run
use adb_client::{ADBUSBDevice, ADBDeviceExt};

let vendor_id = 0x04e8;
let product_id = 0x6860;
let mut device = ADBUSBDevice::new(vendor_id, product_id).expect("cannot find device");
device.shell_command(["df", "-h"],std::io::stdout());
```

#### [USB] Push a file to the device

```rust no_run
use adb_client::{ADBUSBDevice, ADBDeviceExt};
use std::fs::File;
use std::path::Path;

let vendor_id = 0x04e8;
let product_id = 0x6860;
let mut device = ADBUSBDevice::new(vendor_id, product_id).expect("cannot find device");
let mut input = File::open(Path::new("/tmp/f")).expect("Cannot open file");
device.push(&mut input, "/data/local/tmp");
```
3 changes: 3 additions & 0 deletions adb_client/src/adb_device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub trait ADBDeviceExt {
/// Pull the remote file pointed to by [source] and write its contents into [`output`]
fn pull<A: AsRef<str>, W: Write>(&mut self, source: A, output: W) -> Result<()>;

/// Push [stream] to [path] on the device.
fn push<R: Read, A: AsRef<str>>(&mut self, stream: R, path: A) -> Result<()>;

/// Reboots the device using given reboot type
fn reboot(&mut self, reboot_type: RebootType) -> Result<()>;
}
4 changes: 4 additions & 0 deletions adb_client/src/server/adb_server_device_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,8 @@ impl ADBDeviceExt for ADBServerDevice {
fn reboot(&mut self, reboot_type: crate::RebootType) -> Result<()> {
self.reboot(reboot_type)
}

fn push<R: Read, A: AsRef<str>>(&mut self, stream: R, path: A) -> Result<()> {
self.push(stream, path)
}
}
2 changes: 1 addition & 1 deletion adb_client/src/server/device_commands/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<W: Write> Write for ADBSendCommandWriter<W> {

impl ADBServerDevice {
/// Send [stream] to [path] on the device.
pub fn send<R: Read, A: AsRef<str>>(&mut self, stream: R, path: A) -> Result<()> {
pub fn push<R: Read, A: AsRef<str>>(&mut self, stream: R, path: A) -> Result<()> {
log::info!("Sending data to {}", path.as_ref());
let serial = self.identifier.clone();
self.connect()?
Expand Down
Loading

0 comments on commit e82ba39

Please sign in to comment.