main: Naming collision avoidance + arg parsing

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

56
Cargo.lock generated
View File

@ -2,6 +2,26 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "auto-args"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40797fd8889b7625595cb391d6f8428802b65c22023ada3dc08d67953ac5e5e2"
dependencies = [
"auto-args-derive",
]
[[package]]
name = "auto-args-derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d4cbc684c4d4c80b06cd1009b7b78fe5a910187d1daeda1cc04319207b5894f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.31" version = "1.2.31"
@ -35,13 +55,32 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid",
]
[[package]] [[package]]
name = "procon2" name = "procon2"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"auto-args",
"rusb", "rusb",
] ]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "rusb" name = "rusb"
version = "0.9.4" version = "0.9.4"
@ -58,6 +97,23 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View File

@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
auto-args = "0.3.2"
rusb = "0.9.4" rusb = "0.9.4"

View File

@ -133,7 +133,7 @@ impl<'t, Ctx: rusb::UsbContext> Controller<'t, Ctx> {
// debug-print the header // debug-print the header
if self.verbose { if self.verbose {
println!("HEAD: {:02x?}", &buf[..16]); println!("CMD: {:02x?}\n => {:02x?}", command, &buf[..16]);
} }
let mut data = [0; 64]; 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 std::{error::Error, fmt::Display, io::Write, path::Path, thread::sleep, time::Duration};
use auto_args::AutoArgs;
use procon2::{ use procon2::{
Controller, Controller,
descriptor::{VID, pid}, descriptor::{VID, pid},
@ -25,16 +27,16 @@ const PLAYER: [u8; 16] = [
0b1010, 0b1010,
]; ];
fn main() -> Result<(), Box<dyn Error>> { #[derive(Debug, AutoArgs)]
let (mut dump, mut verbose) = (false, false); 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() { fn main() -> Result<(), Box<dyn Error>> {
match arg.as_str() { let Args { verbose, dump } = Args::from_args();
"dump" => dump = true,
"verbose" => verbose = true,
_ => {}
}
}
let mut devices = vec![]; let mut devices = vec![];
@ -53,20 +55,9 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
if dump { 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 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)?; procon_dump(controller, path)?;
} }
return Ok(()); return Ok(());
@ -92,6 +83,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
/// Dumps a Controller's firmware to a file at the given path
fn procon_dump<Ctx: rusb::UsbContext>( fn procon_dump<Ctx: rusb::UsbContext>(
controller: Controller<'_, Ctx>, controller: Controller<'_, Ctx>,
path: impl AsRef<Path> + Display, path: impl AsRef<Path> + Display,
@ -105,11 +97,12 @@ fn procon_dump<Ctx: rusb::UsbContext>(
file.write_all(&data)?; file.write_all(&data)?;
// progress bar // progress bar
if addr % 0x8000 == 0 { if addr % 0x40000 == 0 {
controller.set_player_led(PLAYER[7 - (addr >> 15 & 7)])?;
print!("."); print!(".");
std::io::stdout().flush()?; 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}"); println!("\nDumped to file {path}");
Ok(()) 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)
}