main: Naming collision avoidance + arg parsing

This commit is contained in:
2025-08-02 08:10:46 -04:00
parent 8b56a1bc5d
commit 0bb97b167f
4 changed files with 101 additions and 26 deletions

View File

@@ -133,7 +133,7 @@ impl<'t, Ctx: rusb::UsbContext> Controller<'t, Ctx> {
// debug-print the header
if self.verbose {
println!("HEAD: {:02x?}", &buf[..16]);
println!("CMD: {:02x?}\n => {:02x?}", command, &buf[..16]);
}
let mut data = [0; 64];

View File

@@ -1,5 +1,7 @@
use std::{error::Error, fmt::Display, io::Write, path::Path, thread::sleep, time::Duration};
use auto_args::AutoArgs;
use procon2::{
Controller,
descriptor::{VID, pid},
@@ -25,16 +27,16 @@ const PLAYER: [u8; 16] = [
0b1010,
];
fn main() -> Result<(), Box<dyn Error>> {
let (mut dump, mut verbose) = (false, false);
#[derive(Debug, AutoArgs)]
struct Args {
/// Prints the sent and received messages
verbose: bool,
/// Dumps the firmware of all connected controllers
dump: bool,
}
for arg in std::env::args() {
match arg.as_str() {
"dump" => dump = true,
"verbose" => verbose = true,
_ => {}
}
}
fn main() -> Result<(), Box<dyn Error>> {
let Args { verbose, dump } = Args::from_args();
let mut devices = vec![];
@@ -53,20 +55,9 @@ fn main() -> Result<(), Box<dyn Error>> {
}
if dump {
for (player, device) in devices.iter().enumerate() {
for device in &devices {
let path = make_path(device)?;
let controller = Controller::new(device).verbose(verbose);
let descriptor = device.device().device_descriptor()?;
let name = if let Some(nid) = descriptor.product_string_index() {
device.read_string_descriptor_ascii(nid)?
} else {
String::from("procon")
};
let path = format!(
"{name} {:04x}_{:04x}_{}-{player:x}.bin",
descriptor.vendor_id(),
descriptor.product_id(),
descriptor.device_version()
);
procon_dump(controller, path)?;
}
return Ok(());
@@ -92,6 +83,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
/// Dumps a Controller's firmware to a file at the given path
fn procon_dump<Ctx: rusb::UsbContext>(
controller: Controller<'_, Ctx>,
path: impl AsRef<Path> + Display,
@@ -105,11 +97,12 @@ fn procon_dump<Ctx: rusb::UsbContext>(
file.write_all(&data)?;
// progress bar
if addr % 0x8000 == 0 {
controller.set_player_led(PLAYER[7 - (addr >> 15 & 7)])?;
if addr % 0x40000 == 0 {
print!(".");
std::io::stdout().flush()?;
sleep(Duration::from_millis(0));
}
if addr % 0x8000 == 0 {
controller.set_player_led(PLAYER[7 - ((addr / 0x8000) & 7)])?;
}
}
@@ -117,3 +110,28 @@ fn procon_dump<Ctx: rusb::UsbContext>(
println!("\nDumped to file {path}");
Ok(())
}
/// Creates a path to store a given device's firmware at, avoiding naming collisions
fn make_path<Ctx: rusb::UsbContext>(device: &rusb::DeviceHandle<Ctx>) -> rusb::Result<String> {
let descriptor = device.device().device_descriptor()?;
let name = match descriptor.product_string_index() {
Some(nid) => device.read_string_descriptor_ascii(nid)?,
None => String::from("procon"),
};
let path = format!(
"{name} {:04x}_{:04x}_{}",
descriptor.vendor_id(),
descriptor.product_id(),
descriptor.device_version()
);
let mut count = 1;
let mut out_path = format!("{path}.bin");
while std::fs::exists(&out_path).unwrap_or(true) {
out_path = format!("{path}({count}).bin");
count += 1;
}
Ok(out_path)
}