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