From aa82959c90b17a14bda6459e0df1882f87a5da10 Mon Sep 17 00:00:00 2001 From: Artem Egorkine Date: Mon, 28 Oct 2024 00:01:34 +0200 Subject: [PATCH] USB: show enumeration errors in USB device list To make using USB devices easier (to make debugging USB problems easier), it is better not to hide devices that fail USB enumeration (USB device open fail, USB device init fail), but to show the actual error message whenever the enumeration is listed: in the help text and in the settings dialog drop-downs. --- gui/src/opts.rs | 5 +++-- gui/src/settings.rs | 7 ++++--- gui/src/usb.rs | 4 ++-- usb/src/dev_handler.rs | 1 + usb/src/lib.rs | 28 ++++++++++++++++++---------- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/gui/src/opts.rs b/gui/src/opts.rs index 91e5d92..5f2a320 100644 --- a/gui/src/opts.rs +++ b/gui/src/opts.rs @@ -81,8 +81,9 @@ pub fn generate_help_text() -> Result { if cfg!(feature = "usb") { writeln!(s, "USB devices (-u):")?; - for (i, n) in usb_list_devices().iter().enumerate() { - writeln!(s, "{}[{}] {}", tab, i, n)?; + for (i, (n, is_ok)) in usb_list_devices().iter().enumerate() { + let prefix = if *is_ok { "" } else { "ERROR: " }; + writeln!(s, "{}[{}] {}{}", tab, i, prefix, n)?; } writeln!(s, "")?; } diff --git a/gui/src/settings.rs b/gui/src/settings.rs index bb7b508..40d0d64 100644 --- a/gui/src/settings.rs +++ b/gui/src/settings.rs @@ -205,7 +205,7 @@ fn populate_midi_channel_combo(settings: &SettingsDialog) { CHANNELS.iter().for_each(|i| settings.midi_channel_combo.append_text(i)); } -fn combo_model_populate(model: >k::ListStore, midi_devices: &Vec, usb_devices: &Vec) { +fn combo_model_populate(model: >k::ListStore, midi_devices: &Vec, usb_devices: &Vec<(String, bool)>) { model.clear(); let mut n: u32 = 0; @@ -227,8 +227,9 @@ fn combo_model_populate(model: >k::ListStore, midi_devices: &Vec, usb_ add("USB", EntryFlags::ENTRY_HEADER); if !usb_devices.is_empty() { - for name in usb_devices { - add(name, EntryFlags::ENTRY_USB); + for (name, is_ok) in usb_devices { + let flag = if *is_ok { EntryFlags::empty() } else { EntryFlags::ENTRY_TEXT }; + add(name, EntryFlags::ENTRY_USB | flag); } } else { add("No devices found...", EntryFlags::ENTRY_TEXT); diff --git a/gui/src/usb.rs b/gui/src/usb.rs index 8cf0f40..861591f 100644 --- a/gui/src/usb.rs +++ b/gui/src/usb.rs @@ -20,7 +20,7 @@ mod imp { ); } - pub fn usb_list_devices() -> Vec { + pub fn usb_list_devices() -> Vec<(String, bool)> { pod_usb::usb_list_devices() } @@ -41,7 +41,7 @@ mod nop { fn start_usb() { } - fn usb_list_devices() -> Vec { + fn usb_list_devices() -> Vec<(String, bool)> { vec![] } diff --git a/usb/src/dev_handler.rs b/usb/src/dev_handler.rs index 149b3a8..21fc050 100644 --- a/usb/src/dev_handler.rs +++ b/usb/src/dev_handler.rs @@ -17,6 +17,7 @@ use crate::podxt_framer::new_pod_xt_framer; use crate::usb::{DeviceHandle, SubmittedTransfer, Transfer, TransferCommand}; use crate::util::usb_address_string; +#[derive(Clone)] pub struct Device { pub name: String, handle: Arc, diff --git a/usb/src/lib.rs b/usb/src/lib.rs index 60ac730..68cc0cb 100644 --- a/usb/src/lib.rs +++ b/usb/src/lib.rs @@ -91,6 +91,10 @@ enum UsbFoundDevice { Found(DeviceAddedEvent), Open(Device) } +enum UsbEnumeratedDevice { + Device(Device), + Error(String) +} static mut INIT_DONE: AtomicBool = AtomicBool::new(false); static INIT_DONE_NOTIFY: Lazy> = Lazy::new(|| { @@ -177,7 +181,7 @@ pub async fn usb_init_wait() { debug!("Waiting for USB init over"); } -fn usb_enumerate_devices(devices: &mut HashMap) -> Vec<&mut Device> { +fn usb_enumerate_devices(devices: &mut HashMap) -> Vec { let Some(usb) = USB.get() else { error!("Cannot enumerate USB: usb not ready!"); return vec![]; @@ -186,6 +190,7 @@ fn usb_enumerate_devices(devices: &mut HashMap) -> Vec<& info!("Enumerating USB devices..."); let mut update = HashMap::new(); + let mut enumerated = Vec::with_capacity(devices.len()); for (key, value) in devices.iter() { match value { &UsbFoundDevice::Found(DeviceAddedEvent { vid, pid, bus, address }) => { @@ -194,6 +199,7 @@ fn usb_enumerate_devices(devices: &mut HashMap) -> Vec<& Ok(h) => { h } Err(e) => { error!("Failed to open device: {}", e); + enumerated.push(UsbEnumeratedDevice::Error(e.to_string())); continue } }; @@ -201,13 +207,16 @@ fn usb_enumerate_devices(devices: &mut HashMap) -> Vec<& Ok(h) => { h } Err(e) => { error!("Filed to initialize device {:?}: {}", usb_dev.name, e); + enumerated.push(UsbEnumeratedDevice::Error(format!("Failed to initialize device {:?}: {}", usb_dev.name, e))); continue } }; update.insert(key.clone(), UsbFoundDevice::Open(handler)); } - UsbFoundDevice::Open(_) => {} + UsbFoundDevice::Open(dev) => { + enumerated.push(UsbEnumeratedDevice::Device(dev.clone())) + } } } let updated = update.len(); @@ -215,18 +224,17 @@ fn usb_enumerate_devices(devices: &mut HashMap) -> Vec<& devices.insert(key, value); } info!("Enumerating USB devices finished: {updated} entries updated"); - - devices.values_mut().flat_map(|v| match v { - UsbFoundDevice::Found(_) => { None } - UsbFoundDevice::Open(dev) => { Some(dev) } - }) - .collect() + enumerated } -pub fn usb_list_devices() -> Vec { +pub fn usb_list_devices() -> Vec<(String, bool)> { let mut devices = DEVICES.lock().unwrap(); - usb_enumerate_devices(&mut devices).iter().map(|i| i.name.clone()).collect() + usb_enumerate_devices(&mut devices).iter() + .map(|i| match i { + UsbEnumeratedDevice::Device(dev) => { (dev.name.clone(), true) } + UsbEnumeratedDevice::Error(err) => { (err.clone(), false) } + }).collect() } fn usb_add_device(key: String, event: DeviceAddedEvent) {