vitaly 0.1.32

VIA/Vial API client and cli tool for guiless keyboard configuration.
Documentation
use crate::common;
use crate::keymap;
use crate::protocol;
use anyhow::Result;
use crossterm::cursor;
use hidapi::{DeviceInfo, HidApi};
use std::collections::HashMap;
use std::io;
use std::io::Write;
use std::{thread, time};

pub fn run(api: &HidApi, device: &DeviceInfo, unlock: bool, lock: bool) -> Result<()> {
    let device_path = device.path();
    let dev = api.open_path(device_path)?;
    let capabilities = protocol::scan_capabilities(&dev)?;
    let meta = common::load_meta(&dev, &capabilities, &None)?;
    if capabilities.vial_version == 0 {
        println!("Device doesn't support locking");
    } else {
        let mut status = protocol::get_locked_status(&dev)?;
        // println!("{:?}", status);
        println!("Device is locked: {}", status.locked);
        if status.locked && unlock {
            println!("Starting unlock process... ");
            println!("Push marked buttons and keep then pushed to unlock...");
            let layout_options = &meta["layouts"]["labels"];
            let state = protocol::load_layout_options(&dev)?;
            let options = protocol::LayoutOptions::from_json(state, layout_options)?;
            let mut buttons = keymap::keymap_to_buttons(&meta["layouts"]["keymap"], &options)?;
            let mut button_labels = HashMap::new();
            for (row, col) in &status.unlock_buttons {
                button_labels.insert((*row, *col), "☆☆,☆☆".to_string());
            }
            for button in &mut buttons {
                button.color = if status
                    .unlock_buttons
                    .contains(&(button.wire_x, button.wire_y))
                {
                    Some((255, 255, 255))
                } else {
                    None
                };
            }
            keymap::render_and_dump(&buttons, Some(button_labels));
            if !status.unlock_in_progress {
                protocol::start_unlock(&dev)?;
            }
            let sleep_duration = time::Duration::from_millis(100);
            let mut unlocked = false;
            let mut polls_remaining: u8;
            while !unlocked {
                thread::sleep(sleep_duration);
                (unlocked, polls_remaining) = protocol::unlock_poll(&dev)?;
                print!("{}", cursor::MoveToColumn(0));
                print!(
                    "Seconds remaining: {} keep pushing...",
                    (polls_remaining as f64) / 10.0
                );
                io::stdout().flush()?;
            }
            status = protocol::get_locked_status(&dev)?;
            println!("\nDevice is locked: {}", status.locked);
        } else if !status.locked && lock {
            println!("Locking keyboard...");
            protocol::set_locked(&dev)?;
            status = protocol::get_locked_status(&dev)?;
            println!("Device is locked: {}", status.locked);
        }
    }

    Ok(())
}