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