use libusb::{Context, Device, DeviceHandle}; use std::fs::File; use std::io::Write; use std::result::Result; use std::time::Duration; use std::fmt; #[derive(Debug)] struct USBError { err: String, } struct USBList { list: Vec, } #[derive(Debug)] struct USBDetails { manufacturer: String, product: String, serial_number: String, bus_number: u8, device_address: u8, vendor_id: u16, product_id: u16, maj_device_version: u8, min_device_version: u8, } impl fmt::Display for USBList { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(for usb in &self.list { writeln!(f, "\nUSB Device details")?; writeln!(f, "Manufacturer: {}", usb.manufacturer)?; writeln!(f, "Product: {}", usb.product)?; writeln!(f, "Serial number: {}", usb.serial_number)?; writeln!(f, "Bus number: {}", usb.bus_number)?; writeln!(f, "Device address: {}", usb.device_address)?; writeln!(f, "Vendor Id: {}", usb.vendor_id)?; writeln!(f, "Product Id: {}", usb.product_id)?; writeln!(f, "Major device version: {}", usb.maj_device_version)?; writeln!(f, "Minor device version: {}", usb.min_device_version)?; }) } } impl From for USBError { fn from(_e: libusb::Error) -> Self { USBError { err: "Error in accessing USB device".to_string(), } } } impl From for USBError { fn from(e: std::io::Error) -> Self { USBError { err: e.to_string() } } } fn main() -> Result<(), USBError> { // Get libusb context let context = Context::new()?; //Get list of devices let mut device_list = USBList { list: vec![] }; for device in context.devices()?.iter() { let device_desc = device.device_descriptor()?; let device_handle = context .open_device_with_vid_pid(device_desc.vendor_id(), device_desc.product_id()) .unwrap(); // For each USB device, get the information let usb_details = get_device_information(device, &device_handle)?; device_list.list.push(usb_details); } println!("\n{}", device_list); write_to_file(device_list)?; Ok(()) } //Function to write details to output file fn write_to_file(usb: USBList) -> Result<(), USBError> { let mut file_handle = File::create("usb_details.txt")?; write!(file_handle, "{}\n", usb)?; Ok(()) } // Function to print device information fn get_device_information(device: Device, handle: &DeviceHandle) -> Result { let device_descriptor = device.device_descriptor()?; let timeout = Duration::from_secs(1); let languages = handle.read_languages(timeout)?; let language = languages[0]; // Get device manufacturer name let manufacturer = handle.read_manufacturer_string(language, &device_descriptor, timeout)?; // Get device USB product name let product = handle.read_product_string(language, &device_descriptor, timeout)?; //Get product serial number let product_serial_number = match handle.read_serial_number_string(language, &device_descriptor, timeout) { Ok(s) => s, Err(_) => "Not available".into(), }; // Populate the USBDetails struct Ok(USBDetails { manufacturer, product, serial_number: product_serial_number, bus_number: device.bus_number(), device_address: device.address(), vendor_id: device_descriptor.vendor_id(), product_id: device_descriptor.product_id(), maj_device_version: device_descriptor.device_version().0, min_device_version: device_descriptor.device_version().1, }) }