• 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::{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 device_descriptor_tree = descriptor::parse_usbfs_descriptors(&mut fd)?;
59 
60         let device = Device {
61             fd: Arc::new(fd),
62             device_descriptor_tree,
63         };
64         Ok(device)
65     }
66 
fd(&self) -> Arc<File>67     pub fn fd(&self) -> Arc<File> {
68         self.fd.clone()
69     }
70 
ioctl(&self, nr: IoctlNr) -> Result<i32>71     unsafe fn ioctl(&self, nr: IoctlNr) -> Result<i32> {
72         let ret = handle_eintr_errno!(base::ioctl(&*self.fd, nr));
73         if ret < 0 {
74             return Err(Error::IoctlFailed(nr, base::Error::last()));
75         }
76         Ok(ret)
77     }
78 
ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32>79     unsafe fn ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32> {
80         let ret = handle_eintr_errno!(base::ioctl_with_ref(&*self.fd, nr, arg));
81         if ret < 0 {
82             return Err(Error::IoctlFailed(nr, base::Error::last()));
83         }
84         Ok(ret)
85     }
86 
ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32>87     unsafe fn ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32> {
88         let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(&*self.fd, nr, arg));
89         if ret < 0 {
90             return Err(Error::IoctlFailed(nr, base::Error::last()));
91         }
92         Ok(ret)
93     }
94 
ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32>95     unsafe fn ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32> {
96         let ret = handle_eintr_errno!(base::ioctl_with_mut_ptr(&*self.fd, nr, arg));
97         if ret < 0 {
98             return Err(Error::IoctlFailed(nr, base::Error::last()));
99         }
100         Ok(ret)
101     }
102 
103     /// Submit a transfer to the device.
104     /// The transfer will be processed asynchronously by the device.
105     /// Call `poll_transfers()` on this device to check for completed transfers.
submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle>106     pub fn submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle> {
107         let mut rc_transfer = Arc::new(transfer);
108 
109         // Technically, Arc::from_raw() should only be called on pointers returned
110         // from Arc::into_raw(). However, we need to stash this value inside the
111         // Arc<Transfer> itself, so we manually calculate the address that would be
112         // returned from Arc::into_raw() via Deref and then call Arc::into_raw()
113         // to forget the Arc without dropping its contents.
114         // Do not remove the into_raw() call!
115         let raw_transfer = (&*rc_transfer) as *const Transfer as usize;
116         match Arc::get_mut(&mut rc_transfer) {
117             Some(t) => t.urb_mut().usercontext = raw_transfer,
118             None => {
119                 // This should never happen, since there is only one strong reference
120                 // at this point.
121                 return Err(Error::RcGetMutFailed);
122             }
123         }
124         let _ = Arc::into_raw(rc_transfer.clone());
125 
126         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
127 
128         // Safe because we control the lifetime of the URB via Arc::into_raw() and
129         // Arc::from_raw() in poll_transfers().
130         unsafe {
131             self.ioctl_with_mut_ptr(usb_sys::USBDEVFS_SUBMITURB(), urb_ptr)?;
132         }
133 
134         let weak_transfer = Arc::downgrade(&rc_transfer);
135 
136         Ok(TransferHandle {
137             weak_transfer,
138             fd: Arc::downgrade(&self.fd),
139         })
140     }
141 
142     /// Check for completed asynchronous transfers submitted via `submit_transfer()`.
143     /// The callback for each completed transfer will be called.
poll_transfers(&self) -> Result<()>144     pub fn poll_transfers(&self) -> Result<()> {
145         // Reap completed transfers until we get EAGAIN.
146         loop {
147             let mut urb_ptr: *mut usb_sys::usbdevfs_urb = std::ptr::null_mut();
148             // Safe because we provide a valid urb_ptr to be filled by the kernel.
149             let result =
150                 unsafe { self.ioctl_with_mut_ref(usb_sys::USBDEVFS_REAPURBNDELAY(), &mut urb_ptr) };
151             match result {
152                 Err(Error::IoctlFailed(_nr, e)) => {
153                     if e.errno() == EAGAIN {
154                         // No more completed transfers right now.
155                         break;
156                     }
157                 }
158                 Err(e) => return Err(e),
159                 Ok(_) => {}
160             }
161 
162             if urb_ptr.is_null() {
163                 break;
164             }
165 
166             // Safe because the URB usercontext field is always set to the result of
167             // Arc::into_raw() in submit_transfer().
168             let rc_transfer: Arc<Transfer> =
169                 unsafe { Arc::from_raw((*urb_ptr).usercontext as *const Transfer) };
170 
171             // There should always be exactly one strong reference to rc_transfer,
172             // so try_unwrap() should never fail.
173             let mut transfer = Arc::try_unwrap(rc_transfer).map_err(|_| Error::RcUnwrapFailed)?;
174 
175             if let Some(cb) = transfer.callback.take() {
176                 cb(transfer);
177             }
178         }
179 
180         Ok(())
181     }
182 
183     /// Perform a USB port reset to reinitialize a device.
reset(&self) -> Result<()>184     pub fn reset(&self) -> Result<()> {
185         // TODO(dverkamp): re-enable reset once crbug.com/1058059 is resolved.
186         // Skip reset for all non-Edge TPU devices.
187         let vid = self.device_descriptor_tree.idVendor;
188         let pid = self.device_descriptor_tree.idProduct;
189         match (vid, pid) {
190             (0x1a6e, 0x089a) => (),
191             _ => return Ok(()),
192         }
193 
194         // Safe because self.fd is a valid usbdevfs file descriptor.
195         let result = unsafe { self.ioctl(usb_sys::USBDEVFS_RESET()) };
196 
197         if let Err(Error::IoctlFailed(_nr, errno_err)) = result {
198             // The device may disappear after a reset if e.g. its firmware changed.
199             // Treat that as success.
200             if errno_err.errno() == libc::ENODEV {
201                 return Ok(());
202             }
203         }
204 
205         result?;
206         Ok(())
207     }
208 
209     /// Claim an interface on this device.
claim_interface(&self, interface_number: u8) -> Result<()>210     pub fn claim_interface(&self, interface_number: u8) -> Result<()> {
211         let disconnect_claim = usb_sys::usbdevfs_disconnect_claim {
212             interface: interface_number.into(),
213             flags: 0,
214             driver: [0u8; 256],
215         };
216         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
217         // pointer to a usbdevs_disconnect_claim structure.
218         unsafe {
219             self.ioctl_with_ref(usb_sys::USBDEVFS_DISCONNECT_CLAIM(), &disconnect_claim)?;
220         }
221 
222         Ok(())
223     }
224 
225     /// Release an interface previously claimed with `claim_interface()`.
release_interface(&self, interface_number: u8) -> Result<()>226     pub fn release_interface(&self, interface_number: u8) -> Result<()> {
227         let ifnum: c_uint = interface_number.into();
228         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
229         // pointer to unsigned int.
230         unsafe {
231             self.ioctl_with_ref(usb_sys::USBDEVFS_RELEASEINTERFACE(), &ifnum)?;
232         }
233 
234         Ok(())
235     }
236 
237     /// Activate an alternate setting for an interface.
set_interface_alt_setting( &self, interface_number: u8, alternative_setting: u8, ) -> Result<()>238     pub fn set_interface_alt_setting(
239         &self,
240         interface_number: u8,
241         alternative_setting: u8,
242     ) -> Result<()> {
243         let setinterface = usb_sys::usbdevfs_setinterface {
244             interface: interface_number.into(),
245             altsetting: alternative_setting.into(),
246         };
247         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
248         // pointer to a usbdevfs_setinterface structure.
249         unsafe {
250             self.ioctl_with_ref(usb_sys::USBDEVFS_SETINTERFACE(), &setinterface)?;
251         }
252         Ok(())
253     }
254 
255     /// Set active configuration for this device.
set_active_configuration(&mut self, config: u8) -> Result<()>256     pub fn set_active_configuration(&mut self, config: u8) -> Result<()> {
257         let config: c_int = config.into();
258         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
259         // pointer to int.
260         unsafe {
261             self.ioctl_with_ref(usb_sys::USBDEVFS_SETCONFIGURATION(), &config)?;
262         }
263 
264         Ok(())
265     }
266 
267     /// Get the device descriptor of this device.
get_device_descriptor(&self) -> Result<DeviceDescriptor>268     pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
269         Ok(*self.device_descriptor_tree)
270     }
271 
272     /// Get active config descriptor of this device.
get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree>273     pub fn get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree> {
274         match self.device_descriptor_tree.get_config_descriptor(config) {
275             Some(config_descriptor) => Ok(config_descriptor.clone()),
276             None => Err(Error::NoSuchDescriptor),
277         }
278     }
279 
280     /// Get bConfigurationValue of the currently active configuration.
get_active_configuration(&self) -> Result<u8>281     pub fn get_active_configuration(&self) -> Result<u8> {
282         // Send a synchronous control transfer to get the active configuration.
283         let mut active_config: u8 = 0;
284         let ctrl_transfer = usb_sys::usbdevfs_ctrltransfer {
285             bRequestType: control_request_type(
286                 ControlRequestType::Standard,
287                 ControlRequestDataPhaseTransferDirection::DeviceToHost,
288                 ControlRequestRecipient::Device,
289             ),
290             bRequest: StandardControlRequest::GetConfiguration as u8,
291             wValue: 0,
292             wIndex: 0,
293             wLength: size_of_val(&active_config) as u16,
294             timeout: 5000, // milliseconds
295             data: &mut active_config as *mut u8 as *mut c_void,
296         };
297         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
298         // pointer to a usbdevfs_ctrltransfer structure.
299         unsafe {
300             self.ioctl_with_ref(usb_sys::USBDEVFS_CONTROL(), &ctrl_transfer)?;
301         }
302         Ok(active_config)
303     }
304 
305     /// Get the total number of configurations for this device.
get_num_configurations(&self) -> u8306     pub fn get_num_configurations(&self) -> u8 {
307         self.device_descriptor_tree.bNumConfigurations
308     }
309 
310     /// Clear the halt/stall condition for an endpoint.
clear_halt(&self, ep_addr: u8) -> Result<()>311     pub fn clear_halt(&self, ep_addr: u8) -> Result<()> {
312         let endpoint: c_uint = ep_addr.into();
313         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
314         // pointer to unsigned int.
315         unsafe {
316             self.ioctl_with_ref(usb_sys::USBDEVFS_CLEAR_HALT(), &endpoint)?;
317         }
318 
319         Ok(())
320     }
321 }
322 
323 impl AsRawDescriptor for Device {
as_raw_descriptor(&self) -> RawDescriptor324     fn as_raw_descriptor(&self) -> RawDescriptor {
325         self.fd.as_raw_descriptor()
326     }
327 }
328 
329 impl Transfer {
urb(&self) -> &usb_sys::usbdevfs_urb330     fn urb(&self) -> &usb_sys::usbdevfs_urb {
331         // self.urb is a Vec created with `vec_with_array_field`; the first entry is
332         // the URB itself.
333         &self.urb[0]
334     }
335 
urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb336     fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb {
337         &mut self.urb[0]
338     }
339 
new( transfer_type: u8, endpoint: u8, buffer: Vec<u8>, iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], ) -> Result<Transfer>340     fn new(
341         transfer_type: u8,
342         endpoint: u8,
343         buffer: Vec<u8>,
344         iso_packets: &[usb_sys::usbdevfs_iso_packet_desc],
345     ) -> Result<Transfer> {
346         let mut transfer = Transfer {
347             urb: vec_with_array_field::<usb_sys::usbdevfs_urb, usb_sys::usbdevfs_iso_packet_desc>(
348                 iso_packets.len(),
349             ),
350             buffer,
351             callback: None,
352         };
353 
354         transfer.urb_mut().urb_type = transfer_type;
355         transfer.urb_mut().endpoint = endpoint;
356         transfer.urb_mut().buffer = transfer.buffer.as_mut_ptr() as *mut c_void;
357         transfer.urb_mut().buffer_length = transfer
358             .buffer
359             .len()
360             .try_into()
361             .map_err(Error::InvalidBufferLength)?;
362 
363         // Safe because we ensured there is enough space in transfer.urb to hold the number of
364         // isochronous frames required.
365         let iso_frame_desc = unsafe {
366             transfer
367                 .urb_mut()
368                 .iso_frame_desc
369                 .as_mut_slice(iso_packets.len())
370         };
371         iso_frame_desc.copy_from_slice(iso_packets);
372 
373         Ok(transfer)
374     }
375 
376     /// Create a control transfer.
new_control(buffer: Vec<u8>) -> Result<Transfer>377     pub fn new_control(buffer: Vec<u8>) -> Result<Transfer> {
378         let endpoint = 0;
379         Self::new(usb_sys::USBDEVFS_URB_TYPE_CONTROL, endpoint, buffer, &[])
380     }
381 
382     /// Create an interrupt transfer.
new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>383     pub fn new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
384         Self::new(usb_sys::USBDEVFS_URB_TYPE_INTERRUPT, endpoint, buffer, &[])
385     }
386 
387     /// Create a bulk transfer.
new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>388     pub fn new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
389         Self::new(usb_sys::USBDEVFS_URB_TYPE_BULK, endpoint, buffer, &[])
390     }
391 
392     /// Create an isochronous transfer.
new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>393     pub fn new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> {
394         // TODO(dverkamp): allow user to specify iso descriptors
395         Self::new(usb_sys::USBDEVFS_URB_TYPE_ISO, endpoint, buffer, &[])
396     }
397 
398     /// Get the status of a completed transfer.
status(&self) -> TransferStatus399     pub fn status(&self) -> TransferStatus {
400         let status = self.urb().status;
401         if status == 0 {
402             TransferStatus::Completed
403         } else if status == -ENODEV {
404             TransferStatus::NoDevice
405         } else if status == -ENOENT {
406             TransferStatus::Cancelled
407         } else {
408             TransferStatus::Error
409         }
410     }
411 
412     /// Get the actual amount of data transferred, which may be less than
413     /// the original length.
actual_length(&self) -> usize414     pub fn actual_length(&self) -> usize {
415         self.urb().actual_length as usize
416     }
417 
418     /// Set callback function for transfer completion.
set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C)419     pub fn set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C) {
420         self.callback = Some(Box::new(cb));
421     }
422 }
423 
424 impl TransferHandle {
425     /// Attempt to cancel the transfer associated with this `TransferHandle`.
426     /// Safe to call even if the transfer has already completed;
427     /// `Error::TransferAlreadyCompleted` will be returned in this case.
cancel(self) -> Result<()>428     pub fn cancel(self) -> Result<()> {
429         let rc_transfer = match self.weak_transfer.upgrade() {
430             None => return Err(Error::TransferAlreadyCompleted),
431             Some(rc_transfer) => rc_transfer,
432         };
433 
434         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
435         let fd = match self.fd.upgrade() {
436             None => return Err(Error::NoDevice),
437             Some(fd) => fd,
438         };
439 
440         // Safe because fd is a valid usbdevfs file descriptor and we pass a valid
441         // pointer to a usbdevfs_urb structure.
442         if unsafe {
443             handle_eintr_errno!(base::ioctl_with_mut_ptr(
444                 &*fd,
445                 usb_sys::USBDEVFS_DISCARDURB(),
446                 urb_ptr
447             ))
448         } < 0
449         {
450             return Err(Error::IoctlFailed(
451                 usb_sys::USBDEVFS_DISCARDURB(),
452                 base::Error::last(),
453             ));
454         }
455 
456         Ok(())
457     }
458 }
459