extern crate libusb; use std::time::Duration; struct UsbDevice<'a> { handle: libusb::DeviceHandle<'a>, language: libusb::Language, timeout: Duration } fn main() { list_devices().unwrap(); } fn list_devices() -> libusb::Result<()> { let timeout = Duration::from_secs(1); let context = try!(libusb::Context::new()); for device in try!(context.devices()).iter() { let device_desc = match device.device_descriptor() { Ok(d) => d, Err(_) => continue }; let mut usb_device = { match device.open() { Ok(h) => { match h.read_languages(timeout) { Ok(l) => { if l.len() > 0 { Some(UsbDevice { handle: h, language: l[0], timeout: timeout }) } else { None } }, Err(_) => None } }, Err(_) => None } }; println!("Bus {:03} Device {:03} ID {:04x}:{:04x} {}", device.bus_number(), device.address(), device_desc.vendor_id(), device_desc.product_id(), get_speed(device.speed())); print_device(&device_desc, &mut usb_device); for n in 0..device_desc.num_configurations() { let config_desc = match device.config_descriptor(n) { Ok(c) => c, Err(_) => continue }; print_config(&config_desc, &mut usb_device); for interface in config_desc.interfaces() { for interface_desc in interface.descriptors() { print_interface(&interface_desc, &mut usb_device); for endpoint_desc in interface_desc.endpoint_descriptors() { print_endpoint(&endpoint_desc); } } } } } Ok(()) } fn print_device(device_desc: &libusb::DeviceDescriptor, handle: &mut Option) { println!("Device Descriptor:"); println!(" bcdUSB {:2}.{}{}", device_desc.usb_version().major(), device_desc.usb_version().minor(), device_desc.usb_version().sub_minor()); println!(" bDeviceClass {:#04x}", device_desc.class_code()); println!(" bDeviceSubClass {:#04x}", device_desc.sub_class_code()); println!(" bDeviceProtocol {:#04x}", device_desc.protocol_code()); println!(" bMaxPacketSize0 {:3}", device_desc.max_packet_size()); println!(" idVendor {:#06x}", device_desc.vendor_id()); println!(" idProduct {:#06x}", device_desc.product_id()); println!(" bcdDevice {:2}.{}{}", device_desc.device_version().major(), device_desc.device_version().minor(), device_desc.device_version().sub_minor()); println!(" iManufacturer {:3} {}", device_desc.manufacturer_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_manufacturer_string(h.language, device_desc, h.timeout).unwrap_or(String::new()))); println!(" iProduct {:3} {}", device_desc.product_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_product_string(h.language, device_desc, h.timeout).unwrap_or(String::new()))); println!(" iSerialNumber {:3} {}", device_desc.serial_number_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_serial_number_string(h.language, device_desc, h.timeout).unwrap_or(String::new()))); println!(" bNumConfigurations {:3}", device_desc.num_configurations()); } fn print_config(config_desc: &libusb::ConfigDescriptor, handle: &mut Option) { println!(" Config Descriptor:"); println!(" bNumInterfaces {:3}", config_desc.num_interfaces()); println!(" bConfigurationValue {:3}", config_desc.number()); println!(" iConfiguration {:3} {}", config_desc.description_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_configuration_string(h.language, config_desc, h.timeout).unwrap_or(String::new()))); println!(" bmAttributes:"); println!(" Self Powered {:>5}", config_desc.self_powered()); println!(" Remote Wakeup {:>5}", config_desc.remote_wakeup()); println!(" bMaxPower {:4}mW", config_desc.max_power()); } fn print_interface(interface_desc: &libusb::InterfaceDescriptor, handle: &mut Option) { println!(" Interface Descriptor:"); println!(" bInterfaceNumber {:3}", interface_desc.interface_number()); println!(" bAlternateSetting {:3}", interface_desc.setting_number()); println!(" bNumEndpoints {:3}", interface_desc.num_endpoints()); println!(" bInterfaceClass {:#04x}", interface_desc.class_code()); println!(" bInterfaceSubClass {:#04x}", interface_desc.sub_class_code()); println!(" bInterfaceProtocol {:#04x}", interface_desc.protocol_code()); println!(" iInterface {:3} {}", interface_desc.description_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_interface_string(h.language, interface_desc, h.timeout).unwrap_or(String::new()))); } fn print_endpoint(endpoint_desc: &libusb::EndpointDescriptor) { println!(" Endpoint Descriptor:"); println!(" bEndpointAddress {:#04x} EP {} {:?}", endpoint_desc.address(), endpoint_desc.number(), endpoint_desc.direction()); println!(" bmAttributes:"); println!(" Transfer Type {:?}", endpoint_desc.transfer_type()); println!(" Synch Type {:?}", endpoint_desc.sync_type()); println!(" Usage Type {:?}", endpoint_desc.usage_type()); println!(" wMaxPacketSize {:#06x}", endpoint_desc.max_packet_size()); println!(" bInterval {:3}", endpoint_desc.interval()); } fn get_speed(speed: libusb::Speed) -> &'static str { match speed { libusb::Speed::Super => "5000 Mbps", libusb::Speed::High => " 480 Mbps", libusb::Speed::Full => " 12 Mbps", libusb::Speed::Low => " 1.5 Mbps", libusb::Speed::Unknown => "(unknown)" } }