Browse Source

优化hid读取方式

caner 1 year ago
parent
commit
8ba88e9ee4
3 changed files with 59 additions and 34 deletions
  1. 6 3
      src-tauri/Cargo.lock
  2. 3 1
      src-tauri/Cargo.toml
  3. 50 30
      src-tauri/src/lib.rs

+ 6 - 3
src-tauri/Cargo.lock

@@ -6,7 +6,9 @@ version = 4
 name = "Control"
 name = "Control"
 version = "0.1.0"
 version = "0.1.0"
 dependencies = [
 dependencies = [
+ "hex",
  "hidapi",
  "hidapi",
+ "lazy_static",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
  "tauri",
  "tauri",
@@ -1304,14 +1306,15 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
 
 [[package]]
 [[package]]
 name = "hidapi"
 name = "hidapi"
-version = "1.5.0"
+version = "2.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "798154e4b6570af74899d71155fb0072d5b17e6aa12f39c8ef22c60fb8ec99e7"
+checksum = "03b876ecf37e86b359573c16c8366bc3eba52b689884a0fc42ba3f67203d2a8b"
 dependencies = [
 dependencies = [
  "cc",
  "cc",
+ "cfg-if",
  "libc",
  "libc",
  "pkg-config",
  "pkg-config",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 ]
 
 
 [[package]]
 [[package]]

+ 3 - 1
src-tauri/Cargo.toml

@@ -23,4 +23,6 @@ serde = { version = "1", features = ["derive"] }
 serde_json = "1"
 serde_json = "1"
 tauri-plugin-mqtt = "0.1.1"
 tauri-plugin-mqtt = "0.1.1"
 tauri-plugin-shell = "2"
 tauri-plugin-shell = "2"
-hidapi = "1.3"
+hidapi = "2.0.0"
+lazy_static = "1.4.0"
+hex = "0.4.3"

+ 50 - 30
src-tauri/src/lib.rs

@@ -1,53 +1,69 @@
 use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
 use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
 use std::thread;
 use std::thread;
-use std::time::Duration;
 use hidapi::HidApi;
 use hidapi::HidApi;
 use tauri::{Emitter,Window};
 use tauri::{Emitter,Window};
-static STOP_SIGNAL: AtomicBool = AtomicBool::new(false);
+// 全局停止标志和线程句柄
+lazy_static::lazy_static! {
+    static ref STOP_SIGNAL: AtomicBool = AtomicBool::new(false);
+    static ref THREAD_HANDLE: Mutex<Option<thread::JoinHandle<()>>> = Mutex::new(None);
+}
+// G923设备标识
+const LOGITECH_VID: u16 = 0x046D;  // 罗技厂商ID
+const G923_PIDS: &[u16] = &[
+    0xC262,  // G923 PlayStation
+    0xC267,  // G923 Xbox
+    0xC266,  // G920(兼容检查)
+];
 
 
 // 读取G923数据
 // 读取G923数据
 #[tauri::command]
 #[tauri::command]
 fn start_reading_data(window: Window) -> Result<(), String> {
 fn start_reading_data(window: Window) -> Result<(), String> {
-    // 重置标志位
-    STOP_SIGNAL.store(false, Ordering::SeqCst);
-    // 初始化 HidApi
-    let api_result = HidApi::new();
-    if let Err(_e) = api_result {
-        return Err("HID设备初始化失败".to_string());
-    }
-    let api = Arc::new(Mutex::new(api_result.unwrap()));
-    // 打开 G923 设备
-    let device_result = api.lock().unwrap().open(0x046D, 0xC267);
-    if let Err(_e) = device_result {
-        return Err("请连接-G923-方向盘".to_string());
-    }
-    let device = Arc::new(Mutex::new(device_result.unwrap()));
-    // 启动一个线程持续读取数据
-    thread::spawn(move || {
-        let mut buf = [0u8; 64]; // HID 设备通常使用 64 字节的缓冲区
+    // 停止现有线程
+    stop_reading_data();
+    // 初始化HID API
+    let api = HidApi::new().map_err(|_| "HID设备初始化失败".to_string())?;
+    // 自动检测设备
+    let device_info = api.device_list().find(|d| d.vendor_id() == LOGITECH_VID && G923_PIDS.contains(&d.product_id())).ok_or("未找到G923方向盘")?;
+    // 打印检测到的设备信息
+    println!("找到G923设备: VID:{:04X} PID:{:04X}", 
+        device_info.vendor_id(), 
+        device_info.product_id());
+    // 打开设备
+    let device = device_info.open_device(&api).map_err(|e| format!("无法打开设备: {}", e))?;
+    // 克隆Arc用于线程
+    let device = Arc::new(Mutex::new(device));
+    let thread_device = Arc::clone(&device);
+    let thread_window = window.clone();
+    // 启动读取线程
+    let handle = thread::spawn(move || {
+        let mut buf = [0u8; 64];
         loop {
         loop {
-            // 检查标志位,如果为 true,则退出线程
+            // 检查停止标志
             if STOP_SIGNAL.load(Ordering::SeqCst) {
             if STOP_SIGNAL.load(Ordering::SeqCst) {
-                println!("线程已退出并关闭设备");
-                drop(device.lock().unwrap());
+                println!("停止读取线程");
                 break;
                 break;
             }
             }
-            let res = match device.lock().unwrap().read(&mut buf) {
-                Ok(res) => res,
+
+            // 使用带超时的读取(100ms)
+            let res = match thread_device.lock().unwrap().read_timeout(&mut buf, 100) {
+                Ok(n) => n,
                 Err(e) => {
                 Err(e) => {
                     eprintln!("读取数据失败: {}", e);
                     eprintln!("读取数据失败: {}", e);
                     continue;
                     continue;
                 }
                 }
             };
             };
+
+            // 处理&发送数据
             let data = &buf[..res];
             let data = &buf[..res];
-            // 将数据发送到前端
-            if let Err(e) = window.emit("g923-data", format!("{:?}", data)) {
-                eprintln!("发送数据到前端失败: {}", e);
-            }
-            // 休眠一段时间(例如 10ms)
-            thread::sleep(Duration::from_millis(10));
+            let _ = thread_window.emit("g923-data", format!("{:?}", data));
         }
         }
+
+        // 关闭设备
+        drop(thread_device.lock().unwrap());
     });
     });
+    // 存储线程句柄
+    *THREAD_HANDLE.lock().unwrap() = Some(handle);
+    // return
     Ok(())
     Ok(())
 }
 }
 
 
@@ -55,6 +71,10 @@ fn start_reading_data(window: Window) -> Result<(), String> {
 #[tauri::command]
 #[tauri::command]
 fn stop_reading_data() {
 fn stop_reading_data() {
     STOP_SIGNAL.store(true, Ordering::SeqCst);
     STOP_SIGNAL.store(true, Ordering::SeqCst);
+    if let Some(handle) = THREAD_HANDLE.lock().unwrap().take() {
+       let _ = handle.join().map_err(|_| "无法等待线程退出".to_string());
+    }
+    STOP_SIGNAL.store(false, Ordering::SeqCst);
 }
 }
 
 
 pub fn run() {
 pub fn run() {