xref: /aosp_15_r20/external/crosvm/usb_util/src/device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of_val;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_int;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_uchar;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_uint;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_void;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Weak;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::handle_eintr_errno;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::IoctlNr;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::MappedRegion;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
28*bb4ee6a4SAndroid Build Coastguard Worker use data_model::vec_with_array_field;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::EAGAIN;
30*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENODEV;
31*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOENT;
32*bb4ee6a4SAndroid Build Coastguard Worker use libc::EPIPE;
33*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
34*bb4ee6a4SAndroid Build Coastguard Worker 
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::control_request_type;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::ConfigDescriptorTree;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::ControlRequestDataPhaseTransferDirection;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::ControlRequestRecipient;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::ControlRequestType;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceDescriptor;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceDescriptorTree;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceSpeed;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::StandardControlRequest;
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker // This is the maximum block size observed during storage performance test
49*bb4ee6a4SAndroid Build Coastguard Worker const MMAP_SIZE: usize = 1024 * 1024;
50*bb4ee6a4SAndroid Build Coastguard Worker 
51*bb4ee6a4SAndroid Build Coastguard Worker /// ManagedDmaBuffer represents the entire DMA buffer allocated by a device
52*bb4ee6a4SAndroid Build Coastguard Worker struct ManagedDmaBuffer {
53*bb4ee6a4SAndroid Build Coastguard Worker     /// The entire DMA buffer
54*bb4ee6a4SAndroid Build Coastguard Worker     buf: MemoryMapping,
55*bb4ee6a4SAndroid Build Coastguard Worker     /// A DMA buffer lent to a TransferBuffer. This is a part of the entire buffer.
56*bb4ee6a4SAndroid Build Coastguard Worker     used: Option<Arc<Mutex<DmaBuffer>>>,
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker /// DmaBuffer represents a DMA buffer lent by a device
60*bb4ee6a4SAndroid Build Coastguard Worker pub struct DmaBuffer {
61*bb4ee6a4SAndroid Build Coastguard Worker     /// Host virtual address of the buffer
62*bb4ee6a4SAndroid Build Coastguard Worker     addr: u64,
63*bb4ee6a4SAndroid Build Coastguard Worker     /// Size of the buffer
64*bb4ee6a4SAndroid Build Coastguard Worker     size: usize,
65*bb4ee6a4SAndroid Build Coastguard Worker }
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker impl DmaBuffer {
address(&mut self) -> *mut c_void68*bb4ee6a4SAndroid Build Coastguard Worker     pub fn address(&mut self) -> *mut c_void {
69*bb4ee6a4SAndroid Build Coastguard Worker         self.addr as *mut c_void
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker 
size(&self) -> usize72*bb4ee6a4SAndroid Build Coastguard Worker     pub fn size(&self) -> usize {
73*bb4ee6a4SAndroid Build Coastguard Worker         self.size
74*bb4ee6a4SAndroid Build Coastguard Worker     }
75*bb4ee6a4SAndroid Build Coastguard Worker 
as_slice(&self) -> &[u8]76*bb4ee6a4SAndroid Build Coastguard Worker     pub fn as_slice(&self) -> &[u8] {
77*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
78*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the region has been lent by a device
79*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { std::slice::from_raw_parts(self.addr as *const u8, self.size) }
80*bb4ee6a4SAndroid Build Coastguard Worker     }
81*bb4ee6a4SAndroid Build Coastguard Worker 
as_mut_slice(&mut self) -> &mut [u8]82*bb4ee6a4SAndroid Build Coastguard Worker     pub fn as_mut_slice(&mut self) -> &mut [u8] {
83*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
84*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the region has been lent by a device
85*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { std::slice::from_raw_parts_mut(self.addr as *mut u8, self.size) }
86*bb4ee6a4SAndroid Build Coastguard Worker     }
87*bb4ee6a4SAndroid Build Coastguard Worker }
88*bb4ee6a4SAndroid Build Coastguard Worker 
89*bb4ee6a4SAndroid Build Coastguard Worker /// TransferBuffer is used for data transfer between crosvm and the host kernel
90*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
91*bb4ee6a4SAndroid Build Coastguard Worker pub enum TransferBuffer {
92*bb4ee6a4SAndroid Build Coastguard Worker     Vector(Vec<u8>),
93*bb4ee6a4SAndroid Build Coastguard Worker     Dma(Weak<Mutex<DmaBuffer>>),
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker impl TransferBuffer {
address(&mut self) -> Option<*mut c_void>97*bb4ee6a4SAndroid Build Coastguard Worker     pub fn address(&mut self) -> Option<*mut c_void> {
98*bb4ee6a4SAndroid Build Coastguard Worker         match self {
99*bb4ee6a4SAndroid Build Coastguard Worker             TransferBuffer::Vector(v) => Some(v.as_mut_ptr() as *mut c_void),
100*bb4ee6a4SAndroid Build Coastguard Worker             TransferBuffer::Dma(buf) => buf.upgrade().map(|buf| buf.lock().address()),
101*bb4ee6a4SAndroid Build Coastguard Worker         }
102*bb4ee6a4SAndroid Build Coastguard Worker     }
size(&self) -> Option<usize>103*bb4ee6a4SAndroid Build Coastguard Worker     pub fn size(&self) -> Option<usize> {
104*bb4ee6a4SAndroid Build Coastguard Worker         match self {
105*bb4ee6a4SAndroid Build Coastguard Worker             TransferBuffer::Vector(v) => Some(v.len()),
106*bb4ee6a4SAndroid Build Coastguard Worker             TransferBuffer::Dma(buf) => buf.upgrade().map(|buf| buf.lock().size()),
107*bb4ee6a4SAndroid Build Coastguard Worker         }
108*bb4ee6a4SAndroid Build Coastguard Worker     }
109*bb4ee6a4SAndroid Build Coastguard Worker }
110*bb4ee6a4SAndroid Build Coastguard Worker 
111*bb4ee6a4SAndroid Build Coastguard Worker /// Device represents a USB device.
112*bb4ee6a4SAndroid Build Coastguard Worker pub struct Device {
113*bb4ee6a4SAndroid Build Coastguard Worker     fd: Arc<File>,
114*bb4ee6a4SAndroid Build Coastguard Worker     device_descriptor_tree: DeviceDescriptorTree,
115*bb4ee6a4SAndroid Build Coastguard Worker     dma_buffer: Option<ManagedDmaBuffer>,
116*bb4ee6a4SAndroid Build Coastguard Worker }
117*bb4ee6a4SAndroid Build Coastguard Worker 
118*bb4ee6a4SAndroid Build Coastguard Worker /// Transfer contains the information necessary to submit a USB request
119*bb4ee6a4SAndroid Build Coastguard Worker /// and, once it has been submitted and completed, contains the response.
120*bb4ee6a4SAndroid Build Coastguard Worker pub struct Transfer {
121*bb4ee6a4SAndroid Build Coastguard Worker     // NOTE: This Vec is actually a single URB with a trailing
122*bb4ee6a4SAndroid Build Coastguard Worker     // variable-length field created by vec_with_array_field().
123*bb4ee6a4SAndroid Build Coastguard Worker     urb: Vec<usb_sys::usbdevfs_urb>,
124*bb4ee6a4SAndroid Build Coastguard Worker     pub buffer: TransferBuffer,
125*bb4ee6a4SAndroid Build Coastguard Worker     callback: Option<Box<dyn Fn(Transfer) + Send + Sync>>,
126*bb4ee6a4SAndroid Build Coastguard Worker }
127*bb4ee6a4SAndroid Build Coastguard Worker 
128*bb4ee6a4SAndroid Build Coastguard Worker /// TransferHandle is a handle that allows cancellation of in-flight transfers
129*bb4ee6a4SAndroid Build Coastguard Worker /// between submit_transfer() and get_completed_transfer().
130*bb4ee6a4SAndroid Build Coastguard Worker /// Attempting to cancel a transfer that has already completed is safe and will
131*bb4ee6a4SAndroid Build Coastguard Worker /// return an error.
132*bb4ee6a4SAndroid Build Coastguard Worker pub struct TransferHandle {
133*bb4ee6a4SAndroid Build Coastguard Worker     weak_transfer: std::sync::Weak<Transfer>,
134*bb4ee6a4SAndroid Build Coastguard Worker     fd: std::sync::Weak<File>,
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq, Eq, Clone, Copy)]
138*bb4ee6a4SAndroid Build Coastguard Worker pub enum TransferStatus {
139*bb4ee6a4SAndroid Build Coastguard Worker     Completed,
140*bb4ee6a4SAndroid Build Coastguard Worker     Error,
141*bb4ee6a4SAndroid Build Coastguard Worker     Cancelled,
142*bb4ee6a4SAndroid Build Coastguard Worker     NoDevice,
143*bb4ee6a4SAndroid Build Coastguard Worker     Stalled,
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker impl Device {
147*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new `Device` from a file descriptor.
148*bb4ee6a4SAndroid Build Coastguard Worker     /// `fd` should be a file in usbdevfs (e.g. `/dev/bus/usb/001/002`).
new(mut fd: File) -> Result<Self>149*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(mut fd: File) -> Result<Self> {
150*bb4ee6a4SAndroid Build Coastguard Worker         fd.seek(SeekFrom::Start(0)).map_err(Error::DescriptorRead)?;
151*bb4ee6a4SAndroid Build Coastguard Worker         let mut descriptor_data = Vec::new();
152*bb4ee6a4SAndroid Build Coastguard Worker         fd.read_to_end(&mut descriptor_data)
153*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::DescriptorRead)?;
154*bb4ee6a4SAndroid Build Coastguard Worker         let device_descriptor_tree = descriptor::parse_usbfs_descriptors(&descriptor_data)?;
155*bb4ee6a4SAndroid Build Coastguard Worker 
156*bb4ee6a4SAndroid Build Coastguard Worker         let mut device = Device {
157*bb4ee6a4SAndroid Build Coastguard Worker             fd: Arc::new(fd),
158*bb4ee6a4SAndroid Build Coastguard Worker             device_descriptor_tree,
159*bb4ee6a4SAndroid Build Coastguard Worker             dma_buffer: None,
160*bb4ee6a4SAndroid Build Coastguard Worker         };
161*bb4ee6a4SAndroid Build Coastguard Worker 
162*bb4ee6a4SAndroid Build Coastguard Worker         let map = MemoryMappingBuilder::new(MMAP_SIZE)
163*bb4ee6a4SAndroid Build Coastguard Worker             .from_file(&device.fd)
164*bb4ee6a4SAndroid Build Coastguard Worker             .protection(Protection::read_write())
165*bb4ee6a4SAndroid Build Coastguard Worker             .build();
166*bb4ee6a4SAndroid Build Coastguard Worker         match map {
167*bb4ee6a4SAndroid Build Coastguard Worker             Ok(map) => {
168*bb4ee6a4SAndroid Build Coastguard Worker                 device.dma_buffer = Some(ManagedDmaBuffer {
169*bb4ee6a4SAndroid Build Coastguard Worker                     buf: map,
170*bb4ee6a4SAndroid Build Coastguard Worker                     used: None,
171*bb4ee6a4SAndroid Build Coastguard Worker                 });
172*bb4ee6a4SAndroid Build Coastguard Worker             }
173*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
174*bb4ee6a4SAndroid Build Coastguard Worker                 // Ignore the error since we can process requests without DMA buffer
175*bb4ee6a4SAndroid Build Coastguard Worker                 warn!(
176*bb4ee6a4SAndroid Build Coastguard Worker                     "mmap() failed. User-provided buffer will be used for data transfer. {}",
177*bb4ee6a4SAndroid Build Coastguard Worker                     e
178*bb4ee6a4SAndroid Build Coastguard Worker                 );
179*bb4ee6a4SAndroid Build Coastguard Worker             }
180*bb4ee6a4SAndroid Build Coastguard Worker         }
181*bb4ee6a4SAndroid Build Coastguard Worker         Ok(device)
182*bb4ee6a4SAndroid Build Coastguard Worker     }
183*bb4ee6a4SAndroid Build Coastguard Worker 
fd(&self) -> Arc<File>184*bb4ee6a4SAndroid Build Coastguard Worker     pub fn fd(&self) -> Arc<File> {
185*bb4ee6a4SAndroid Build Coastguard Worker         self.fd.clone()
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
ioctl(&self, nr: IoctlNr) -> Result<i32>188*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn ioctl(&self, nr: IoctlNr) -> Result<i32> {
189*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(base::ioctl(&*self.fd, nr));
190*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
191*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::IoctlFailed(nr, base::Error::last()));
192*bb4ee6a4SAndroid Build Coastguard Worker         }
193*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ret)
194*bb4ee6a4SAndroid Build Coastguard Worker     }
195*bb4ee6a4SAndroid Build Coastguard Worker 
ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32>196*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32> {
197*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(base::ioctl_with_ref(&*self.fd, nr, arg));
198*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
199*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::IoctlFailed(nr, base::Error::last()));
200*bb4ee6a4SAndroid Build Coastguard Worker         }
201*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ret)
202*bb4ee6a4SAndroid Build Coastguard Worker     }
203*bb4ee6a4SAndroid Build Coastguard Worker 
ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32>204*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32> {
205*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(&*self.fd, nr, arg));
206*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
207*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::IoctlFailed(nr, base::Error::last()));
208*bb4ee6a4SAndroid Build Coastguard Worker         }
209*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ret)
210*bb4ee6a4SAndroid Build Coastguard Worker     }
211*bb4ee6a4SAndroid Build Coastguard Worker 
ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32>212*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32> {
213*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(base::ioctl_with_mut_ptr(&*self.fd, nr, arg));
214*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
215*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::IoctlFailed(nr, base::Error::last()));
216*bb4ee6a4SAndroid Build Coastguard Worker         }
217*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ret)
218*bb4ee6a4SAndroid Build Coastguard Worker     }
219*bb4ee6a4SAndroid Build Coastguard Worker 
reserve_dma_buffer(&mut self, size: usize) -> Result<Weak<Mutex<DmaBuffer>>>220*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserve_dma_buffer(&mut self, size: usize) -> Result<Weak<Mutex<DmaBuffer>>> {
221*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(managed) = &mut self.dma_buffer {
222*bb4ee6a4SAndroid Build Coastguard Worker             if managed.used.is_none() {
223*bb4ee6a4SAndroid Build Coastguard Worker                 let buf = Arc::new(Mutex::new(DmaBuffer {
224*bb4ee6a4SAndroid Build Coastguard Worker                     addr: managed.buf.as_ptr() as u64,
225*bb4ee6a4SAndroid Build Coastguard Worker                     size,
226*bb4ee6a4SAndroid Build Coastguard Worker                 }));
227*bb4ee6a4SAndroid Build Coastguard Worker                 let ret = Ok(Arc::downgrade(&buf));
228*bb4ee6a4SAndroid Build Coastguard Worker                 managed.used = Some(buf);
229*bb4ee6a4SAndroid Build Coastguard Worker                 return ret;
230*bb4ee6a4SAndroid Build Coastguard Worker             }
231*bb4ee6a4SAndroid Build Coastguard Worker         }
232*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::GetDmaBufferFailed(size))
233*bb4ee6a4SAndroid Build Coastguard Worker     }
234*bb4ee6a4SAndroid Build Coastguard Worker 
release_dma_buffer(&mut self, dmabuf: Weak<Mutex<DmaBuffer>>) -> Result<()>235*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_dma_buffer(&mut self, dmabuf: Weak<Mutex<DmaBuffer>>) -> Result<()> {
236*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(managed) = &mut self.dma_buffer {
237*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(released) = dmabuf.upgrade() {
238*bb4ee6a4SAndroid Build Coastguard Worker                 let addr = { released.lock().address() as u64 };
239*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(lent) = &managed.used {
240*bb4ee6a4SAndroid Build Coastguard Worker                     if lent.lock().addr == addr {
241*bb4ee6a4SAndroid Build Coastguard Worker                         managed.used = None;
242*bb4ee6a4SAndroid Build Coastguard Worker                         return Ok(());
243*bb4ee6a4SAndroid Build Coastguard Worker                     }
244*bb4ee6a4SAndroid Build Coastguard Worker                 }
245*bb4ee6a4SAndroid Build Coastguard Worker             }
246*bb4ee6a4SAndroid Build Coastguard Worker         }
247*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::ReleaseDmaBufferFailed)
248*bb4ee6a4SAndroid Build Coastguard Worker     }
249*bb4ee6a4SAndroid Build Coastguard Worker 
250*bb4ee6a4SAndroid Build Coastguard Worker     /// Submit a transfer to the device.
251*bb4ee6a4SAndroid Build Coastguard Worker     /// The transfer will be processed asynchronously by the device.
252*bb4ee6a4SAndroid Build Coastguard Worker     /// Call `poll_transfers()` on this device to check for completed transfers.
submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle>253*bb4ee6a4SAndroid Build Coastguard Worker     pub fn submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle> {
254*bb4ee6a4SAndroid Build Coastguard Worker         let mut rc_transfer = Arc::new(transfer);
255*bb4ee6a4SAndroid Build Coastguard Worker 
256*bb4ee6a4SAndroid Build Coastguard Worker         // Technically, Arc::from_raw() should only be called on pointers returned
257*bb4ee6a4SAndroid Build Coastguard Worker         // from Arc::into_raw(). However, we need to stash this value inside the
258*bb4ee6a4SAndroid Build Coastguard Worker         // Arc<Transfer> itself, so we manually calculate the address that would be
259*bb4ee6a4SAndroid Build Coastguard Worker         // returned from Arc::into_raw() via Deref and then call Arc::into_raw()
260*bb4ee6a4SAndroid Build Coastguard Worker         // to forget the Arc without dropping its contents.
261*bb4ee6a4SAndroid Build Coastguard Worker         // Do not remove the into_raw() call!
262*bb4ee6a4SAndroid Build Coastguard Worker         let raw_transfer = (&*rc_transfer) as *const Transfer as usize;
263*bb4ee6a4SAndroid Build Coastguard Worker         match Arc::get_mut(&mut rc_transfer) {
264*bb4ee6a4SAndroid Build Coastguard Worker             Some(t) => t.urb_mut().usercontext = raw_transfer,
265*bb4ee6a4SAndroid Build Coastguard Worker             None => {
266*bb4ee6a4SAndroid Build Coastguard Worker                 // This should never happen, since there is only one strong reference
267*bb4ee6a4SAndroid Build Coastguard Worker                 // at this point.
268*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::RcGetMutFailed);
269*bb4ee6a4SAndroid Build Coastguard Worker             }
270*bb4ee6a4SAndroid Build Coastguard Worker         }
271*bb4ee6a4SAndroid Build Coastguard Worker         let _ = Arc::into_raw(rc_transfer.clone());
272*bb4ee6a4SAndroid Build Coastguard Worker 
273*bb4ee6a4SAndroid Build Coastguard Worker         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
276*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we control the lifetime of the URB via Arc::into_raw() and
277*bb4ee6a4SAndroid Build Coastguard Worker         // Arc::from_raw() in poll_transfers().
278*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
279*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_mut_ptr(usb_sys::USBDEVFS_SUBMITURB, urb_ptr)?;
280*bb4ee6a4SAndroid Build Coastguard Worker         }
281*bb4ee6a4SAndroid Build Coastguard Worker 
282*bb4ee6a4SAndroid Build Coastguard Worker         let weak_transfer = Arc::downgrade(&rc_transfer);
283*bb4ee6a4SAndroid Build Coastguard Worker 
284*bb4ee6a4SAndroid Build Coastguard Worker         Ok(TransferHandle {
285*bb4ee6a4SAndroid Build Coastguard Worker             weak_transfer,
286*bb4ee6a4SAndroid Build Coastguard Worker             fd: Arc::downgrade(&self.fd),
287*bb4ee6a4SAndroid Build Coastguard Worker         })
288*bb4ee6a4SAndroid Build Coastguard Worker     }
289*bb4ee6a4SAndroid Build Coastguard Worker 
290*bb4ee6a4SAndroid Build Coastguard Worker     /// Check for completed asynchronous transfers submitted via `submit_transfer()`.
291*bb4ee6a4SAndroid Build Coastguard Worker     /// The callback for each completed transfer will be called.
poll_transfers(&mut self) -> Result<()>292*bb4ee6a4SAndroid Build Coastguard Worker     pub fn poll_transfers(&mut self) -> Result<()> {
293*bb4ee6a4SAndroid Build Coastguard Worker         // Reap completed transfers until we get EAGAIN.
294*bb4ee6a4SAndroid Build Coastguard Worker         loop {
295*bb4ee6a4SAndroid Build Coastguard Worker             let mut urb_ptr: *mut usb_sys::usbdevfs_urb = std::ptr::null_mut();
296*bb4ee6a4SAndroid Build Coastguard Worker             let result =
297*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
298*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we provide a valid urb_ptr to be filled by the kernel.
299*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { self.ioctl_with_mut_ref(usb_sys::USBDEVFS_REAPURBNDELAY, &mut urb_ptr) };
300*bb4ee6a4SAndroid Build Coastguard Worker             match result {
301*bb4ee6a4SAndroid Build Coastguard Worker                 // EAGAIN indicates no more completed transfers right now.
302*bb4ee6a4SAndroid Build Coastguard Worker                 Err(Error::IoctlFailed(_nr, e)) if e.errno() == EAGAIN => break,
303*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => return Err(e),
304*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(_) => {}
305*bb4ee6a4SAndroid Build Coastguard Worker             }
306*bb4ee6a4SAndroid Build Coastguard Worker 
307*bb4ee6a4SAndroid Build Coastguard Worker             if urb_ptr.is_null() {
308*bb4ee6a4SAndroid Build Coastguard Worker                 break;
309*bb4ee6a4SAndroid Build Coastguard Worker             }
310*bb4ee6a4SAndroid Build Coastguard Worker 
311*bb4ee6a4SAndroid Build Coastguard Worker             let rc_transfer: Arc<Transfer> =
312*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
313*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because the URB usercontext field is always set to the result of
314*bb4ee6a4SAndroid Build Coastguard Worker             // Arc::into_raw() in submit_transfer().
315*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { Arc::from_raw((*urb_ptr).usercontext as *const Transfer) };
316*bb4ee6a4SAndroid Build Coastguard Worker 
317*bb4ee6a4SAndroid Build Coastguard Worker             // There should always be exactly one strong reference to rc_transfer,
318*bb4ee6a4SAndroid Build Coastguard Worker             // so try_unwrap() should never fail.
319*bb4ee6a4SAndroid Build Coastguard Worker             let mut transfer = Arc::try_unwrap(rc_transfer).map_err(|_| Error::RcUnwrapFailed)?;
320*bb4ee6a4SAndroid Build Coastguard Worker 
321*bb4ee6a4SAndroid Build Coastguard Worker             let dmabuf = match &mut transfer.buffer {
322*bb4ee6a4SAndroid Build Coastguard Worker                 TransferBuffer::Dma(buf) => Some(buf.clone()),
323*bb4ee6a4SAndroid Build Coastguard Worker                 TransferBuffer::Vector(_) => None,
324*bb4ee6a4SAndroid Build Coastguard Worker             };
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(cb) = transfer.callback.take() {
327*bb4ee6a4SAndroid Build Coastguard Worker                 cb(transfer);
328*bb4ee6a4SAndroid Build Coastguard Worker             }
329*bb4ee6a4SAndroid Build Coastguard Worker 
330*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(dmabuf) = dmabuf {
331*bb4ee6a4SAndroid Build Coastguard Worker                 if self.release_dma_buffer(dmabuf).is_err() {
332*bb4ee6a4SAndroid Build Coastguard Worker                     warn!("failed to release dma buffer");
333*bb4ee6a4SAndroid Build Coastguard Worker                 }
334*bb4ee6a4SAndroid Build Coastguard Worker             }
335*bb4ee6a4SAndroid Build Coastguard Worker         }
336*bb4ee6a4SAndroid Build Coastguard Worker 
337*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
338*bb4ee6a4SAndroid Build Coastguard Worker     }
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker     /// Perform a USB port reset to reinitialize a device.
reset(&self) -> Result<()>341*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reset(&self) -> Result<()> {
342*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(dverkamp): re-enable reset once crbug.com/1058059 is resolved.
343*bb4ee6a4SAndroid Build Coastguard Worker         // Skip reset for all non-Edge TPU devices.
344*bb4ee6a4SAndroid Build Coastguard Worker         let vid = self.device_descriptor_tree.idVendor;
345*bb4ee6a4SAndroid Build Coastguard Worker         let pid = self.device_descriptor_tree.idProduct;
346*bb4ee6a4SAndroid Build Coastguard Worker         match (vid, pid) {
347*bb4ee6a4SAndroid Build Coastguard Worker             (0x1a6e, 0x089a) => (),
348*bb4ee6a4SAndroid Build Coastguard Worker             _ => return Ok(()),
349*bb4ee6a4SAndroid Build Coastguard Worker         }
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
352*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor.
353*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { self.ioctl(usb_sys::USBDEVFS_RESET) };
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(Error::IoctlFailed(_nr, errno_err)) = result {
356*bb4ee6a4SAndroid Build Coastguard Worker             // The device may disappear after a reset if e.g. its firmware changed.
357*bb4ee6a4SAndroid Build Coastguard Worker             // Treat that as success.
358*bb4ee6a4SAndroid Build Coastguard Worker             if errno_err.errno() == libc::ENODEV {
359*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(());
360*bb4ee6a4SAndroid Build Coastguard Worker             }
361*bb4ee6a4SAndroid Build Coastguard Worker         }
362*bb4ee6a4SAndroid Build Coastguard Worker 
363*bb4ee6a4SAndroid Build Coastguard Worker         result?;
364*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
365*bb4ee6a4SAndroid Build Coastguard Worker     }
366*bb4ee6a4SAndroid Build Coastguard Worker 
367*bb4ee6a4SAndroid Build Coastguard Worker     /// Claim an interface on this device.
claim_interface(&self, interface_number: u8) -> Result<()>368*bb4ee6a4SAndroid Build Coastguard Worker     pub fn claim_interface(&self, interface_number: u8) -> Result<()> {
369*bb4ee6a4SAndroid Build Coastguard Worker         let disconnect_claim = usb_sys::usbdevfs_disconnect_claim {
370*bb4ee6a4SAndroid Build Coastguard Worker             interface: interface_number.into(),
371*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
372*bb4ee6a4SAndroid Build Coastguard Worker             driver: [0u8; 256],
373*bb4ee6a4SAndroid Build Coastguard Worker         };
374*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
375*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
376*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevs_disconnect_claim structure.
377*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
378*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_DISCONNECT_CLAIM, &disconnect_claim)?;
379*bb4ee6a4SAndroid Build Coastguard Worker         }
380*bb4ee6a4SAndroid Build Coastguard Worker 
381*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
382*bb4ee6a4SAndroid Build Coastguard Worker     }
383*bb4ee6a4SAndroid Build Coastguard Worker 
384*bb4ee6a4SAndroid Build Coastguard Worker     /// Release an interface previously claimed with `claim_interface()`.
release_interface(&self, interface_number: u8) -> Result<()>385*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_interface(&self, interface_number: u8) -> Result<()> {
386*bb4ee6a4SAndroid Build Coastguard Worker         let ifnum: c_uint = interface_number.into();
387*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
388*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
389*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to unsigned int.
390*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
391*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_RELEASEINTERFACE, &ifnum)?;
392*bb4ee6a4SAndroid Build Coastguard Worker         }
393*bb4ee6a4SAndroid Build Coastguard Worker 
394*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
395*bb4ee6a4SAndroid Build Coastguard Worker     }
396*bb4ee6a4SAndroid Build Coastguard Worker 
397*bb4ee6a4SAndroid Build Coastguard Worker     /// Activate an alternate setting for an interface.
set_interface_alt_setting( &self, interface_number: u8, alternative_setting: u8, ) -> Result<()>398*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_interface_alt_setting(
399*bb4ee6a4SAndroid Build Coastguard Worker         &self,
400*bb4ee6a4SAndroid Build Coastguard Worker         interface_number: u8,
401*bb4ee6a4SAndroid Build Coastguard Worker         alternative_setting: u8,
402*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
403*bb4ee6a4SAndroid Build Coastguard Worker         let setinterface = usb_sys::usbdevfs_setinterface {
404*bb4ee6a4SAndroid Build Coastguard Worker             interface: interface_number.into(),
405*bb4ee6a4SAndroid Build Coastguard Worker             altsetting: alternative_setting.into(),
406*bb4ee6a4SAndroid Build Coastguard Worker         };
407*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
408*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
409*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevfs_setinterface structure.
410*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
411*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_SETINTERFACE, &setinterface)?;
412*bb4ee6a4SAndroid Build Coastguard Worker         }
413*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
414*bb4ee6a4SAndroid Build Coastguard Worker     }
415*bb4ee6a4SAndroid Build Coastguard Worker 
416*bb4ee6a4SAndroid Build Coastguard Worker     /// Set active configuration for this device.
set_active_configuration(&mut self, config: u8) -> Result<()>417*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_active_configuration(&mut self, config: u8) -> Result<()> {
418*bb4ee6a4SAndroid Build Coastguard Worker         let config: c_int = config.into();
419*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
420*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
421*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to int.
422*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
423*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_SETCONFIGURATION, &config)?;
424*bb4ee6a4SAndroid Build Coastguard Worker         }
425*bb4ee6a4SAndroid Build Coastguard Worker 
426*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
427*bb4ee6a4SAndroid Build Coastguard Worker     }
428*bb4ee6a4SAndroid Build Coastguard Worker 
429*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the device descriptor of this device.
get_device_descriptor(&self) -> Result<DeviceDescriptor>430*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
431*bb4ee6a4SAndroid Build Coastguard Worker         Ok(*self.device_descriptor_tree)
432*bb4ee6a4SAndroid Build Coastguard Worker     }
433*bb4ee6a4SAndroid Build Coastguard Worker 
get_device_descriptor_tree(&self) -> &DeviceDescriptorTree434*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_device_descriptor_tree(&self) -> &DeviceDescriptorTree {
435*bb4ee6a4SAndroid Build Coastguard Worker         &self.device_descriptor_tree
436*bb4ee6a4SAndroid Build Coastguard Worker     }
437*bb4ee6a4SAndroid Build Coastguard Worker 
438*bb4ee6a4SAndroid Build Coastguard Worker     /// Get active config descriptor of this device.
get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree>439*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree> {
440*bb4ee6a4SAndroid Build Coastguard Worker         match self.device_descriptor_tree.get_config_descriptor(config) {
441*bb4ee6a4SAndroid Build Coastguard Worker             Some(config_descriptor) => Ok(config_descriptor.clone()),
442*bb4ee6a4SAndroid Build Coastguard Worker             None => Err(Error::NoSuchDescriptor),
443*bb4ee6a4SAndroid Build Coastguard Worker         }
444*bb4ee6a4SAndroid Build Coastguard Worker     }
445*bb4ee6a4SAndroid Build Coastguard Worker 
446*bb4ee6a4SAndroid Build Coastguard Worker     /// Get a configuration descriptor by its index within the list of descriptors returned
447*bb4ee6a4SAndroid Build Coastguard Worker     /// by the device.
get_config_descriptor_by_index(&self, config_index: u8) -> Result<ConfigDescriptorTree>448*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_config_descriptor_by_index(&self, config_index: u8) -> Result<ConfigDescriptorTree> {
449*bb4ee6a4SAndroid Build Coastguard Worker         match self
450*bb4ee6a4SAndroid Build Coastguard Worker             .device_descriptor_tree
451*bb4ee6a4SAndroid Build Coastguard Worker             .get_config_descriptor_by_index(config_index)
452*bb4ee6a4SAndroid Build Coastguard Worker         {
453*bb4ee6a4SAndroid Build Coastguard Worker             Some(config_descriptor) => Ok(config_descriptor.clone()),
454*bb4ee6a4SAndroid Build Coastguard Worker             None => Err(Error::NoSuchDescriptor),
455*bb4ee6a4SAndroid Build Coastguard Worker         }
456*bb4ee6a4SAndroid Build Coastguard Worker     }
457*bb4ee6a4SAndroid Build Coastguard Worker 
458*bb4ee6a4SAndroid Build Coastguard Worker     /// Get bConfigurationValue of the currently active configuration.
get_active_configuration(&self) -> Result<u8>459*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_active_configuration(&self) -> Result<u8> {
460*bb4ee6a4SAndroid Build Coastguard Worker         // If the device only exposes a single configuration, bypass the control transfer below
461*bb4ee6a4SAndroid Build Coastguard Worker         // by looking up the configuration value from the descriptor.
462*bb4ee6a4SAndroid Build Coastguard Worker         if self.device_descriptor_tree.bNumConfigurations == 1 {
463*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(config_descriptor) = self
464*bb4ee6a4SAndroid Build Coastguard Worker                 .device_descriptor_tree
465*bb4ee6a4SAndroid Build Coastguard Worker                 .get_config_descriptor_by_index(0)
466*bb4ee6a4SAndroid Build Coastguard Worker             {
467*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(config_descriptor.bConfigurationValue);
468*bb4ee6a4SAndroid Build Coastguard Worker             }
469*bb4ee6a4SAndroid Build Coastguard Worker         }
470*bb4ee6a4SAndroid Build Coastguard Worker 
471*bb4ee6a4SAndroid Build Coastguard Worker         // Send a synchronous control transfer to get the active configuration.
472*bb4ee6a4SAndroid Build Coastguard Worker         let mut active_config: u8 = 0;
473*bb4ee6a4SAndroid Build Coastguard Worker         let ctrl_transfer = usb_sys::usbdevfs_ctrltransfer {
474*bb4ee6a4SAndroid Build Coastguard Worker             bRequestType: control_request_type(
475*bb4ee6a4SAndroid Build Coastguard Worker                 ControlRequestType::Standard,
476*bb4ee6a4SAndroid Build Coastguard Worker                 ControlRequestDataPhaseTransferDirection::DeviceToHost,
477*bb4ee6a4SAndroid Build Coastguard Worker                 ControlRequestRecipient::Device,
478*bb4ee6a4SAndroid Build Coastguard Worker             ),
479*bb4ee6a4SAndroid Build Coastguard Worker             bRequest: StandardControlRequest::GetConfiguration as u8,
480*bb4ee6a4SAndroid Build Coastguard Worker             wValue: 0,
481*bb4ee6a4SAndroid Build Coastguard Worker             wIndex: 0,
482*bb4ee6a4SAndroid Build Coastguard Worker             wLength: size_of_val(&active_config) as u16,
483*bb4ee6a4SAndroid Build Coastguard Worker             timeout: 5000, // milliseconds
484*bb4ee6a4SAndroid Build Coastguard Worker             data: &mut active_config as *mut u8 as *mut c_void,
485*bb4ee6a4SAndroid Build Coastguard Worker         };
486*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
487*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
488*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevfs_ctrltransfer structure.
489*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
490*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_CONTROL, &ctrl_transfer)?;
491*bb4ee6a4SAndroid Build Coastguard Worker         }
492*bb4ee6a4SAndroid Build Coastguard Worker         Ok(active_config)
493*bb4ee6a4SAndroid Build Coastguard Worker     }
494*bb4ee6a4SAndroid Build Coastguard Worker 
495*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the total number of configurations for this device.
get_num_configurations(&self) -> u8496*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_num_configurations(&self) -> u8 {
497*bb4ee6a4SAndroid Build Coastguard Worker         self.device_descriptor_tree.bNumConfigurations
498*bb4ee6a4SAndroid Build Coastguard Worker     }
499*bb4ee6a4SAndroid Build Coastguard Worker 
500*bb4ee6a4SAndroid Build Coastguard Worker     /// Clear the halt/stall condition for an endpoint.
clear_halt(&self, ep_addr: u8) -> Result<()>501*bb4ee6a4SAndroid Build Coastguard Worker     pub fn clear_halt(&self, ep_addr: u8) -> Result<()> {
502*bb4ee6a4SAndroid Build Coastguard Worker         let endpoint: c_uint = ep_addr.into();
503*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
504*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
505*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to unsigned int.
506*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
507*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_CLEAR_HALT, &endpoint)?;
508*bb4ee6a4SAndroid Build Coastguard Worker         }
509*bb4ee6a4SAndroid Build Coastguard Worker 
510*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
511*bb4ee6a4SAndroid Build Coastguard Worker     }
512*bb4ee6a4SAndroid Build Coastguard Worker 
513*bb4ee6a4SAndroid Build Coastguard Worker     /// Get speed of this device.
get_speed(&self) -> Result<Option<DeviceSpeed>>514*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_speed(&self) -> Result<Option<DeviceSpeed>> {
515*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: args are valid and the return value is checked
516*bb4ee6a4SAndroid Build Coastguard Worker         let speed = unsafe { self.ioctl(usb_sys::USBDEVFS_GET_SPEED) }?;
517*bb4ee6a4SAndroid Build Coastguard Worker         match speed {
518*bb4ee6a4SAndroid Build Coastguard Worker             1 => Ok(Some(DeviceSpeed::Low)),       // Low Speed
519*bb4ee6a4SAndroid Build Coastguard Worker             2 => Ok(Some(DeviceSpeed::Full)),      // Full Speed
520*bb4ee6a4SAndroid Build Coastguard Worker             3 => Ok(Some(DeviceSpeed::High)),      // High Speed
521*bb4ee6a4SAndroid Build Coastguard Worker             4 => Ok(Some(DeviceSpeed::High)),      // Wireless, treat as a High Speed device
522*bb4ee6a4SAndroid Build Coastguard Worker             5 => Ok(Some(DeviceSpeed::Super)),     // Super Speed
523*bb4ee6a4SAndroid Build Coastguard Worker             6 => Ok(Some(DeviceSpeed::SuperPlus)), // Super Speed Plus
524*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
525*bb4ee6a4SAndroid Build Coastguard Worker                 error!("unexpected speed: {:?}", speed);
526*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(None)
527*bb4ee6a4SAndroid Build Coastguard Worker             }
528*bb4ee6a4SAndroid Build Coastguard Worker         }
529*bb4ee6a4SAndroid Build Coastguard Worker     }
530*bb4ee6a4SAndroid Build Coastguard Worker 
531*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate streams for the endpoint
alloc_streams(&self, ep: u8, num_streams: u16) -> Result<()>532*bb4ee6a4SAndroid Build Coastguard Worker     pub fn alloc_streams(&self, ep: u8, num_streams: u16) -> Result<()> {
533*bb4ee6a4SAndroid Build Coastguard Worker         let mut streams = vec_with_array_field::<usb_sys::usbdevfs_streams, c_uchar>(1);
534*bb4ee6a4SAndroid Build Coastguard Worker         streams[0].num_streams = num_streams as c_uint;
535*bb4ee6a4SAndroid Build Coastguard Worker         streams[0].num_eps = 1 as c_uint;
536*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
537*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we have allocated enough memory
538*bb4ee6a4SAndroid Build Coastguard Worker         let eps = unsafe { streams[0].eps.as_mut_slice(1) };
539*bb4ee6a4SAndroid Build Coastguard Worker         eps[0] = ep as c_uchar;
540*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
541*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
542*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevfs_streams structure.
543*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
544*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_ALLOC_STREAMS, &streams[0])?;
545*bb4ee6a4SAndroid Build Coastguard Worker         }
546*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
547*bb4ee6a4SAndroid Build Coastguard Worker     }
548*bb4ee6a4SAndroid Build Coastguard Worker 
549*bb4ee6a4SAndroid Build Coastguard Worker     /// Free streams for the endpoint
free_streams(&self, ep: u8) -> Result<()>550*bb4ee6a4SAndroid Build Coastguard Worker     pub fn free_streams(&self, ep: u8) -> Result<()> {
551*bb4ee6a4SAndroid Build Coastguard Worker         let mut streams = vec_with_array_field::<usb_sys::usbdevfs_streams, c_uchar>(1);
552*bb4ee6a4SAndroid Build Coastguard Worker         streams[0].num_eps = 1 as c_uint;
553*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
554*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we have allocated enough memory
555*bb4ee6a4SAndroid Build Coastguard Worker         let eps = unsafe { streams[0].eps.as_mut_slice(1) };
556*bb4ee6a4SAndroid Build Coastguard Worker         eps[0] = ep as c_uchar;
557*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
558*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid
559*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevfs_streams structure.
560*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
561*bb4ee6a4SAndroid Build Coastguard Worker             self.ioctl_with_ref(usb_sys::USBDEVFS_FREE_STREAMS, &streams[0])?;
562*bb4ee6a4SAndroid Build Coastguard Worker         }
563*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
564*bb4ee6a4SAndroid Build Coastguard Worker     }
565*bb4ee6a4SAndroid Build Coastguard Worker }
566*bb4ee6a4SAndroid Build Coastguard Worker 
567*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for Device {
as_raw_descriptor(&self) -> RawDescriptor568*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
569*bb4ee6a4SAndroid Build Coastguard Worker         self.fd.as_raw_descriptor()
570*bb4ee6a4SAndroid Build Coastguard Worker     }
571*bb4ee6a4SAndroid Build Coastguard Worker }
572*bb4ee6a4SAndroid Build Coastguard Worker 
573*bb4ee6a4SAndroid Build Coastguard Worker impl Transfer {
urb(&self) -> &usb_sys::usbdevfs_urb574*bb4ee6a4SAndroid Build Coastguard Worker     fn urb(&self) -> &usb_sys::usbdevfs_urb {
575*bb4ee6a4SAndroid Build Coastguard Worker         // self.urb is a Vec created with `vec_with_array_field`; the first entry is
576*bb4ee6a4SAndroid Build Coastguard Worker         // the URB itself.
577*bb4ee6a4SAndroid Build Coastguard Worker         &self.urb[0]
578*bb4ee6a4SAndroid Build Coastguard Worker     }
579*bb4ee6a4SAndroid Build Coastguard Worker 
urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb580*bb4ee6a4SAndroid Build Coastguard Worker     fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb {
581*bb4ee6a4SAndroid Build Coastguard Worker         &mut self.urb[0]
582*bb4ee6a4SAndroid Build Coastguard Worker     }
583*bb4ee6a4SAndroid Build Coastguard Worker 
new( transfer_type: u8, endpoint: u8, buffer: TransferBuffer, iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], ) -> Result<Transfer>584*bb4ee6a4SAndroid Build Coastguard Worker     fn new(
585*bb4ee6a4SAndroid Build Coastguard Worker         transfer_type: u8,
586*bb4ee6a4SAndroid Build Coastguard Worker         endpoint: u8,
587*bb4ee6a4SAndroid Build Coastguard Worker         buffer: TransferBuffer,
588*bb4ee6a4SAndroid Build Coastguard Worker         iso_packets: &[usb_sys::usbdevfs_iso_packet_desc],
589*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Transfer> {
590*bb4ee6a4SAndroid Build Coastguard Worker         let mut transfer = Transfer {
591*bb4ee6a4SAndroid Build Coastguard Worker             urb: vec_with_array_field::<usb_sys::usbdevfs_urb, usb_sys::usbdevfs_iso_packet_desc>(
592*bb4ee6a4SAndroid Build Coastguard Worker                 iso_packets.len(),
593*bb4ee6a4SAndroid Build Coastguard Worker             ),
594*bb4ee6a4SAndroid Build Coastguard Worker             buffer,
595*bb4ee6a4SAndroid Build Coastguard Worker             callback: None,
596*bb4ee6a4SAndroid Build Coastguard Worker         };
597*bb4ee6a4SAndroid Build Coastguard Worker 
598*bb4ee6a4SAndroid Build Coastguard Worker         transfer.urb_mut().urb_type = transfer_type;
599*bb4ee6a4SAndroid Build Coastguard Worker         transfer.urb_mut().endpoint = endpoint;
600*bb4ee6a4SAndroid Build Coastguard Worker         transfer.urb_mut().buffer = transfer.buffer.address().ok_or(Error::InvalidBuffer)?;
601*bb4ee6a4SAndroid Build Coastguard Worker         transfer.urb_mut().buffer_length = transfer
602*bb4ee6a4SAndroid Build Coastguard Worker             .buffer
603*bb4ee6a4SAndroid Build Coastguard Worker             .size()
604*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidBuffer)?
605*bb4ee6a4SAndroid Build Coastguard Worker             .try_into()
606*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::InvalidBufferLength)?;
607*bb4ee6a4SAndroid Build Coastguard Worker 
608*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
609*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we ensured there is enough space in transfer.urb to hold the number of
610*bb4ee6a4SAndroid Build Coastguard Worker         // isochronous frames required.
611*bb4ee6a4SAndroid Build Coastguard Worker         let iso_frame_desc = unsafe {
612*bb4ee6a4SAndroid Build Coastguard Worker             transfer
613*bb4ee6a4SAndroid Build Coastguard Worker                 .urb_mut()
614*bb4ee6a4SAndroid Build Coastguard Worker                 .iso_frame_desc
615*bb4ee6a4SAndroid Build Coastguard Worker                 .as_mut_slice(iso_packets.len())
616*bb4ee6a4SAndroid Build Coastguard Worker         };
617*bb4ee6a4SAndroid Build Coastguard Worker         iso_frame_desc.copy_from_slice(iso_packets);
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker         Ok(transfer)
620*bb4ee6a4SAndroid Build Coastguard Worker     }
621*bb4ee6a4SAndroid Build Coastguard Worker 
622*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a control transfer.
new_control(buffer: TransferBuffer) -> Result<Transfer>623*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_control(buffer: TransferBuffer) -> Result<Transfer> {
624*bb4ee6a4SAndroid Build Coastguard Worker         let endpoint = 0;
625*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(usb_sys::USBDEVFS_URB_TYPE_CONTROL, endpoint, buffer, &[])
626*bb4ee6a4SAndroid Build Coastguard Worker     }
627*bb4ee6a4SAndroid Build Coastguard Worker 
628*bb4ee6a4SAndroid Build Coastguard Worker     /// Create an interrupt transfer.
new_interrupt(endpoint: u8, buffer: TransferBuffer) -> Result<Transfer>629*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_interrupt(endpoint: u8, buffer: TransferBuffer) -> Result<Transfer> {
630*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(usb_sys::USBDEVFS_URB_TYPE_INTERRUPT, endpoint, buffer, &[])
631*bb4ee6a4SAndroid Build Coastguard Worker     }
632*bb4ee6a4SAndroid Build Coastguard Worker 
633*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a bulk transfer.
new_bulk( endpoint: u8, buffer: TransferBuffer, stream_id: Option<u16>, ) -> Result<Transfer>634*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_bulk(
635*bb4ee6a4SAndroid Build Coastguard Worker         endpoint: u8,
636*bb4ee6a4SAndroid Build Coastguard Worker         buffer: TransferBuffer,
637*bb4ee6a4SAndroid Build Coastguard Worker         stream_id: Option<u16>,
638*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Transfer> {
639*bb4ee6a4SAndroid Build Coastguard Worker         let mut transfer = Self::new(usb_sys::USBDEVFS_URB_TYPE_BULK, endpoint, buffer, &[])?;
640*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(stream_id) = stream_id {
641*bb4ee6a4SAndroid Build Coastguard Worker             transfer.urb_mut().number_of_packets_or_stream_id = stream_id as u32;
642*bb4ee6a4SAndroid Build Coastguard Worker         }
643*bb4ee6a4SAndroid Build Coastguard Worker         Ok(transfer)
644*bb4ee6a4SAndroid Build Coastguard Worker     }
645*bb4ee6a4SAndroid Build Coastguard Worker 
646*bb4ee6a4SAndroid Build Coastguard Worker     /// Create an isochronous transfer.
new_isochronous(endpoint: u8, buffer: TransferBuffer) -> Result<Transfer>647*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_isochronous(endpoint: u8, buffer: TransferBuffer) -> Result<Transfer> {
648*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(dverkamp): allow user to specify iso descriptors
649*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(usb_sys::USBDEVFS_URB_TYPE_ISO, endpoint, buffer, &[])
650*bb4ee6a4SAndroid Build Coastguard Worker     }
651*bb4ee6a4SAndroid Build Coastguard Worker 
652*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the status of a completed transfer.
status(&self) -> TransferStatus653*bb4ee6a4SAndroid Build Coastguard Worker     pub fn status(&self) -> TransferStatus {
654*bb4ee6a4SAndroid Build Coastguard Worker         let status = self.urb().status;
655*bb4ee6a4SAndroid Build Coastguard Worker         if status == 0 {
656*bb4ee6a4SAndroid Build Coastguard Worker             TransferStatus::Completed
657*bb4ee6a4SAndroid Build Coastguard Worker         } else if status == -ENODEV {
658*bb4ee6a4SAndroid Build Coastguard Worker             TransferStatus::NoDevice
659*bb4ee6a4SAndroid Build Coastguard Worker         } else if status == -ENOENT {
660*bb4ee6a4SAndroid Build Coastguard Worker             TransferStatus::Cancelled
661*bb4ee6a4SAndroid Build Coastguard Worker         } else if status == -EPIPE {
662*bb4ee6a4SAndroid Build Coastguard Worker             TransferStatus::Stalled
663*bb4ee6a4SAndroid Build Coastguard Worker         } else {
664*bb4ee6a4SAndroid Build Coastguard Worker             TransferStatus::Error
665*bb4ee6a4SAndroid Build Coastguard Worker         }
666*bb4ee6a4SAndroid Build Coastguard Worker     }
667*bb4ee6a4SAndroid Build Coastguard Worker 
668*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the actual amount of data transferred, which may be less than
669*bb4ee6a4SAndroid Build Coastguard Worker     /// the original length.
actual_length(&self) -> usize670*bb4ee6a4SAndroid Build Coastguard Worker     pub fn actual_length(&self) -> usize {
671*bb4ee6a4SAndroid Build Coastguard Worker         self.urb().actual_length as usize
672*bb4ee6a4SAndroid Build Coastguard Worker     }
673*bb4ee6a4SAndroid Build Coastguard Worker 
674*bb4ee6a4SAndroid Build Coastguard Worker     /// Set callback function for transfer completion.
set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C)675*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C) {
676*bb4ee6a4SAndroid Build Coastguard Worker         self.callback = Some(Box::new(cb));
677*bb4ee6a4SAndroid Build Coastguard Worker     }
678*bb4ee6a4SAndroid Build Coastguard Worker }
679*bb4ee6a4SAndroid Build Coastguard Worker 
680*bb4ee6a4SAndroid Build Coastguard Worker impl TransferHandle {
681*bb4ee6a4SAndroid Build Coastguard Worker     /// Attempt to cancel the transfer associated with this `TransferHandle`.
682*bb4ee6a4SAndroid Build Coastguard Worker     /// Safe to call even if the transfer has already completed;
683*bb4ee6a4SAndroid Build Coastguard Worker     /// `Error::TransferAlreadyCompleted` will be returned in this case.
cancel(&self) -> Result<()>684*bb4ee6a4SAndroid Build Coastguard Worker     pub fn cancel(&self) -> Result<()> {
685*bb4ee6a4SAndroid Build Coastguard Worker         let rc_transfer = match self.weak_transfer.upgrade() {
686*bb4ee6a4SAndroid Build Coastguard Worker             None => return Err(Error::TransferAlreadyCompleted),
687*bb4ee6a4SAndroid Build Coastguard Worker             Some(rc_transfer) => rc_transfer,
688*bb4ee6a4SAndroid Build Coastguard Worker         };
689*bb4ee6a4SAndroid Build Coastguard Worker 
690*bb4ee6a4SAndroid Build Coastguard Worker         let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb;
691*bb4ee6a4SAndroid Build Coastguard Worker         let fd = match self.fd.upgrade() {
692*bb4ee6a4SAndroid Build Coastguard Worker             None => return Err(Error::NoDevice),
693*bb4ee6a4SAndroid Build Coastguard Worker             Some(fd) => fd,
694*bb4ee6a4SAndroid Build Coastguard Worker         };
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
697*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because fd is a valid usbdevfs file descriptor and we pass a valid
698*bb4ee6a4SAndroid Build Coastguard Worker         // pointer to a usbdevfs_urb structure.
699*bb4ee6a4SAndroid Build Coastguard Worker         if unsafe {
700*bb4ee6a4SAndroid Build Coastguard Worker             handle_eintr_errno!(base::ioctl_with_mut_ptr(
701*bb4ee6a4SAndroid Build Coastguard Worker                 &*fd,
702*bb4ee6a4SAndroid Build Coastguard Worker                 usb_sys::USBDEVFS_DISCARDURB,
703*bb4ee6a4SAndroid Build Coastguard Worker                 urb_ptr
704*bb4ee6a4SAndroid Build Coastguard Worker             ))
705*bb4ee6a4SAndroid Build Coastguard Worker         } < 0
706*bb4ee6a4SAndroid Build Coastguard Worker         {
707*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::IoctlFailed(
708*bb4ee6a4SAndroid Build Coastguard Worker                 usb_sys::USBDEVFS_DISCARDURB,
709*bb4ee6a4SAndroid Build Coastguard Worker                 base::Error::last(),
710*bb4ee6a4SAndroid Build Coastguard Worker             ));
711*bb4ee6a4SAndroid Build Coastguard Worker         }
712*bb4ee6a4SAndroid Build Coastguard Worker 
713*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
714*bb4ee6a4SAndroid Build Coastguard Worker     }
715*bb4ee6a4SAndroid Build Coastguard Worker }
716