1 use rusb::{
2 ConfigDescriptor, DeviceDescriptor, DeviceHandle, DeviceList, EndpointDescriptor,
3 InterfaceDescriptor, Language, Result, Speed, UsbContext,
4 };
5 use std::time::Duration;
6
7 use usb_ids::{self, FromId};
8
9 struct UsbDevice<T: UsbContext> {
10 handle: DeviceHandle<T>,
11 language: Language,
12 timeout: Duration,
13 }
14
main()15 fn main() {
16 list_devices().unwrap();
17 }
18
list_devices() -> Result<()>19 fn list_devices() -> Result<()> {
20 let timeout = Duration::from_secs(1);
21
22 for device in DeviceList::new()?.iter() {
23 let device_desc = match device.device_descriptor() {
24 Ok(d) => d,
25 Err(_) => continue,
26 };
27
28 let mut usb_device = {
29 match device.open() {
30 Ok(h) => match h.read_languages(timeout) {
31 Ok(l) => {
32 if !l.is_empty() {
33 Some(UsbDevice {
34 handle: h,
35 language: l[0],
36 timeout,
37 })
38 } else {
39 None
40 }
41 }
42 Err(_) => None,
43 },
44 Err(_) => None,
45 }
46 };
47
48 println!(
49 "Bus {:03} Device {:03} ID {:04x}:{:04x} {}",
50 device.bus_number(),
51 device.address(),
52 device_desc.vendor_id(),
53 device_desc.product_id(),
54 get_speed(device.speed())
55 );
56 print_device(&device_desc, &mut usb_device);
57
58 for n in 0..device_desc.num_configurations() {
59 let config_desc = match device.config_descriptor(n) {
60 Ok(c) => c,
61 Err(_) => continue,
62 };
63
64 print_config(&config_desc, &mut usb_device);
65
66 for interface in config_desc.interfaces() {
67 for interface_desc in interface.descriptors() {
68 print_interface(&interface_desc, &mut usb_device);
69
70 for endpoint_desc in interface_desc.endpoint_descriptors() {
71 print_endpoint(&endpoint_desc);
72 }
73 }
74 }
75 }
76 }
77
78 Ok(())
79 }
80
print_device<T: UsbContext>(device_desc: &DeviceDescriptor, handle: &mut Option<UsbDevice<T>>)81 fn print_device<T: UsbContext>(device_desc: &DeviceDescriptor, handle: &mut Option<UsbDevice<T>>) {
82 let vid = device_desc.vendor_id();
83 let pid = device_desc.product_id();
84
85 let vendor_name = match usb_ids::Vendor::from_id(device_desc.vendor_id()) {
86 Some(vendor) => vendor.name(),
87 None => "Unknown vendor",
88 };
89
90 let product_name =
91 match usb_ids::Device::from_vid_pid(device_desc.vendor_id(), device_desc.product_id()) {
92 Some(product) => product.name(),
93 None => "Unknown product",
94 };
95
96 println!("Device Descriptor:");
97 println!(" bLength {:3}", device_desc.length());
98 println!(" bDescriptorType {:3}", device_desc.descriptor_type());
99 println!(
100 " bcdUSB {:2}.{}{}",
101 device_desc.usb_version().major(),
102 device_desc.usb_version().minor(),
103 device_desc.usb_version().sub_minor()
104 );
105 println!(" bDeviceClass {:#04x}", device_desc.class_code());
106 println!(
107 " bDeviceSubClass {:#04x}",
108 device_desc.sub_class_code()
109 );
110 println!(" bDeviceProtocol {:#04x}", device_desc.protocol_code());
111 println!(" bMaxPacketSize0 {:3}", device_desc.max_packet_size());
112 println!(" idVendor {vid:#06x} {vendor_name}",);
113 println!(" idProduct {pid:#06x} {product_name}",);
114 println!(
115 " bcdDevice {:2}.{}{}",
116 device_desc.device_version().major(),
117 device_desc.device_version().minor(),
118 device_desc.device_version().sub_minor()
119 );
120 println!(
121 " iManufacturer {:3} {}",
122 device_desc.manufacturer_string_index().unwrap_or(0),
123 handle.as_mut().map_or(String::new(), |h| h
124 .handle
125 .read_manufacturer_string(h.language, device_desc, h.timeout)
126 .unwrap_or_default())
127 );
128 println!(
129 " iProduct {:3} {}",
130 device_desc.product_string_index().unwrap_or(0),
131 handle.as_mut().map_or(String::new(), |h| h
132 .handle
133 .read_product_string(h.language, device_desc, h.timeout)
134 .unwrap_or_default())
135 );
136 println!(
137 " iSerialNumber {:3} {}",
138 device_desc.serial_number_string_index().unwrap_or(0),
139 handle.as_mut().map_or(String::new(), |h| h
140 .handle
141 .read_serial_number_string(h.language, device_desc, h.timeout)
142 .unwrap_or_default())
143 );
144 println!(
145 " bNumConfigurations {:3}",
146 device_desc.num_configurations()
147 );
148 }
149
print_config<T: UsbContext>(config_desc: &ConfigDescriptor, handle: &mut Option<UsbDevice<T>>)150 fn print_config<T: UsbContext>(config_desc: &ConfigDescriptor, handle: &mut Option<UsbDevice<T>>) {
151 println!(" Config Descriptor:");
152 println!(" bLength {:3}", config_desc.length());
153 println!(
154 " bDescriptorType {:3}",
155 config_desc.descriptor_type()
156 );
157 println!(" wTotalLength {:#06x}", config_desc.total_length());
158 println!(
159 " bNumInterfaces {:3}",
160 config_desc.num_interfaces()
161 );
162 println!(" bConfigurationValue {:3}", config_desc.number());
163 println!(
164 " iConfiguration {:3} {}",
165 config_desc.description_string_index().unwrap_or(0),
166 handle.as_mut().map_or(String::new(), |h| h
167 .handle
168 .read_configuration_string(h.language, config_desc, h.timeout)
169 .unwrap_or_default())
170 );
171 println!(" bmAttributes:");
172 println!(" Self Powered {:>5}", config_desc.self_powered());
173 println!(" Remote Wakeup {:>5}", config_desc.remote_wakeup());
174 println!(" bMaxPower {:4}mW", config_desc.max_power());
175
176 if !config_desc.extra().is_empty() {
177 println!(" {:?}", config_desc.extra());
178 } else {
179 println!(" no extra data");
180 }
181 }
182
print_interface<T: UsbContext>( interface_desc: &InterfaceDescriptor, handle: &mut Option<UsbDevice<T>>, )183 fn print_interface<T: UsbContext>(
184 interface_desc: &InterfaceDescriptor,
185 handle: &mut Option<UsbDevice<T>>,
186 ) {
187 println!(" Interface Descriptor:");
188 println!(" bLength {:3}", interface_desc.length());
189 println!(
190 " bDescriptorType {:3}",
191 interface_desc.descriptor_type()
192 );
193 println!(
194 " bInterfaceNumber {:3}",
195 interface_desc.interface_number()
196 );
197 println!(
198 " bAlternateSetting {:3}",
199 interface_desc.setting_number()
200 );
201 println!(
202 " bNumEndpoints {:3}",
203 interface_desc.num_endpoints()
204 );
205 println!(
206 " bInterfaceClass {:#04x}",
207 interface_desc.class_code()
208 );
209 println!(
210 " bInterfaceSubClass {:#04x}",
211 interface_desc.sub_class_code()
212 );
213 println!(
214 " bInterfaceProtocol {:#04x}",
215 interface_desc.protocol_code()
216 );
217 println!(
218 " iInterface {:3} {}",
219 interface_desc.description_string_index().unwrap_or(0),
220 handle.as_mut().map_or(String::new(), |h| h
221 .handle
222 .read_interface_string(h.language, interface_desc, h.timeout)
223 .unwrap_or_default())
224 );
225
226 if interface_desc.extra().is_empty() {
227 println!(" {:?}", interface_desc.extra());
228 } else {
229 println!(" no extra data");
230 }
231 }
232
print_endpoint(endpoint_desc: &EndpointDescriptor)233 fn print_endpoint(endpoint_desc: &EndpointDescriptor) {
234 println!(" Endpoint Descriptor:");
235 println!(" bLength {:3}", endpoint_desc.length());
236 println!(
237 " bDescriptorType {:3}",
238 endpoint_desc.descriptor_type()
239 );
240 println!(
241 " bEndpointAddress {:#04x} EP {} {:?}",
242 endpoint_desc.address(),
243 endpoint_desc.number(),
244 endpoint_desc.direction()
245 );
246 println!(" bmAttributes:");
247 println!(
248 " Transfer Type {:?}",
249 endpoint_desc.transfer_type()
250 );
251 println!(
252 " Synch Type {:?}",
253 endpoint_desc.sync_type()
254 );
255 println!(
256 " Usage Type {:?}",
257 endpoint_desc.usage_type()
258 );
259 println!(
260 " wMaxPacketSize {:#06x}",
261 endpoint_desc.max_packet_size()
262 );
263 println!(
264 " bInterval {:3}",
265 endpoint_desc.interval()
266 );
267 }
268
get_speed(speed: Speed) -> &'static str269 fn get_speed(speed: Speed) -> &'static str {
270 match speed {
271 Speed::SuperPlus => "10000 Mbps",
272 Speed::Super => "5000 Mbps",
273 Speed::High => " 480 Mbps",
274 Speed::Full => " 12 Mbps",
275 Speed::Low => " 1.5 Mbps",
276 _ => "(unknown)",
277 }
278 }
279