usb_util/
device.rs

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
5use std::convert::TryInto;
6use std::fs::File;
7use std::io::Read;
8use std::io::Seek;
9use std::io::SeekFrom;
10use std::mem::size_of_val;
11use std::os::raw::c_int;
12use std::os::raw::c_uchar;
13use std::os::raw::c_uint;
14use std::os::raw::c_void;
15use std::sync::Arc;
16use std::sync::Weak;
17
18use base::error;
19use base::handle_eintr_errno;
20use base::warn;
21use base::AsRawDescriptor;
22use base::IoctlNr;
23use base::MappedRegion;
24use base::MemoryMapping;
25use base::MemoryMappingBuilder;
26use base::Protection;
27use base::RawDescriptor;
28use data_model::vec_with_array_field;
29use libc::EAGAIN;
30use libc::ENODEV;
31use libc::ENOENT;
32use libc::EPIPE;
33use sync::Mutex;
34
35use crate::control_request_type;
36use crate::descriptor;
37use crate::ConfigDescriptorTree;
38use crate::ControlRequestDataPhaseTransferDirection;
39use crate::ControlRequestRecipient;
40use crate::ControlRequestType;
41use crate::DeviceDescriptor;
42use crate::DeviceDescriptorTree;
43use crate::DeviceSpeed;
44use crate::Error;
45use crate::Result;
46use crate::StandardControlRequest;
47
48// This is the maximum block size observed during storage performance test
49const MMAP_SIZE: usize = 1024 * 1024;
50
51/// ManagedDmaBuffer represents the entire DMA buffer allocated by a device
52struct 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
60pub struct DmaBuffer {
61    /// Host virtual address of the buffer
62    addr: u64,
63    /// Size of the buffer
64    size: usize,
65}
66
67impl DmaBuffer {
68    pub fn address(&mut self) -> *mut c_void {
69        self.addr as *mut c_void
70    }
71
72    pub fn size(&self) -> usize {
73        self.size
74    }
75
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
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)]
91pub enum TransferBuffer {
92    Vector(Vec<u8>),
93    Dma(Weak<Mutex<DmaBuffer>>),
94}
95
96impl TransferBuffer {
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    }
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.
112pub 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.
120pub 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.
132pub struct TransferHandle {
133    weak_transfer: std::sync::Weak<Transfer>,
134    fd: std::sync::Weak<File>,
135}
136
137#[derive(PartialEq, Eq, Clone, Copy)]
138pub enum TransferStatus {
139    Completed,
140    Error,
141    Cancelled,
142    NoDevice,
143    Stalled,
144}
145
146impl 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`).
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
184    pub fn fd(&self) -> Arc<File> {
185        self.fd.clone()
186    }
187
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
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
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
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
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
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.
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.
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.
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.
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()`.
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.
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.
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.
430    pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
431        Ok(*self.device_descriptor_tree)
432    }
433
434    pub fn get_device_descriptor_tree(&self) -> &DeviceDescriptorTree {
435        &self.device_descriptor_tree
436    }
437
438    /// Get active config descriptor of this device.
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.
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.
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.
496    pub fn get_num_configurations(&self) -> u8 {
497        self.device_descriptor_tree.bNumConfigurations
498    }
499
500    /// Clear the halt/stall condition for an endpoint.
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.
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
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
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
567impl AsRawDescriptor for Device {
568    fn as_raw_descriptor(&self) -> RawDescriptor {
569        self.fd.as_raw_descriptor()
570    }
571}
572
573impl Transfer {
574    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
580    fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb {
581        &mut self.urb[0]
582    }
583
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.
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.
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.
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.
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.
653    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.
670    pub fn actual_length(&self) -> usize {
671        self.urb().actual_length as usize
672    }
673
674    /// Set callback function for transfer completion.
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
680impl 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.
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}