-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add framebuffer over USB/TCP direct devices
- Loading branch information
Showing
15 changed files
with
304 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,11 @@ | ||
use std::net::SocketAddr; | ||
use std::path::PathBuf; | ||
|
||
use clap::Parser; | ||
use std::net::SocketAddr; | ||
|
||
use crate::models::RebootTypeCommand; | ||
use super::DeviceCommands; | ||
|
||
#[derive(Parser, Debug)] | ||
pub struct TcpCommand { | ||
pub address: SocketAddr, | ||
#[clap(subcommand)] | ||
pub commands: TcpCommands, | ||
} | ||
|
||
#[derive(Parser, Debug)] | ||
pub enum TcpCommands { | ||
/// Spawn an interactive shell or run a list of commands on the device | ||
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 }, | ||
/// Run an activity on device specified by the intent | ||
Run { | ||
/// The package whose activity is to be invoked | ||
#[clap(short = 'p', long = "package")] | ||
package: String, | ||
/// The activity to be invoked itself, Usually it is MainActivity | ||
#[clap(short = 'a', long = "activity")] | ||
activity: String, | ||
}, | ||
/// Reboot the device | ||
Reboot { | ||
#[clap(subcommand)] | ||
reboot_type: RebootTypeCommand, | ||
}, | ||
/// Install an APK on device | ||
Install { | ||
/// Path to APK file. Extension must be ".apk" | ||
path: PathBuf, | ||
}, | ||
pub commands: DeviceCommands, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
use std::io::{Cursor, Read, Write}; | ||
|
||
use byteorder::{LittleEndian, ReadBytesExt}; | ||
use image::{ImageBuffer, ImageFormat, Rgba}; | ||
|
||
use crate::{ | ||
device::{adb_message_device::ADBMessageDevice, ADBTransportMessage, MessageCommand}, | ||
models::{FrameBufferInfoV1, FrameBufferInfoV2}, | ||
ADBMessageTransport, Result, RustADBError, | ||
}; | ||
|
||
impl<T: ADBMessageTransport> ADBMessageDevice<T> { | ||
pub fn framebuffer<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<()> { | ||
let img = self.framebuffer_inner()?; | ||
Ok(img.save(path.as_ref())?) | ||
} | ||
|
||
pub fn framebuffer_bytes<W: Write + std::io::Seek>(&mut self, mut writer: W) -> Result<()> { | ||
let img = self.framebuffer_inner()?; | ||
Ok(img.write_to(&mut writer, ImageFormat::Png)?) | ||
} | ||
|
||
fn framebuffer_inner(&mut self) -> Result<ImageBuffer<Rgba<u8>, Vec<u8>>> { | ||
let message = | ||
ADBTransportMessage::new(MessageCommand::Open, 1, 0, b"framebuffer:\0".to_vec()); | ||
|
||
let response = self.send_and_expect_okay(message)?; | ||
|
||
let local_id = response.header().arg1(); | ||
let remote_id = response.header().arg0(); | ||
|
||
let response = self.recv_and_reply_okay(local_id, remote_id)?; | ||
|
||
let mut payload_cursor = Cursor::new(response.payload()); | ||
|
||
let version = payload_cursor.read_u32::<LittleEndian>()?; | ||
|
||
let img = match version { | ||
// RGBA_8888 | ||
1 => { | ||
let mut buf = [0u8; std::mem::size_of::<FrameBufferInfoV1>()]; | ||
|
||
payload_cursor.read_exact(&mut buf)?; | ||
|
||
let framebuffer_info: FrameBufferInfoV1 = buf.try_into()?; | ||
|
||
let mut data = vec![ | ||
0_u8; | ||
framebuffer_info | ||
.size | ||
.try_into() | ||
.map_err(|_| RustADBError::ConversionError)? | ||
]; | ||
payload_cursor.read_exact(&mut data)?; | ||
|
||
ImageBuffer::<Rgba<u8>, Vec<u8>>::from_vec( | ||
framebuffer_info.width, | ||
framebuffer_info.height, | ||
data, | ||
) | ||
.ok_or_else(|| RustADBError::FramebufferConversionError)? | ||
} | ||
// RGBX_8888 | ||
2 => { | ||
let mut buf = [0u8; std::mem::size_of::<FrameBufferInfoV2>()]; | ||
|
||
payload_cursor.read_exact(&mut buf)?; | ||
|
||
let framebuffer_info: FrameBufferInfoV2 = buf.try_into()?; | ||
|
||
let mut framebuffer_data = Vec::new(); | ||
payload_cursor.read_to_end(&mut framebuffer_data)?; | ||
|
||
loop { | ||
if framebuffer_data.len() as u32 == framebuffer_info.size { | ||
break; | ||
} | ||
|
||
let response = self.recv_and_reply_okay(local_id, remote_id)?; | ||
|
||
framebuffer_data.extend_from_slice(&response.into_payload()); | ||
|
||
log::debug!( | ||
"received framebuffer data. new size {}", | ||
framebuffer_data.len() | ||
); | ||
} | ||
|
||
ImageBuffer::<Rgba<u8>, Vec<u8>>::from_vec( | ||
framebuffer_info.width, | ||
framebuffer_info.height, | ||
framebuffer_data, | ||
) | ||
.ok_or_else(|| RustADBError::FramebufferConversionError)? | ||
} | ||
v => return Err(RustADBError::UnimplementedFramebufferImageVersion(v)), | ||
}; | ||
|
||
let message = self.get_transport_mut().read_message()?; | ||
match message.header().command() { | ||
MessageCommand::Clse => Ok(img), | ||
c => Err(RustADBError::ADBRequestFailed(format!( | ||
"Wrong command received {}", | ||
c | ||
))), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
mod framebuffer; | ||
mod install; | ||
mod pull; | ||
mod push; | ||
|
Oops, something went wrong.