Skip to content

Commit

Permalink
USB: show enumeration errors in USB device list
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
arteme committed Oct 27, 2024
1 parent f09f487 commit aa82959
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 17 deletions.
5 changes: 3 additions & 2 deletions gui/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ pub fn generate_help_text() -> Result<String> {

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, "")?;
}
Expand Down
7 changes: 4 additions & 3 deletions gui/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: &gtk::ListStore, midi_devices: &Vec<String>, usb_devices: &Vec<String>) {
fn combo_model_populate(model: &gtk::ListStore, midi_devices: &Vec<String>, usb_devices: &Vec<(String, bool)>) {
model.clear();

let mut n: u32 = 0;
Expand All @@ -227,8 +227,9 @@ fn combo_model_populate(model: &gtk::ListStore, midi_devices: &Vec<String>, 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);
Expand Down
4 changes: 2 additions & 2 deletions gui/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod imp {
);
}

pub fn usb_list_devices() -> Vec<String> {
pub fn usb_list_devices() -> Vec<(String, bool)> {
pod_usb::usb_list_devices()
}

Expand All @@ -41,7 +41,7 @@ mod nop {
fn start_usb() {
}

fn usb_list_devices() -> Vec<String> {
fn usb_list_devices() -> Vec<(String, bool)> {
vec![]
}

Expand Down
1 change: 1 addition & 0 deletions usb/src/dev_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DeviceHandle>,
Expand Down
28 changes: 18 additions & 10 deletions usb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Arc<Notify>> = Lazy::new(|| {
Expand Down Expand Up @@ -177,7 +181,7 @@ pub async fn usb_init_wait() {
debug!("Waiting for USB init over");
}

fn usb_enumerate_devices(devices: &mut HashMap<String, UsbFoundDevice>) -> Vec<&mut Device> {
fn usb_enumerate_devices(devices: &mut HashMap<String, UsbFoundDevice>) -> Vec<UsbEnumeratedDevice> {
let Some(usb) = USB.get() else {
error!("Cannot enumerate USB: usb not ready!");
return vec![];
Expand All @@ -186,6 +190,7 @@ fn usb_enumerate_devices(devices: &mut HashMap<String, UsbFoundDevice>) -> 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 }) => {
Expand All @@ -194,39 +199,42 @@ fn usb_enumerate_devices(devices: &mut HashMap<String, UsbFoundDevice>) -> Vec<&
Ok(h) => { h }
Err(e) => {
error!("Failed to open device: {}", e);
enumerated.push(UsbEnumeratedDevice::Error(e.to_string()));
continue
}
};
let handler = match Device::new(h, usb_dev) {
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();
for (key, value) in update {
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<String> {
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) {
Expand Down

0 comments on commit aa82959

Please sign in to comment.