use std::collections::HashMap;
use std::fs::{self, File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
use std::env;
use std::process::Command;
use crate::{FifoConfig, Profile};
pub fn gen_regs_yaml(files: &Vec<String>, replacements: &HashMap<&str, String>) {
let out_dir = env::var("OUT_DIR").unwrap();
let output_path = Path::new(&out_dir).join("usb_regs.yaml");
let mut output_file = File::create(&output_path).unwrap();
for file_path in files {
let content = fs::read_to_string(file_path).unwrap();
let mut modified_content = content.clone();
for (key, value) in replacements {
modified_content = modified_content.replace(*key, value);
}
write!(output_file, "{modified_content}\n").unwrap();
}
}
pub fn gen_usb_pac() {
let out_dir = env::var("OUT_DIR")
.expect("OUT_DIR environment variable not set");
let input_path = Path::new(&out_dir).join("usb_regs.yaml");
let output_path = Path::new(&out_dir).join("usb_regs.tmp");
let yaml2pac_status = Command::new("yaml2pac")
.arg("-i")
.arg(input_path.to_str().unwrap())
.arg("-o")
.arg(output_path.to_str().unwrap())
.arg("--common")
.status()
.unwrap();
if !yaml2pac_status.success() {
panic!("yaml2pac command failed: {}", yaml2pac_status.code().unwrap());
}
let rustfmt_status = Command::new("rustfmt")
.arg(output_path.to_str().unwrap())
.status()
.expect("Failed to execute rustfmt");
if !rustfmt_status.success() {
panic!("rustfmt command failed: {}", yaml2pac_status.code().unwrap());
}
let file = File::open(output_path).unwrap();
let reader = BufReader::new(file);
let mut output_file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(Path::new(&out_dir).join("usb_regs.rs")).unwrap();
let lines = reader.lines().skip(4);
for line in lines {
output_file.write_all(line.unwrap().as_bytes()).unwrap();
output_file.write_all(b"\n").unwrap();
}
}
pub fn gen_info(profile: &Profile){
let out_dir = env::var("OUT_DIR").unwrap();
let output_path = Path::new(&out_dir).join("info.rs");
let mut file = File::create(output_path).unwrap();
if let Some(base_address) = profile.base_address {
let insert_content = format!(
r#"pub struct UsbInstance;
impl crate::MusbInstance for UsbInstance {{
fn regs() -> crate::regs::Usb {{
unsafe {{ crate::regs::Usb::from_ptr(({base_address:#x}) as _ ) }}
}}
}}
"#);
file.write_all(insert_content.as_bytes()).unwrap();
}
if let Some(endpoints_num) = profile.endpoints_num {
writeln!(file, "pub const ENDPOINTS_NUM: usize = {};", endpoints_num).unwrap();
}
match &profile.fifo {
FifoConfig::Fixed(config) => {
if config.equal_size {
if let Some(size) = config.dword_size {
writeln!(file, "pub const MAX_FIFO_SIZE_DWPRD: u8 = {};", size).unwrap();
}
} else {
if !config.dword_size_endpoints.is_empty() {
write!(file, "pub const MAX_FIFO_SIZE_DWPRD: [u8; {}] = [", config.dword_size_endpoints.len()).unwrap();
for (i, size) in config.dword_size_endpoints.iter().enumerate() {
if i > 0 {
write!(file, ", ").unwrap();
}
write!(file, "{}", size).unwrap();
}
writeln!(file, "];").unwrap();
}
}
},
FifoConfig::Dynamic(config) => {
writeln!(file, "pub const TOTAL_FIFO_SIZE_DWPRD: u32 = {};", config.dword_size_total).unwrap();
}
}
}