You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.7 KiB
Rust

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<USBDetails>,
}
#[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<libusb::Error> for USBError {
fn from(_e: libusb::Error) -> Self {
USBError {
err: "Error in accessing USB device".to_string(),
}
}
}
impl From<std::io::Error> 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<USBDetails, USBError> {
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,
})
}