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