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