1use anyhow::{Context, Result, ensure};
6use rusb;
7use std::time::Duration;
8
9use crate::transport::TransportError;
10
11pub struct UsbBackend {
13 device: rusb::Device<rusb::GlobalContext>,
14 handle: rusb::DeviceHandle<rusb::GlobalContext>,
15 serial_number: String,
16 timeout: Duration,
17}
18
19impl UsbBackend {
20 pub fn scan(
23 usb_vid: u16,
24 usb_pid: u16,
25 usb_serial: Option<&str>,
26 ) -> Result<Vec<(rusb::Device<rusb::GlobalContext>, String)>> {
27 let mut devices = Vec::new();
28 let mut deferred_log_messages = Vec::new();
29 for device in rusb::devices().context("USB error")?.iter() {
30 let descriptor = match device.device_descriptor() {
31 Ok(desc) => desc,
32 Err(e) => {
33 deferred_log_messages.push(format!(
34 "Could not read device descriptor for device at bus={} address={}: {}",
35 device.bus_number(),
36 device.address(),
37 e,
38 ));
39 continue;
40 }
41 };
42 if descriptor.vendor_id() != usb_vid {
43 continue;
44 }
45 if descriptor.product_id() != usb_pid {
46 continue;
47 }
48 let handle = match device.open() {
49 Ok(handle) => handle,
50 Err(e) => {
51 deferred_log_messages.push(format!(
52 "Could not open device at bus={} address={}: {}",
53 device.bus_number(),
54 device.address(),
55 e,
56 ));
57 continue;
58 }
59 };
60 let serial_number = match handle.read_serial_number_string_ascii(&descriptor) {
61 Ok(sn) => sn,
62 Err(e) => {
63 deferred_log_messages.push(format!(
64 "Could not read serial number from device at bus={} address={}: {}",
65 device.bus_number(),
66 device.address(),
67 e,
68 ));
69 continue;
70 }
71 };
72 if let Some(sn) = &usb_serial
73 && &serial_number != sn
74 {
75 continue;
76 }
77 devices.push((device, serial_number));
78 }
79
80 let severity = match devices.len() {
85 1 => log::Level::Info,
86 _ => log::Level::Error,
87 };
88 for s in deferred_log_messages {
89 log::log!(severity, "{}", s);
90 }
91
92 Ok(devices)
93 }
94
95 pub fn new(usb_vid: u16, usb_pid: u16, usb_serial: Option<&str>) -> Result<Self> {
97 let mut devices = UsbBackend::scan(usb_vid, usb_pid, usb_serial)?;
98 ensure!(!devices.is_empty(), TransportError::NoDevice);
99 ensure!(devices.len() == 1, TransportError::MultipleDevices);
100
101 let (device, serial_number) = devices.remove(0);
102 Ok(UsbBackend {
103 handle: device.open().context("USB open error")?,
104 device,
105 serial_number,
106 timeout: Duration::from_millis(500),
107 })
108 }
109
110 pub fn get_vendor_id(&self) -> u16 {
111 self.device.device_descriptor().unwrap().vendor_id()
112 }
113
114 pub fn get_product_id(&self) -> u16 {
115 self.device.device_descriptor().unwrap().product_id()
116 }
117
118 pub fn get_serial_number(&self) -> &str {
120 self.serial_number.as_str()
121 }
122
123 pub fn set_active_configuration(&mut self, config: u8) -> Result<()> {
124 self.handle
125 .set_active_configuration(config)
126 .context("USB error")
127 }
128
129 pub fn claim_interface(&mut self, iface: u8) -> Result<()> {
130 self.handle.claim_interface(iface).context("USB error")
131 }
132
133 pub fn release_interface(&mut self, iface: u8) -> Result<()> {
134 self.handle.release_interface(iface).context("USB error")
135 }
136
137 pub fn kernel_driver_active(&self, iface: u8) -> Result<bool> {
138 self.handle.kernel_driver_active(iface).context("USB error")
139 }
140
141 pub fn detach_kernel_driver(&mut self, iface: u8) -> Result<()> {
142 self.handle.detach_kernel_driver(iface).context("USB error")
143 }
144
145 pub fn attach_kernel_driver(&mut self, iface: u8) -> Result<()> {
146 self.handle.attach_kernel_driver(iface).context("USB error")
147 }
148
149 pub fn active_config_descriptor(&self) -> Result<rusb::ConfigDescriptor> {
156 self.device.active_config_descriptor().context("USB error")
157 }
158
159 pub fn bus_number(&self) -> u8 {
160 self.device.bus_number()
161 }
162
163 pub fn port_numbers(&self) -> Result<Vec<u8>> {
164 self.device.port_numbers().context("USB error")
165 }
166
167 pub fn read_string_descriptor_ascii(&self, idx: u8) -> Result<String> {
168 self.handle
169 .read_string_descriptor_ascii(idx)
170 .context("USB error")
171 }
172
173 pub fn write_control(
179 &self,
180 request_type: u8,
181 request: u8,
182 value: u16,
183 index: u16,
184 buf: &[u8],
185 ) -> Result<usize> {
186 self.handle
187 .write_control(request_type, request, value, index, buf, self.timeout)
188 .context("USB error")
189 }
190
191 pub fn read_control(
193 &self,
194 request_type: u8,
195 request: u8,
196 value: u16,
197 index: u16,
198 buf: &mut [u8],
199 ) -> Result<usize> {
200 self.handle
201 .read_control(request_type, request, value, index, buf, self.timeout)
202 .context("USB error")
203 }
204
205 pub fn read_bulk(&self, endpoint: u8, data: &mut [u8]) -> Result<usize> {
207 let len = self
208 .handle
209 .read_bulk(endpoint, data, self.timeout)
210 .context("USB error")?;
211 Ok(len)
212 }
213
214 pub fn read_bulk_timeout(
216 &self,
217 endpoint: u8,
218 data: &mut [u8],
219 timeout: Duration,
220 ) -> Result<usize> {
221 let len = self
222 .handle
223 .read_bulk(endpoint, data, timeout)
224 .context("USB error")?;
225 Ok(len)
226 }
227
228 pub fn write_bulk(&self, endpoint: u8, data: &[u8]) -> Result<usize> {
230 let len = self
231 .handle
232 .write_bulk(endpoint, data, self.timeout)
233 .context("USB error")?;
234 Ok(len)
235 }
236}