use std::{
sync::{
mpsc::{self, channel, Sender},
Arc, Mutex, RwLock
},
thread
};
use std::time::Duration;
use std::collections::HashMap;
use hidapi::HidApi;
use windows::Win32::UI::Input::*;
use json::JsonValue;
use lazy_static::lazy_static;
mod raw_input_api;
use raw_input_api::*;
use crate::{Device, Handler, Types};
lazy_static! {
static ref LISTEN_DEVICE_VEC :Arc<Mutex<HashMap<isize, Sender<(RAWKEYBOARD, bool)>>>> = Arc::new(Mutex::new(HashMap::new()));
static ref CONNECT_DEVICE_VEC:Arc<RwLock<Vec<String>>> = Arc::new(RwLock::new(Vec::new()));
}
#[derive(Clone)]
pub struct Win { }
impl Default for Win {
fn default() -> Self {
Self::new()
}
}
impl Win {
pub fn new() -> Self {
log::debug!("New win instance");
Self {}
}
pub fn run<F>(&self, factory: F)
where
F: FnOnce() -> Box<dyn Handler>,
{
start_raw_input_task();
let mut buf = vec![];
log::debug!("hidapi scan loop");
let mut handler = factory();
loop {
let hidapi = match HidApi::new() {
Ok(v) => v,
Err(e) => {
log::warn!("HidApi::new() failed: {:?}", e);
continue;
}
};
log::trace!("Iterator hidapi device list");
let mut recent_device_vec = vec![];
for device in hidapi.device_list() {
let usage = device.usage();
let usage_page = device.usage_page();
if usage != 6 || usage_page != 1 {
continue;
}
let uid = get_uid_from_device_info(&device);
recent_device_vec.push(uid.clone());
if !buf.contains(&uid) {
let raw_path = device.path().to_string_lossy().to_string();
log::debug!(
"Found device prod: {}, {}\nraw_path: {}, uid: {}",
device.product_string().unwrap(),
device.manufacturer_string().unwrap(),
raw_path,
uid,
);
buf.push(uid.clone());
}
let r = Device {
id: uid,
vid: device.vendor_id().to_string(),
pid: device.product_id().to_string(),
types: Types::Keyboard,
manufacturer: device.manufacturer_string().unwrap().trim().to_string(),
name: device.product_string().unwrap().trim().to_string(),
value: JsonValue::from("".to_string()),
count: 0,
};
handler.on_discover(r);
}
{
let r = CONNECT_DEVICE_VEC.read().unwrap();
if *r != recent_device_vec {
drop(r);
log::debug!("Update CONNECT_DEVICE_VEC");
let mut w = CONNECT_DEVICE_VEC.write().unwrap();
w.drain(..);
w.extend(recent_device_vec);
drop(w);
}
}
thread::sleep(Duration::from_secs(3));
}
}
pub fn connect<F>(&self, id: String, factory: F)
where
F: FnOnce() -> Box<dyn Handler>,
{
let device_handle_0 = match get_device_handle_0(&id){
Some(v) => v,
None => {
log::info!("Connect reqeust device not found: {}", id);
factory().on_disconnected(id, "未找到设备".to_string());
return;
}
};
let (tx, rx) = channel();
log::info!("Register detect device: h: {}, id: {}", device_handle_0, id);
let mut w = LISTEN_DEVICE_VEC.lock().unwrap();
w.insert(device_handle_0, tx);
let mut handler = factory();
drop(w);
handler.on_connect(id.clone());
let mut cache = String::with_capacity(32);
loop {
match rx.recv_timeout(Duration::from_millis(1000)) {
Ok(raw_keyboard) => {
let digit_str = raw_keyboard_to_digit_str(raw_keyboard.0, raw_keyboard.1);
log::trace!("Recv raw input str: id: {}, digit: {}", id, digit_str);
if digit_str == "\n" || digit_str == "\t" {
if !cache.is_empty() {
handler.on_data(id.clone(), cache.clone().into());
}
cache.clear();
} else {
cache = format!("{cache}{}", digit_str);
}
},
Err(mpsc::RecvTimeoutError::Timeout) => {
if handler.on_is_close(id.clone()) {
log::debug!("on_is_close");
handler.on_disconnected(id.clone(), "软件主动断开连接".to_string());
break;
}
let r = CONNECT_DEVICE_VEC.read().unwrap();
if !r.contains(&id){
log::debug!("Device not found in device list");
handler.on_disconnected(id.clone(), "设备已从连接列表中消失".to_string());
drop(r);
break;
}
},
Err(mpsc::RecvTimeoutError::Disconnected) => {
log::warn!("Channel disconnect");
handler.on_disconnected(id.clone(), "设备已断开".to_string());
break;
},
}
}
log::debug!("Connect message loop out: {} {}", device_handle_0, id);
let mut w = LISTEN_DEVICE_VEC.lock().unwrap();
w.remove(&device_handle_0);
drop(w);
}
}