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
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,
|
|
})
|
|
}
|