extern crate libusb; extern crate colored; extern crate json; use colored::Colorize; use std::path::Path; #[derive(Debug)] struct KeyboardLighting { lighting_type: String, rows: u16, cols: u16 } #[derive(Debug)] struct KeyboardLayout { rows: u16, cols: u16, keys: Vec } #[derive(Debug)] struct KeyboardConfig { name: String, vendor_id: u16, product_id: u16, layout: KeyboardLayout, lighting: KeyboardLighting } fn parse_config(config_path: &Path) -> KeyboardConfig{ let mut parsed_json = json::parse(&std::fs::read_to_string(config_path).unwrap()).unwrap(); // General info let extracted_name: String = parsed_json["name"].as_str().expect("ERROR: Failed to parse name").to_string(); let extracted_vendor_id: u16 = u16::from_str_radix(parsed_json["vendor_id"].as_str().expect("ERROR: Failed to parse name"), 16).unwrap(); let extracted_product_id: u16 = u16::from_str_radix(parsed_json["product_id"].as_str().expect("ERROR: Failed to parse name"), 16).unwrap(); // Layout let extracted_layout_rows: u16 = parsed_json["layout"]["rows"].as_u16().expect("ERROR: Failed to parse layout rows"); let extracted_layout_cols: u16 = parsed_json["layout"]["cols"].as_u16().expect("ERROR: Failed to parse layout cols"); let mut extracted_layout_keys: Vec = Vec::new(); let mut keys: std::collections::VecDeque = std::collections::VecDeque::new(); for i in 0..extracted_layout_rows { let mut row: json::JsonValue = parsed_json["layout"]["keys"].pop(); for j in 0..extracted_layout_cols { keys.push_front(row.pop().as_str().expect("ERROR: Failed to extract key names").to_string()); } } for i in 0..keys.len() { extracted_layout_keys.push(keys.pop_front().expect("ERROR: Empty key value")); } let keyboard_layout = KeyboardLayout { rows: extracted_layout_rows, cols: extracted_layout_cols, keys: extracted_layout_keys }; // Lighting let extracted_lighting_type: String = parsed_json["lighting"]["type"].as_str().expect("ERROR: Failed to parse lighting type").to_string(); let extracted_lighting_rows: u16 = parsed_json["lighting"]["layout"]["rows"].as_u16().expect("ERROR: Failed to parse lighting rows"); let extracted_lighting_cols: u16 = parsed_json["lighting"]["layout"]["cols"].as_u16().expect("ERROR: Failed to parse lighting cols"); let keyboard_lighting = KeyboardLighting { lighting_type: extracted_lighting_type, rows: extracted_lighting_rows, cols: extracted_lighting_cols }; let keyboard_config = KeyboardConfig { name: extracted_name, vendor_id: extracted_vendor_id, product_id: extracted_product_id, layout: keyboard_layout, lighting: keyboard_lighting }; return keyboard_config; } fn main() { let config: KeyboardConfig = parse_config(&Path::new("numpad_config.json")); println!("{:#?}", config); let context = libusb::Context::new().unwrap(); for device in context.devices().unwrap().iter() { let device_desc = device.device_descriptor().unwrap(); println!("Bus {:03} Device {:03} ID {:04x}:{:04x}", device.bus_number(), device.address(), device_desc.vendor_id(), device_desc.product_id()); if device_desc.vendor_id() == config.vendor_id && device_desc.product_id() == config.product_id { println!("Woah, this is my device! I'm going to open it!"); let config_desc = device.active_config_descriptor().unwrap(); let mut device_handle: libusb::DeviceHandle = device.open().unwrap(); println!("Number of interfaces: {}", config_desc.num_interfaces()); //println!("The device supports these languages: {:?}", &device_handle.read_languages(std::time::Duration::from_millis(100))); if device_handle.kernel_driver_active(0).unwrap() { println!("Interface has kernel driver, detaching..."); device_handle.detach_kernel_driver(0).unwrap(); } device_handle.claim_interface(0).unwrap(); match device_handle.write_control(libusb::request_type(libusb::Direction::Out, libusb::RequestType::Class, libusb::Recipient::Interface), 0x09, 0x0300, 0, &[0x00], std::time::Duration::from_secs(1)) { Ok(n) => { println!("{}", format!("Successfully wrote {} bytes!", n).green()); }, Err(e) => { eprintln!("{}{:?}", format!("Failed to write with error: ").red().bold(), e); } } device_handle.release_interface(0).unwrap(); device_handle.attach_kernel_driver(0).unwrap(); println!("Goodbye!"); std::process::exit(0); } } }