diff --git a/src/device.rs b/src/device.rs index d9e94d3..8dad19c 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,5 +1,5 @@ use hidapi::{DeviceInfo, HidApi, HidError}; -use log::{error, info, warn}; // Use log crate +use log::{error, info, warn, debug, trace}; // Use log crate use serde::{Deserialize, Serialize}; use std::rc::Rc; // Keep Rc for potential sharing within UI if needed @@ -98,7 +98,7 @@ pub(crate) fn find_device_index_for_saved( impl crate::ShiftTool { /// Refreshes the internal list of available HID devices. pub(crate) fn refresh_devices(&mut self) { - info!("Refreshing device list..."); + trace!("Refreshing device list..."); match HidApi::new() { Ok(hidapi) => { let mut current_devices: Vec = Vec::new(); @@ -126,7 +126,7 @@ impl crate::ShiftTool { if crate::util::is_supported( vpc_device.firmware.to_string(), ) { - info!("Found supported device: {}", vpc_device); + debug!("Found supported device: {}", vpc_device); current_devices.push(vpc_device); } else { warn!( @@ -153,7 +153,7 @@ impl crate::ShiftTool { // Update the app's device list self.device_list = current_devices; - info!( + debug!( "Device list refresh complete. Found {} unique devices.", self.device_list.len() - 1 // Exclude default entry ); @@ -200,29 +200,26 @@ impl crate::ShiftTool { /// Checks if saved source/receiver devices still exist in the refreshed list. /// Resets the config entry to default if the device is gone. fn validate_selected_devices(&mut self) { - let mut changed = false; for i in 0..self.config.data.sources.len() { - let idx = self.find_source_device_index(i); + let idx = self.find_device_index_for_saved(&self.config.data.sources[i]); + // Check if device *was* configured but is *not* found (idx 0 is default/not found) if idx == 0 && (self.config.data.sources[i].vendor_id != 0 || self.config.data.sources[i].product_id != 0) { - warn!("Previously selected source device {} not found after refresh. Resetting.", i + 1); - self.config.data.sources[i] = SavedDevice::default(); - changed = true; + // Log that the configured device is currently missing, but DO NOT reset config + warn!( + "validate_selected_devices: Configured source device {} (VID={:04X}, PID={:04X}) not found in refreshed list. Keeping configuration.", + i + 1, self.config.data.sources[i].vendor_id, self.config.data.sources[i].product_id + ); } } for i in 0..self.config.data.receivers.len() { - let idx = self.find_receiver_device_index(i); + let idx = self.find_device_index_for_saved(&self.config.data.receivers[i]); if idx == 0 && (self.config.data.receivers[i].vendor_id != 0 || self.config.data.receivers[i].product_id != 0) { - warn!("Previously selected receiver device {} not found after refresh. Resetting.", i + 1); - self.config.data.receivers[i] = SavedDevice::default(); - changed = true; + warn!( + "validate_selected_devices: Configured receiver device {} (VID={:04X}, PID={:04X}) not found in refreshed list. Keeping configuration.", + i + 1, self.config.data.receivers[i].vendor_id, self.config.data.receivers[i].product_id + ); } } - if changed { - // Optionally save the config immediately after validation changes - // if let Err(e) = self.config.save() { - // error!("Failed to save config after device validation: {}", e); - // } - } } } diff --git a/src/hid_worker.rs b/src/hid_worker.rs index 590b82b..417f8f6 100644 --- a/src/hid_worker.rs +++ b/src/hid_worker.rs @@ -264,11 +264,8 @@ fn run_hid_worker_loop(hidapi: HidApi, data: WorkerData) { } // --- Write to Receiver Devices --- - // We need to determine the correct length to send. Assuming report 4 is always ID + 2 bytes. - const bytes_to_send: usize = 19; // Report ID (1) + Data (2) - - let zero_buffer: [u8; bytes_to_send] = { - let mut buf = [0u8; bytes_to_send]; + let zero_buffer: [u8; REPORT_BUFFER_SIZE] = { + let mut buf = [0u8; REPORT_BUFFER_SIZE]; buf[0] = FEATURE_REPORT_ID; // Set Report ID 4 // All other bytes (1-18) remain 0 for the zero state buf @@ -322,7 +319,7 @@ fn run_hid_worker_loop(hidapi: HidApi, data: WorkerData) { // Send the potentially filtered feature report - match device.send_feature_report(&filtered_write_buffer[0..bytes_to_send]) { + match device.send_feature_report(&filtered_write_buffer[0..REPORT_BUFFER_SIZE]) { Ok(_) => { log::debug!("Worker: Send to receiver[{}] successful.", i); // Successfully sent. Update UI state for this receiver. @@ -392,8 +389,13 @@ fn run_hid_worker_loop(hidapi: HidApi, data: WorkerData) { // --- Cleanup before thread exit --- log::info!("Worker loop finished. Performing cleanup..."); - // Optionally send a 'zero' report to all devices on exit - let cleanup_buffer: [u8; 3] = [FEATURE_REPORT_ID, 0, 0]; + // Send a 'zero' report to all devices on exit + let cleanup_buffer: [u8; REPORT_BUFFER_SIZE] = { + let mut buf = [0u8; REPORT_BUFFER_SIZE]; + buf[0] = FEATURE_REPORT_ID; // Set Report ID 4 + // All other bytes (1-18) remain 0 for the zero state + buf + }; for device_opt in source_devices.iter_mut().chain(receiver_devices.iter_mut()) { if let Some(device) = device_opt { if let Err(e) = device.send_feature_report(&cleanup_buffer) { diff --git a/src/ui.rs b/src/ui.rs index 6dc4775..6356630 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -194,7 +194,7 @@ fn draw_sources_section( // Pass mutable borrow of state_enabled part of source_config draw_status_bits( ui, - "Shift:", + " Shift:", state_val, &mut source_config.state_enabled, vid, @@ -312,7 +312,7 @@ fn draw_receivers_section( }; draw_status_bits( ui, - "Shift:", + " Shift:", state_val, &mut receiver_config.state_enabled, // Pass mut borrow vid, @@ -550,6 +550,11 @@ fn draw_control_buttons( // } // } + if ui.add_enabled(!thread_running, egui::Button::new("Refresh Devices")).clicked() { + log::info!("Refreshing device list manually."); + app.refresh_devices(); + } + if ui.button("About").clicked() { app.state = State::About; }