mirror of
https://codeberg.org/ral/rwedid.git
synced 2024-08-16 09:59:49 +02:00
Autodetect number of blocks to handle
This commit is contained in:
parent
09114c1c3e
commit
a1d0e66ec5
7 changed files with 64 additions and 20 deletions
|
@ -1,8 +1,5 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
// Size of EDID binary block
|
|
||||||
pub const BLOCK_SIZE: usize = 128;
|
|
||||||
|
|
||||||
fn hex_address(a: &str) -> Result<u16, std::num::ParseIntError> {
|
fn hex_address(a: &str) -> Result<u16, std::num::ParseIntError> {
|
||||||
u16::from_str_radix(a.trim_start_matches("0x"), 16)
|
u16::from_str_radix(a.trim_start_matches("0x"), 16)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +15,7 @@ pub struct Args {
|
||||||
#[arg(short, long, default_value = "0x50", value_parser = hex_address)]
|
#[arg(short, long, default_value = "0x50", value_parser = hex_address)]
|
||||||
pub address: u16,
|
pub address: u16,
|
||||||
|
|
||||||
/// Number of 128-byte blocks to read, defaults to reading the base block.
|
/// Number of 128-byte blocks to read, defaults to autodetect from data
|
||||||
#[arg(short, long, default_value_t = 1)]
|
#[arg(short, long, default_value = None)]
|
||||||
pub blocks: usize,
|
pub blocks: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rwedid::args::*;
|
use rwedid::args::*;
|
||||||
use rwedid::i2c::*;
|
use rwedid::i2c::*;
|
||||||
use std::io::{self, Write};
|
use rwedid::misc::*;
|
||||||
|
use rwedid::std::*;
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
// Parse command line arguments
|
// Parse command line arguments
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
// Read the data from the chip
|
// Read the data from the chip
|
||||||
let bytes = read_from_bus(&args.device, args.address, BLOCK_SIZE * args.blocks)?;
|
let bytes = block_by_block_read(args.blocks, |o, l| {
|
||||||
|
read_from_bus(&args.device, args.address, o, l)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Write binary blob to stdout
|
// Write binary blob to stdout
|
||||||
let mut stdout = io::stdout().lock();
|
write_to_std(&bytes)
|
||||||
stdout.write_all(&bytes)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rwedid::args::*;
|
use rwedid::args::*;
|
||||||
use rwedid::i2c::*;
|
use rwedid::i2c::*;
|
||||||
use std::io::{self, Read};
|
use rwedid::misc::*;
|
||||||
|
use rwedid::std::*;
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
// Parse command line arguments
|
// Parse command line arguments
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
// Read binary from stdin
|
// Read binary from stdin
|
||||||
let data_length = args.blocks * BLOCK_SIZE;
|
let data = block_by_block_read(args.blocks, |_, l| read_from_std(l))?;
|
||||||
let mut data = vec![0; data_length];
|
|
||||||
|
|
||||||
// Read binary blob from stdin
|
|
||||||
io::stdin().read_exact(data.as_mut_slice())?;
|
|
||||||
|
|
||||||
// Write the data to the chip
|
// Write the data to the chip
|
||||||
write_to_bus(&args.device, args.address, data.as_slice())
|
write_to_bus(&args.device, args.address, data.as_slice())
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::time::Duration;
|
||||||
pub fn read_from_bus(
|
pub fn read_from_bus(
|
||||||
i2c_device: &str,
|
i2c_device: &str,
|
||||||
slave_address: u16,
|
slave_address: u16,
|
||||||
|
memory_address: u8,
|
||||||
data_length: usize,
|
data_length: usize,
|
||||||
) -> Result<Vec<u8>, std::io::Error> {
|
) -> Result<Vec<u8>, std::io::Error> {
|
||||||
let mut data = vec![0; data_length];
|
let mut data = vec![0; data_length];
|
||||||
|
@ -14,7 +15,7 @@ pub fn read_from_bus(
|
||||||
let mut dev = LinuxI2CDevice::new(i2c_device, slave_address)?;
|
let mut dev = LinuxI2CDevice::new(i2c_device, slave_address)?;
|
||||||
let mut msgs = [
|
let mut msgs = [
|
||||||
// Address to read from
|
// Address to read from
|
||||||
LinuxI2CMessage::write(&[0x00]),
|
LinuxI2CMessage::write(&[memory_address]),
|
||||||
// Read data into buffer
|
// Read data into buffer
|
||||||
LinuxI2CMessage::read(&mut data),
|
LinuxI2CMessage::read(&mut data),
|
||||||
];
|
];
|
||||||
|
@ -34,9 +35,8 @@ pub fn write_to_bus(
|
||||||
|
|
||||||
// Write 8 bytes at a time
|
// Write 8 bytes at a time
|
||||||
for (i, chunk) in data.chunks_exact(8).into_iter().enumerate() {
|
for (i, chunk) in data.chunks_exact(8).into_iter().enumerate() {
|
||||||
|
|
||||||
// Memory address
|
// Memory address
|
||||||
let memory_address : u8 = (i as u8) * 8;
|
let memory_address: u8 = (i as u8) * 8;
|
||||||
let mut msgs = [
|
let mut msgs = [
|
||||||
// Address to write to
|
// Address to write to
|
||||||
LinuxI2CMessage::write(&[memory_address]),
|
LinuxI2CMessage::write(&[memory_address]),
|
||||||
|
@ -47,7 +47,7 @@ pub fn write_to_bus(
|
||||||
dev.transfer(&mut msgs)?;
|
dev.transfer(&mut msgs)?;
|
||||||
|
|
||||||
thread::sleep(Duration::from_millis(20));
|
thread::sleep(Duration::from_millis(20));
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod i2c;
|
pub mod i2c;
|
||||||
|
pub mod misc;
|
||||||
|
pub mod std;
|
||||||
|
|
31
src/misc.rs
Normal file
31
src/misc.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Size of EDID binary block
|
||||||
|
pub const BLOCK_SIZE: usize = 128;
|
||||||
|
|
||||||
|
pub fn block_by_block_read(
|
||||||
|
blocks: Option<usize>,
|
||||||
|
read: impl Fn(u8, usize) -> Result<Vec<u8>, std::io::Error>,
|
||||||
|
) -> Result<Vec<u8>, std::io::Error> {
|
||||||
|
match blocks {
|
||||||
|
// Default: autodetect number of extension blocks
|
||||||
|
None => {
|
||||||
|
// Read first block (128 bytes)
|
||||||
|
let data_base = read(0x00, BLOCK_SIZE)?;
|
||||||
|
// Try to read remaining bytes
|
||||||
|
let data_extensions = match data_base.len() {
|
||||||
|
// Proper 128 byte block
|
||||||
|
BLOCK_SIZE => {
|
||||||
|
// Number of extension blocks that should follow
|
||||||
|
let num_extensions: usize = data_base[BLOCK_SIZE - 2].into();
|
||||||
|
// Read remaining blocks
|
||||||
|
read(BLOCK_SIZE as u8, num_extensions * BLOCK_SIZE)?
|
||||||
|
}
|
||||||
|
// Something else, obviously broken
|
||||||
|
_ => vec![],
|
||||||
|
};
|
||||||
|
// Return complete byte stream
|
||||||
|
Ok([data_base, data_extensions].concat())
|
||||||
|
}
|
||||||
|
// Explicitly read as many blocks as specified by user
|
||||||
|
Some(blocks) => read(0x00, blocks * BLOCK_SIZE),
|
||||||
|
}
|
||||||
|
}
|
15
src/std.rs
Normal file
15
src/std.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
|
pub fn read_from_std(data_length: usize) -> Result<Vec<u8>, std::io::Error> {
|
||||||
|
// Buffer to read into
|
||||||
|
let mut data = vec![0; data_length];
|
||||||
|
// Read from stdin
|
||||||
|
io::stdin().read_exact(data.as_mut_slice())?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_std(data: &[u8]) -> Result<(), std::io::Error> {
|
||||||
|
// Write data to stdout
|
||||||
|
let mut stdout = io::stdout().lock();
|
||||||
|
stdout.write_all(&data)
|
||||||
|
}
|
Loading…
Reference in a new issue