diff --git a/.gitignore b/.gitignore index 869df07..3160116 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target -Cargo.lock \ No newline at end of file +Cargo.lock + +src/mouse_config.rs \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3844e13 --- /dev/null +++ b/build.rs @@ -0,0 +1,109 @@ +enum Variable<'a> { + Int(&'a str, i32), + String(&'a str, &'a str), +} + +fn contains_string(variables: &[Variable]) -> bool { + variables.iter().any(|variable| match variable { + Variable::Int(_, _) => false, + Variable::String(_, _) => true, + }) +} + +fn create_config_struct(content: &str, path: &str, struct_name: &str) { + let variables: Vec> = content + .lines() + .map(|line| { + let mut split = line.split(':'); + + let name = split + .next() + .unwrap() + .trim() + .trim_start_matches('"') + .trim_end_matches('"'); + + let value = split.next().unwrap().trim(); + + if value.starts_with('"') { + let trimmed_string = value.trim_start_matches('"').trim_end_matches('"'); + + Variable::String(name, trimmed_string) + } else { + Variable::Int( + name, + if value.starts_with("0x") { + i32::from_str_radix(value.trim_start_matches("0x"), 16).unwrap() + } else { + str::parse(value).unwrap() + }, + ) + } + }) + .collect(); + + let needs_lifetime = contains_string(&variables); + let mut file_string = String::new(); + + file_string += &format!("pub struct {struct_name}"); + + if needs_lifetime { + file_string += "<'a> "; + } + + file_string += "{\n"; + + for variable in variables.iter() { + match variable { + Variable::Int(name, _value) => { + file_string += &format!("\tpub {name}: i32,\n"); + } + Variable::String(name, _value) => { + file_string += &format!("\tpub {name}: &'a str,\n"); + } + } + } + + file_string += "}\n\n"; + + file_string += "impl"; + + if needs_lifetime { + file_string += "<'a> "; + } + + file_string += struct_name; + + if needs_lifetime { + file_string += "<'a> "; + } + + file_string += "{\n"; + file_string += "\tpub const fn new() -> Self {\n"; + file_string += "\t\tSelf {\n"; + + for variable in variables.iter() { + match variable { + Variable::Int(name, value) => { + file_string += &format!("\t\t\t{name}: {value},\n"); + } + Variable::String(name, value) => { + file_string += &format!("\t\t\t{name}: \"{value}\",\n"); + } + } + } + + file_string += "\t\t}\n"; + file_string += "\t}\n"; + file_string += "}\n"; + + std::fs::write(path, file_string).unwrap(); +} + +fn main() { + create_config_struct( + include_str!("mouse.conf"), + "src/mouse_config.rs", + "MouseConfig", + ); +} diff --git a/mouse.conf b/mouse.conf new file mode 100644 index 0000000..8c5f703 --- /dev/null +++ b/mouse.conf @@ -0,0 +1,5 @@ +vendor_id: 0x046d +product_id: 0x101b +manufacturer: "Logitech" +product: "Performance Plus M705" +serial_number: "B14D65DA" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 288e51f..bf17457 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ #![feature(type_alias_impl_trait)] #![feature(never_type)] +mod mouse_config; mod mouse_hid; use embassy_executor::Spawner; @@ -11,7 +12,7 @@ use embassy_time::{Duration, Timer}; use usbd_hid::descriptor::MouseReport; -use crate::mouse_hid::{MouseConfig, MouseHID}; +use crate::{mouse_config::MouseConfig, mouse_hid::MouseHID}; use {defmt_rtt as _, panic_probe as _}; @@ -19,17 +20,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let mut mouse_hid = MouseHID::new( - p.USB, - MouseConfig { - vendor_id: 0x046d, - product_id: 0x101b, - manufacturer: "Logitech", - product: "Performance Plus M705", - serial_number: "B14D65DA", - }, - ) - .await; + let mut mouse_hid = MouseHID::new(p.USB, MouseConfig::new()); let usb_fut = MouseHID::run_usb().await; diff --git a/src/mouse_hid.rs b/src/mouse_hid.rs index 6befce3..d505efc 100644 --- a/src/mouse_hid.rs +++ b/src/mouse_hid.rs @@ -9,6 +9,8 @@ use embassy_usb::{Builder, Config, UsbDevice}; use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; +use crate::mouse_config::MouseConfig; + static mut DEVICE_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256]; static mut CONFIG_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256]; static mut BOS_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256]; @@ -18,26 +20,21 @@ static mut STATE: Option> = None; static mut USB: Option>> = None; static REQUEST_HANDLER: MyRequestHandler = MyRequestHandler {}; -pub struct MouseConfig<'a> { - pub vendor_id: u16, - pub product_id: u16, - pub manufacturer: &'a str, - pub product: &'a str, - pub serial_number: &'a str, -} - pub struct MouseHID<'d> { writer: HidWriter<'d, Driver<'d, USB>, 5>, } impl MouseHID<'static> { - pub async fn new(usb: USB, mouse_config: MouseConfig<'static>) -> MouseHID<'static> { + pub fn new(usb: USB, mouse_config: MouseConfig<'static>) -> MouseHID<'static> { // Create the driver, from the HAL. let irq = interrupt::take!(USBCTRL_IRQ); let driver = Driver::new(usb, irq); // Create embassy-usb Config - let mut config = Config::new(mouse_config.vendor_id, mouse_config.product_id); + let mut config = Config::new( + mouse_config.vendor_id as u16, + mouse_config.product_id as u16, + ); config.manufacturer = Some(mouse_config.manufacturer); config.product = Some(mouse_config.product); config.serial_number = Some(mouse_config.serial_number);