• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use crate::{
6     control_request_type, descriptor, ConfigDescriptorTree,
7     ControlRequestDataPhaseTransferDirection, ControlRequestRecipient, ControlRequestType,
8     DeviceDescriptor, DeviceDescriptorTree, Error, Result, StandardControlRequest,
9 };
10 use base::{handle_eintr_errno, AsRawDescriptor, IoctlNr, RawDescriptor};
11 use data_model::vec_with_array_field;
12 use libc::{EAGAIN, ENODEV, ENOENT};
13 use std::convert::TryInto;
14 use std::fs::File;
15 use std::io::{Read, Seek, SeekFrom};
16 use std::mem::size_of_val;
17 use std::os::raw::{c_int, c_uint, c_void};
18 use std::sync::Arc;
19 
20 /// Device represents a USB device.
21 pub struct Device {
22     fd: Arc<File>,
23     device_descriptor_tree: DeviceDescriptorTree,
24 }
25 
26 /// Transfer contains the information necessary to submit a USB request
27 /// and, once it has been submitted and completed, contains the response.
28 pub struct Transfer {
29     // NOTE: This Vec is actually a single URB with a trailing
30     // variable-length field created by vec_with_array_field().
31     urb: Vec<usb_sys::usbdevfs_urb>,
32     pub buffer: Vec<u8>,
33     callback: Option<Box<dyn Fn(Transfer) + Send + Sync>>,
34 }
35 
36 /// TransferHandle is a handle that allows cancellation of in-flight transfers
37 /// between submit_transfer() and get_completed_transfer().
38 /// Attempting to cancel a transfer that has already completed is safe and will
39 /// return an error.
40 pub struct TransferHandle {
41     weak_transfer: std::sync::Weak<Transfer>,
42     fd: std::sync::Weak<File>,
43 }
44 
45 #[derive(PartialEq)]
46 pub enum TransferStatus {
47     Completed,
48     Error,
49     Cancelled,
50     NoDevice,
51 }
52 
53 impl Device {
54     /// Create a new `Device` from a file descriptor.
55     /// `fd` should be a file in usbdevfs (e.g. `/dev/bus/usb/001/002`).
new(mut fd: File) -> Result<Self>56     pub fn new(mut fd: File) -> Result<Self> {
57         fd.seek(SeekFrom::Start(0)).map_err(Error::DescriptorRead)?;
58         let mut descriptor_data = Vec::new();
59         fd.read_to_end(&mut descriptor_data)
60             .map_err(Error::DescriptorRead)?;
61         let device_descriptor_tree = descriptor::parse_usbfs_descriptors(&descriptor_data)?;
62 
63         let device = Device {
64             fd: Arc::new(fd),
65             device_descriptor_tree,
66         };
67         Ok(device)
68     }
69 
fd(&self) -> Arc<File>70     pub fn fd(&self) -> Arc<File> {
71         self.fd.clone()
72     }
73 
ioctl(&self, nr: IoctlNr) -> Result<i32>74     unsafe fn ioctl(&self, nr: IoctlNr) -> Result<i32> {
75         let ret = handle_eintr_errno!(base::ioctl(&*self.fd, nr));
76         if ret < 0 {
77             return Err(Error::IoctlFailed(nr, base::Error::last()));
78         }
79         Ok(ret)
80     }
81 
ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32>82     unsafe fn ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32> {
83         let ret = handle_eintr_errno!(base::ioctl_with_ref(&*self.fd, nr, arg));
84         if ret < 0 {
85             return Err(Error::IoctlFailed(nr, base::Error::last()));
86         }
87         Ok(ret)
88     }
89 
ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32>90     unsafe fn ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32> {
91         let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(&*self.fd, nr, arg));
92         if ret < 0 {
93             return Err(Error::IoctlFailed(nr, base::Error::last()));
94         }
95         Ok(ret)
96     }
97 
ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32>98     unsafe fn ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32> {
99         let ret = handle_eintr_errno!(base::ioctl_with_mut_ptr(&*self.fd, nr, arg));
100         if ret < 0 {
101             return Err(Error::IoctlFailed(nr, base::Error::last()));
102         }
103         Ok(ret)
104     }
105 
106     /// Submit a transfer to the device.
107     /// The transfer will be processed asynchronously by the device.
108     /// Call `poll_transfers()` on this device to check for completed transfers.
submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle>109     pub fn submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle> {
110         let mut rc_transfer = Arc::new(transfer);
111 
112         // Technically, Arc::from_raw() should only be called on pointers returned
113         // from Arc::into_raw(). However, we need to stash this value inside the
114         // Arc<Transfer> itself, so we manually calculate the address that would be
115         // returned from Arc::into_raw() via Deref and then call Arc::into_raw()
116         // to forget the Arc without dropping its contents.
117         // Do not remove the into_raw() call!
118         let raw_transfer = (&*rc_transfer) as *const Transfer as usize;
119         match Arc::get_mut(&mut rc_transfer) {
120             Some(t) => t.urb_mut().usercontext = raw_transfer,
121             None => {
122                 // This should never happen, since there is only one strong reference
123                 // at this point.
124                 return Err(Error::RcGetMutFailed);
125             }
126         }
127         let _ = Arc::into_raw(rc_transfer.clone());
128 
129         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
130 
131         // Safe because we control the lifetime of the URB via Arc::into_raw() and
132         // Arc::from_raw() in poll_transfers().
133         unsafe {
134             self.ioctl_with_mut_ptr(usb_sys::USBDEVFS_SUBMITURB(), urb_ptr)?;
135         }
136 
137         let weak_transfer = Arc::downgrade(&rc_transfer);
138 
139         Ok(TransferHandle {
140             weak_transfer,
141             fd: Arc::downgrade(&self.fd),
142         })
143     }
144 
145     /// Check for completed asynchronous transfers submitted via `submit_transfer()`.
146     /// The callback for each completed transfer will be called.
poll_transfers(&self) -> Result<()>147     pub fn poll_transfers(&self) -> Result<()> {
148         // Reap completed transfers until we get EAGAIN.
149         loop {
150             let mut urb_ptr: *mut usb_sys::usbdevfs_urb = std::ptr::null_mut();
151             // Safe because we provide a valid urb_ptr to be filled by the kernel.
152             let result =
153                 unsafe { self.ioctl_with_mut_ref(usb_sys::USBDEVFS_REAPURBNDELAY(), &mut urb_ptr) };
154             match result {
155                 // EAGAIN indicates no more completed transfers right now.
156                 Err(Error::IoctlFailed(_nr, e)) if e.errno() == EAGAIN => break,
157                 Err(e) => return Err(e),
158                 Ok(_) => {}
159             }
160 
161             if urb_ptr.is_null() {
162                 break;
163             }
164 
165             // Safe because the URB usercontext field is always set to the result of
166             // Arc::into_raw() in submit_transfer().
167             let rc_transfer: Arc<Transfer> =
168                 unsafe { Arc::from_raw((*urb_ptr).usercontext as *const Transfer) };
169 
170             // There should always be exactly one strong reference to rc_transfer,
171             // so try_unwrap() should never fail.
172             let mut transfer = Arc::try_unwrap(rc_transfer).map_err(|_| Error::RcUnwrapFailed)?;
173 
174             if let Some(cb) = transfer.callback.take() {
175                 cb(transfer);
176             }
177         }
178 
179         Ok(())
180     }
181 
182     /// Perform a USB port reset to reinitialize a device.
reset(&self) -> Result<()>183     pub fn reset(&self) -> Result<()> {
184         // TODO(dverkamp): re-enable reset once crbug.com/1058059 is resolved.
185         // Skip reset for all non-Edge TPU devices.
186         let vid = self.device_descriptor_tree.idVendor;
187         let pid = self.device_descriptor_tree.idProduct;
188         match (vid, pid) {
189             (0x1a6e, 0x089a) => (),
190             _ => return Ok(()),
191         }
192 
193         // Safe because self.fd is a valid usbdevfs file descriptor.
194         let result = unsafe { self.ioctl(usb_sys::USBDEVFS_RESET()) };
195 
196         if let Err(Error::IoctlFailed(_nr, errno_err)) = result {
197             // The device may disappear after a reset if e.g. its firmware changed.
198             // Treat that as success.
199             if errno_err.errno() == libc::ENODEV {
200                 return Ok(());
201             }
202         }
203 
204         result?;
205         Ok(())
206     }
207 
208     /// Claim an interface on this device.
claim_interface(&self, interface_number: u8) -> Result<()>209     pub fn claim_interface(&self, interface_number: u8) -> Result<()> {
210         let disconnect_claim = usb_sys::usbdevfs_disconnect_claim {
211             interface: interface_number.into(),
212             flags: 0,
213             driver: [0u8; 256],
214         };
215         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
216         // pointer to a usbdevs_disconnect_claim structure.
217         unsafe {
218             self.ioctl_with_ref(usb_sys::USBDEVFS_DISCONNECT_CLAIM(), &disconnect_claim)?;
219         }
220 
221         Ok(())
222     }
223 
224     /// Release an interface previously claimed with `claim_interface()`.
release_interface(&self, interface_number: u8) -> Result<()>225     pub fn release_interface(&self, interface_number: u8) -> Result<()> {
226         let ifnum: c_uint = interface_number.into();
227         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
228         // pointer to unsigned int.
229         unsafe {
230             self.ioctl_with_ref(usb_sys::USBDEVFS_RELEASEINTERFACE(), &ifnum)?;
231         }
232 
233         Ok(())
234     }
235 
236     /// Activate an alternate setting for an interface.
set_interface_alt_setting( &self, interface_number: u8, alternative_setting: u8, ) -> Result<()>237     pub fn set_interface_alt_setting(
238         &self,
239         interface_number: u8,
240         alternative_setting: u8,
241     ) -> Result<()> {
242         let setinterface = usb_sys::usbdevfs_setinterface {
243             interface: interface_number.into(),
244             altsetting: alternative_setting.into(),
245         };
246         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
247         // pointer to a usbdevfs_setinterface structure.
248         unsafe {
249             self.ioctl_with_ref(usb_sys::USBDEVFS_SETINTERFACE(), &setinterface)?;
250         }
251         Ok(())
252     }
253 
254     /// Set active configuration for this device.
set_active_configuration(&mut self, config: u8) -> Result<()>255     pub fn set_active_configuration(&mut self, config: u8) -> Result<()> {
256         let config: c_int = config.into();
257         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
258         // pointer to int.
259         unsafe {
260             self.ioctl_with_ref(usb_sys::USBDEVFS_SETCONFIGURATION(), &config)?;
261         }
262 
263         Ok(())
264     }
265 
266     /// Get the device descriptor of this device.
get_device_descriptor(&self) -> Result<DeviceDescriptor>267     pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
268         Ok(*self.device_descriptor_tree)
269     }
270 
get_device_descriptor_tree(&self) -> &DeviceDescriptorTree271     pub fn get_device_descriptor_tree(&self) -> &DeviceDescriptorTree {
272         &self.device_descriptor_tree
273     }
274 
275     /// Get active config descriptor of this device.
get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree>276     pub fn get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree> {
277         match self.device_descriptor_tree.get_config_descriptor(config) {
278             Some(config_descriptor) => Ok(config_descriptor.clone()),
279             None => Err(Error::NoSuchDescriptor),
280         }
281     }
282 
283     /// Get a configuration descriptor by its index within the list of descriptors returned
284     /// by the device.
get_config_descriptor_by_index(&self, config_index: u8) -> Result<ConfigDescriptorTree>285     pub fn get_config_descriptor_by_index(&self, config_index: u8) -> Result<ConfigDescriptorTree> {
286         match self
287             .device_descriptor_tree
288             .get_config_descriptor_by_index(config_index)
289         {
290             Some(config_descriptor) => Ok(config_descriptor.clone()),
291             None => Err(Error::NoSuchDescriptor),
292         }
293     }
294 
295     /// Get bConfigurationValue of the currently active configuration.
get_active_configuration(&self) -> Result<u8>296     pub fn get_active_configuration(&self) -> Result<u8> {
297         // If the device only exposes a single configuration, bypass the control transfer below
298         // by looking up the configuration value from the descriptor.
299         if self.device_descriptor_tree.bNumConfigurations == 1 {
300             if let Some(config_descriptor) = self
301                 .device_descriptor_tree
302                 .get_config_descriptor_by_index(0)
303             {
304                 return Ok(config_descriptor.bConfigurationValue);
305             }
306         }
307 
308         // Send a synchronous control transfer to get the active configuration.
309         let mut active_config: u8 = 0;
310         let ctrl_transfer = usb_sys::usbdevfs_ctrltransfer {
311             bRequestType: control_request_type(
312                 ControlRequestType::Standard,
313                 ControlRequestDataPhaseTransferDirection::DeviceToHost,
314                 ControlRequestRecipient::Device,
315             ),
316             bRequest: StandardControlRequest::GetConfiguration as u8,
317             wValue: 0,
318             wIndex: 0,
319             wLength: size_of_val(&active_config) as u16,
320             timeout: 5000, // milliseconds
321             data: &mut active_config as *mut u8 as *mut c_void,
322         };
323         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
324         // pointer to a usbdevfs_ctrltransfer structure.
325         unsafe {
326             self.ioctl_with_ref(usb_sys::USBDEVFS_CONTROL(), &ctrl_transfer)?;
327         }
328         Ok(active_config)
329     }
330 
331     /// Get the total number of configurations for this device.
get_num_configurations(&self) -> u8332     pub fn get_num_configurations(&self) -> u8 {
333         self.device_descriptor_tree.bNumConfigurations
334     }
335 
336     /// Clear the halt/stall condition for an endpoint.
clear_halt(&self, ep_addr: u8) -> Result<()>337     pub fn clear_halt(&self, ep_addr: u8) -> Result<()> {
338         let endpoint: c_uint = ep_addr.into();
339         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
340         // pointer to unsigned int.
341         unsafe {
342             self.ioctl_with_ref(usb_sys::USBDEVFS_CLEAR_HALT(), &endpoint)?;
343         }
344 
345         Ok(())
346     }
347 }
348 
349 impl AsRawDescriptor for Device {
as_raw_descriptor(&self) -> RawDescriptor350     fn as_raw_descriptor(&self) -> RawDescriptor {
351         self.fd.as_raw_descriptor()
352     }
353 }
354 
355 impl Transfer {
urb(&self) -> &usb_sys::usbdevfs_urb356     fn urb(&self) -> &usb_sys::usbdevfs_urb {
357         // self.urb is a Vec created with `vec_with_array_field`; the first entry is
358         // the URB itself.
359         &self.urb[0]
360     }
361 
urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb362     fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb {
363         &mut self.urb[0]
364     }
365 
new( transfer_type: u8, endpoint: u8, buffer: Vec<u8>, iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], ) -> Result<Transfer>366     fn new(
367         transfer_type: u8,
368         endpoint: u8,
369         buffer: Vec<u8>,
370         iso_packets: &[usb_sys::usbdevfs_iso_packet_desc],
371     ) -> Result<Transfer> {
372         let mut transfer = Transfer {
373             urb: vec_with_array_field::<usb_sys::usbdevfs_urb, usb_sys::usbdevfs_iso_packet_desc>(
374                 iso_packets.len(),
375             ),
376             buffer,
377             callback: None,
378         };
379 
380         transfer.urb_mut().urb_type = transfer_type;
381         transfer.urb_mut().endpoint = endpoint;
382         transfer.urb_mut().buffer = transfer.buffer.as_mut_ptr() as *mut c_void;
383         transfer.urb_mut().buffer_length = transfer
384             .buffer
385             .len()
386             .try_into()
387             .map_err(Error::InvalidBufferLength)?;
388 
389         // Safe because we ensured there is enough space in transfer.urb to hold the number of
390         // isochronous frames required.
391         let iso_frame_desc = unsafe {
392             transfer
393                 .urb_mut()
394                 .iso_frame_desc
395                 .as_mut_slice(iso_packets.len())
396         };
397         iso_frame_desc.copy_from_slice(iso_packets);
398 
399         Ok(transfer)
400     }
401 
402     /// Create a control transfer.
new_control(buffer: Vec<u8>) -> Result<Transfer>403     pub fn new_control(buffer: Vec<u8>) -> Result<Transfer> {
404         let endpoint = 0;
405         Self::new(usb_sys::USBDEVFS_URB_TYPE_CONTROL, endpoint, buffer, &[])
406     }
407 
408     /// Create an interrupt transfer.
new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>409     pub fn new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
410         Self::new(usb_sys::USBDEVFS_URB_TYPE_INTERRUPT, endpoint, buffer, &[])
411     }
412 
413     /// Create a bulk transfer.
new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>414     pub fn new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
415         Self::new(usb_sys::USBDEVFS_URB_TYPE_BULK, endpoint, buffer, &[])
416     }
417 
418     /// Create an isochronous transfer.
new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>419     pub fn new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
420         // TODO(dverkamp): allow user to specify iso descriptors
421         Self::new(usb_sys::USBDEVFS_URB_TYPE_ISO, endpoint, buffer, &[])
422     }
423 
424     /// Get the status of a completed transfer.
status(&self) -> TransferStatus425     pub fn status(&self) -> TransferStatus {
426         let status = self.urb().status;
427         if status == 0 {
428             TransferStatus::Completed
429         } else if status == -ENODEV {
430             TransferStatus::NoDevice
431         } else if status == -ENOENT {
432             TransferStatus::Cancelled
433         } else {
434             TransferStatus::Error
435         }
436     }
437 
438     /// Get the actual amount of data transferred, which may be less than
439     /// the original length.
actual_length(&self) -> usize440     pub fn actual_length(&self) -> usize {
441         self.urb().actual_length as usize
442     }
443 
444     /// Set callback function for transfer completion.
set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C)445     pub fn set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C) {
446         self.callback = Some(Box::new(cb));
447     }
448 }
449 
450 impl TransferHandle {
451     /// Attempt to cancel the transfer associated with this `TransferHandle`.
452     /// Safe to call even if the transfer has already completed;
453     /// `Error::TransferAlreadyCompleted` will be returned in this case.
cancel(self) -> Result<()>454     pub fn cancel(self) -> Result<()> {
455         let rc_transfer = match self.weak_transfer.upgrade() {
456             None => return Err(Error::TransferAlreadyCompleted),
457             Some(rc_transfer) => rc_transfer,
458         };
459 
460         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
461         let fd = match self.fd.upgrade() {
462             None => return Err(Error::NoDevice),
463             Some(fd) => fd,
464         };
465 
466         // Safe because fd is a valid usbdevfs file descriptor and we pass a valid
467         // pointer to a usbdevfs_urb structure.
468         if unsafe {
469             handle_eintr_errno!(base::ioctl_with_mut_ptr(
470                 &*fd,
471                 usb_sys::USBDEVFS_DISCARDURB(),
472                 urb_ptr
473             ))
474         } < 0
475         {
476             return Err(Error::IoctlFailed(
477                 usb_sys::USBDEVFS_DISCARDURB(),
478                 base::Error::last(),
479             ));
480         }
481 
482         Ok(())
483     }
484 }
485