From 871bdaf9c0bc8ad0fe4890ca5c4ec895d2fb4fbd Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Sun, 26 Jun 2022 13:55:29 +0200 Subject: [PATCH] Added a function to send lighting update && extract data from button press --- src/main.rs | 84 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index 73549a5..585d0cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,11 @@ extern crate colored; extern crate json; use std::path::Path; +use std::{cell::Cell, rc::Rc}; +use colored::Colorize; + +use gtk::glib::clone; use gtk::{prelude::*, Window}; use gtk::{Application, ApplicationWindow, Button, ListBox}; @@ -148,6 +152,44 @@ fn main() { app.run(); } +// USB Code +fn send_lighting_update(col: u8, row: u8, r: u8, g: u8, b: u8, a: u8) { + let config: KeyboardConfig = parse_config(&Path::new("numpad_config.json")); + + let context = libusb::Context::new().unwrap(); // Get a new USB context + for device in context.devices().unwrap().iter() { // Iterate through all the devices + let device_desc = device.device_descriptor().unwrap(); // Get a descriptor for the device + + if device_desc.vendor_id() == config.vendor_id && device_desc.product_id() == config.product_id { // Check if the devie is the device we are looking for + println!("Woah, this is my device! I'm going to open it!"); + + let mut device_handle: libusb::DeviceHandle = device.open().unwrap(); // Get a handle for the device + + if device_handle.kernel_driver_active(0).unwrap() { // If the device has an active kernel driver, detach it + println!("Interface has kernel driver, detaching..."); + device_handle.detach_kernel_driver(0).unwrap(); + } + device_handle.claim_interface(0).unwrap(); // Now that the device is freed we claim it + + match device_handle.write_control( + libusb::request_type(libusb::Direction::Out, libusb::RequestType::Class, libusb::Recipient::Interface), // The request is outband and uses HID specific features tergeting an interface + 0x09, 0x0301, 0, // We want to send a SET_REPORT request, that is a custom feature, with the feature being lighting, we want to send it to endpoint 0 + &[row, col, r, g, b, a], std::time::Duration::from_secs(1)) { // First we send the row, then the column, then the Red, Green, Blue, and lastly the brightness + 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(); + } + } +} + +// UI Code fn build_ui(app: &Application) { let config: KeyboardConfig = parse_config(&Path::new("numpad_config.json")); @@ -157,16 +199,15 @@ fn build_ui(app: &Application) { .max_children_per_line(config.layout.cols.into()) .build(); - let color_chooser = gtk::ColorChooserWidget::builder() - .build(); - for i in 0..config.layout.keys.len() { let button = Button::builder() .label(&config.layout.keys[i]) .focusable(true) .build(); - button.connect_clicked(move |button| { + let cols = Rc::new(Cell::new(config.lighting.cols)); + let rows = Rc::new(Cell::new(config.lighting.rows)); + button.connect_clicked(clone!(@strong cols, @strong rows => move |button| { let color = gtk::ColorChooserDialog::builder() .default_width(400) .default_height(200) @@ -184,33 +225,38 @@ fn build_ui(app: &Application) { println!("{}", color.rgba()); }); - println!("My button label is {:?}", button.label()); - color.connect_response(move |color, response| { - println!("The user responded to the window with response type {}", response); - println!("{}", color.rgba()); + let num = Rc::new(Cell::new(i)); + color.connect_response(clone!(@strong num, @strong cols, @strong rows => move |color, response| { + println!("The user responded to the window with as cresponse type {}", response); + + if response == gtk::ResponseType::Ok { + let red = color.rgba().red()*255f32; + let green = color.rgba().green()*255f32; + let blue = color.rgba().blue()*255f32; + let alpha = color.rgba().alpha()*255f32; + + let keys_per_row = cols.get(); + let row = (num.get() as f32 / keys_per_row as f32).floor(); + let col = num.get() as f32 - row*keys_per_row as f32; + + println!("i: {}, row: {}, col: {}, red: {}, green: {}, blue: {}, alpha: {}", i, row, col, red as u8, green as u8, blue as u8, alpha as u8); + send_lighting_update(row as u8, col as u8, red as u8, green as u8, blue as u8, alpha as u8); + } color.destroy(); - }); + })); println!("The label of the button is {}", button.label().unwrap()); - }); + })); flow_box.insert(&button, i.try_into().unwrap()); } - - let paned = gtk::Paned::builder() - .orientation(gtk::Orientation::Horizontal) - .start_child(&flow_box) - .end_child(&color_chooser) - .resize_end_child(false) - .build(); - let window = ApplicationWindow::builder() .application(app) .title("Keyboard Control Software") .default_width(1024) .default_height(900) - .child(&paned) + .child(&flow_box) .build(); window.present();