keyboard_control_software/src/main.rs
Sebastian H. Gabrielli 023283b807 Initial commit
2022-06-16 00:10:16 +02:00

132 lines
4.8 KiB
Rust

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<String>
}
#[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<String> = Vec::new();
let mut keys: std::collections::VecDeque<String> = 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);
}
}
}