diff --git a/Cargo.lock b/Cargo.lock index d29716f..c5a32f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -17,6 +17,55 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -119,7 +168,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.72", @@ -197,12 +246,58 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "cobs" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "colored" version = "1.9.4" @@ -214,6 +309,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -427,6 +535,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "enumflags2" version = "0.7.10" @@ -604,6 +718,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -712,6 +832,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "io-kit-sys" version = "0.4.1" @@ -733,6 +875,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.11" @@ -989,6 +1137,12 @@ dependencies = [ "libm", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.36.2" @@ -1211,9 +1365,11 @@ version = "0.1.0" dependencies = [ "anyhow", "axum", + "clap", "dfu-libusb", "fern", "humantime", + "indicatif", "libusb1-sys", "log", "nom", @@ -1545,6 +1701,12 @@ dependencies = [ "void", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -1854,6 +2016,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "usb-device" version = "0.3.2" @@ -1876,6 +2044,12 @@ dependencies = [ "usb-device", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "valuable" version = "0.1.0" diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index f08edfe..95f39bd 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -22,3 +22,5 @@ postcard = {version = "1.0.10", features = ["use-std"]} dfu-libusb = "0.3.0" libusb1-sys = "0.6" rusb = "0.9" +clap = { version = "4.5.19", features = ["derive"] } +indicatif = "0.17.8" diff --git a/daemon/src/bin/flash-dfu.rs b/daemon/src/bin/flash-dfu.rs new file mode 100644 index 0000000..bbe0ffa --- /dev/null +++ b/daemon/src/bin/flash-dfu.rs @@ -0,0 +1,112 @@ +use std::{ + io::{self, Seek}, + thread, + time::{self, Duration}, +}; + +use anyhow::{anyhow, Context}; +use clap::Parser; +use dfu_libusb::{Dfu, DfuLibusb}; +use postcard::{from_bytes_cobs, to_stdvec_cobs}; +use radomctl_protocol::*; +use radomctld::logger::setup_logger; + +#[derive(Parser)] +struct Cli { + /// The usb serial number of the radom-controller + #[arg(short, long)] + serialnumber: String, + + /// The firmware file to flash + #[arg(short, long)] + firmware: std::path::PathBuf, +} + +pub fn main() -> anyhow::Result<()> { + let args = Cli::parse(); + + let ports = serialport::available_ports().unwrap_or(Vec::::new()); + + let mut radom_port: Option = None; + for port in ports { + match port.port_type { + serialport::SerialPortType::UsbPort(usb_port_info) => { + match usb_port_info.serial_number { + Some(serial) => { + if serial == args.serialnumber { + radom_port = Some(port.port_name.to_owned()); + println!("Found radom-controller as {}", port.port_name) + } + } + None => continue, + } + } + _ => continue, + } + } + + let radom_port = match radom_port { + Some(port) => port, + _ => { + return Err(anyhow!("No matching port found.")); + } + }; + + println!("Setting radom-controller to dfu boot..."); + + let mut port = serialport::new(radom_port, 115_200) + .timeout(Duration::from_millis(10)) + .open() + .expect("Failed to open port"); + + let host_msg = HostMessage::TriggerDFUBootloader; + let msg_bytes = to_stdvec_cobs(&host_msg).unwrap(); + port.write_all(&msg_bytes).unwrap(); + drop(port); + + let context = rusb::Context::new()?; + let mut file = std::fs::File::open(args.firmware).context("firmware file not found")?; + + thread::sleep(time::Duration::from_millis(2000)); + + let file_size = + u32::try_from(file.seek(io::SeekFrom::End(0))?).context("the firmware file is too big")?; + file.seek(io::SeekFrom::Start(0))?; + + let vid = 0x0483; + let pid = 0xdf11; + let intf = 0; + let alt = 0; + let mut device: Dfu = + DfuLibusb::open(&context, vid, pid, intf, alt).context("could not open device")?; + + println!("Flashing radom-controller ..."); + + let bar = indicatif::ProgressBar::new(file_size as u64); + bar.set_style( + indicatif::ProgressStyle::default_bar() + .template( + "{spinner:.green} [{elapsed_precise}] [{bar}] \ + {bytes}/{total_bytes} ({bytes_per_sec}) ({eta}) {msg:10}", + )? + .progress_chars("=>-"), + ); + + device.with_progress({ + let bar = bar.clone(); + move |count| { + bar.inc(count as u64); + if bar.position() == file_size as u64 { + bar.finish(); + } + } + }); + + device + .download(file, file_size) + .context("could not write firmware to the device")?; + + println!("Done!"); + + Ok(()) +} diff --git a/daemon/src/bin/trigger-dfu.rs b/daemon/src/bin/trigger-dfu.rs deleted file mode 100644 index f229d73..0000000 --- a/daemon/src/bin/trigger-dfu.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::{ - io::{self, Seek}, - thread, - time::{self, Duration}, -}; - -use anyhow::Context; -use dfu_libusb::{Dfu, DfuLibusb}; -use postcard::{from_bytes_cobs, to_stdvec_cobs}; -use radomctl_protocol::*; -use radomctld::logger::setup_logger; - -pub fn main() -> anyhow::Result<()> { - let mut port = serialport::new("/dev/ttyACM0", 115_200) - .timeout(Duration::from_millis(10)) - .open() - .expect("Failed to open port"); - - let host_msg = HostMessage::TriggerDFUBootloader; - let msg_bytes = to_stdvec_cobs(&host_msg).unwrap(); - port.write_all(&msg_bytes).unwrap(); - drop(port); - - let context = rusb::Context::new()?; - let mut file = std::fs::File::open("../../firmware/radomctl-firmware.bin") - .context("firmware file not found")?; - - thread::sleep(time::Duration::from_millis(1000)); - - let file_size = - u32::try_from(file.seek(io::SeekFrom::End(0))?).context("the firmware file is too big")?; - file.seek(io::SeekFrom::Start(0))?; - - let vid = 0x0483; - let pid = 0xdf11; - let intf = 0; - let alt = 0; - let mut device: Dfu = - DfuLibusb::open(&context, vid, pid, intf, alt).context("could not open device")?; - - device - .download(file, file_size) - .context("could not write firmware to the device")?; - - Ok(()) -}