1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 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 crate::{ 6 control_request_type, descriptor, ConfigDescriptorTree, 7 ControlRequestDataPhaseTransferDirection, ControlRequestRecipient, ControlRequestType, 8 DeviceDescriptor, DeviceDescriptorTree, Error, Result, StandardControlRequest, 9 }; 10 use base::{handle_eintr_errno, AsRawDescriptor, IoctlNr, RawDescriptor}; 11 use data_model::vec_with_array_field; 12 use libc::{EAGAIN, ENODEV, ENOENT}; 13 use std::convert::TryInto; 14 use std::fs::File; 15 use std::io::{Seek, SeekFrom}; 16 use std::mem::size_of_val; 17 use std::os::raw::{c_int, c_uint, c_void}; 18 use std::sync::Arc; 19 20 /// Device represents a USB device. 21 pub struct Device { 22 fd: Arc<File>, 23 device_descriptor_tree: DeviceDescriptorTree, 24 } 25 26 /// Transfer contains the information necessary to submit a USB request 27 /// and, once it has been submitted and completed, contains the response. 28 pub struct Transfer { 29 // NOTE: This Vec is actually a single URB with a trailing 30 // variable-length field created by vec_with_array_field(). 31 urb: Vec<usb_sys::usbdevfs_urb>, 32 pub buffer: Vec<u8>, 33 callback: Option<Box<dyn Fn(Transfer) + Send + Sync>>, 34 } 35 36 /// TransferHandle is a handle that allows cancellation of in-flight transfers 37 /// between submit_transfer() and get_completed_transfer(). 38 /// Attempting to cancel a transfer that has already completed is safe and will 39 /// return an error. 40 pub struct TransferHandle { 41 weak_transfer: std::sync::Weak<Transfer>, 42 fd: std::sync::Weak<File>, 43 } 44 45 #[derive(PartialEq)] 46 pub enum TransferStatus { 47 Completed, 48 Error, 49 Cancelled, 50 NoDevice, 51 } 52 53 impl Device { 54 /// Create a new `Device` from a file descriptor. 55 /// `fd` should be a file in usbdevfs (e.g. `/dev/bus/usb/001/002`). new(mut fd: File) -> Result<Self>56 pub fn new(mut fd: File) -> Result<Self> { 57 fd.seek(SeekFrom::Start(0)).map_err(Error::DescriptorRead)?; 58 let device_descriptor_tree = descriptor::parse_usbfs_descriptors(&mut fd)?; 59 60 let device = Device { 61 fd: Arc::new(fd), 62 device_descriptor_tree, 63 }; 64 Ok(device) 65 } 66 fd(&self) -> Arc<File>67 pub fn fd(&self) -> Arc<File> { 68 self.fd.clone() 69 } 70 ioctl(&self, nr: IoctlNr) -> Result<i32>71 unsafe fn ioctl(&self, nr: IoctlNr) -> Result<i32> { 72 let ret = handle_eintr_errno!(base::ioctl(&*self.fd, nr)); 73 if ret < 0 { 74 return Err(Error::IoctlFailed(nr, base::Error::last())); 75 } 76 Ok(ret) 77 } 78 ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32>79 unsafe fn ioctl_with_ref<T>(&self, nr: IoctlNr, arg: &T) -> Result<i32> { 80 let ret = handle_eintr_errno!(base::ioctl_with_ref(&*self.fd, nr, arg)); 81 if ret < 0 { 82 return Err(Error::IoctlFailed(nr, base::Error::last())); 83 } 84 Ok(ret) 85 } 86 ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32>87 unsafe fn ioctl_with_mut_ref<T>(&self, nr: IoctlNr, arg: &mut T) -> Result<i32> { 88 let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(&*self.fd, nr, arg)); 89 if ret < 0 { 90 return Err(Error::IoctlFailed(nr, base::Error::last())); 91 } 92 Ok(ret) 93 } 94 ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32>95 unsafe fn ioctl_with_mut_ptr<T>(&self, nr: IoctlNr, arg: *mut T) -> Result<i32> { 96 let ret = handle_eintr_errno!(base::ioctl_with_mut_ptr(&*self.fd, nr, arg)); 97 if ret < 0 { 98 return Err(Error::IoctlFailed(nr, base::Error::last())); 99 } 100 Ok(ret) 101 } 102 103 /// Submit a transfer to the device. 104 /// The transfer will be processed asynchronously by the device. 105 /// Call `poll_transfers()` on this device to check for completed transfers. submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle>106 pub fn submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle> { 107 let mut rc_transfer = Arc::new(transfer); 108 109 // Technically, Arc::from_raw() should only be called on pointers returned 110 // from Arc::into_raw(). However, we need to stash this value inside the 111 // Arc<Transfer> itself, so we manually calculate the address that would be 112 // returned from Arc::into_raw() via Deref and then call Arc::into_raw() 113 // to forget the Arc without dropping its contents. 114 // Do not remove the into_raw() call! 115 let raw_transfer = (&*rc_transfer) as *const Transfer as usize; 116 match Arc::get_mut(&mut rc_transfer) { 117 Some(t) => t.urb_mut().usercontext = raw_transfer, 118 None => { 119 // This should never happen, since there is only one strong reference 120 // at this point. 121 return Err(Error::RcGetMutFailed); 122 } 123 } 124 let _ = Arc::into_raw(rc_transfer.clone()); 125 126 let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb; 127 128 // Safe because we control the lifetime of the URB via Arc::into_raw() and 129 // Arc::from_raw() in poll_transfers(). 130 unsafe { 131 self.ioctl_with_mut_ptr(usb_sys::USBDEVFS_SUBMITURB(), urb_ptr)?; 132 } 133 134 let weak_transfer = Arc::downgrade(&rc_transfer); 135 136 Ok(TransferHandle { 137 weak_transfer, 138 fd: Arc::downgrade(&self.fd), 139 }) 140 } 141 142 /// Check for completed asynchronous transfers submitted via `submit_transfer()`. 143 /// The callback for each completed transfer will be called. poll_transfers(&self) -> Result<()>144 pub fn poll_transfers(&self) -> Result<()> { 145 // Reap completed transfers until we get EAGAIN. 146 loop { 147 let mut urb_ptr: *mut usb_sys::usbdevfs_urb = std::ptr::null_mut(); 148 // Safe because we provide a valid urb_ptr to be filled by the kernel. 149 let result = 150 unsafe { self.ioctl_with_mut_ref(usb_sys::USBDEVFS_REAPURBNDELAY(), &mut urb_ptr) }; 151 match result { 152 Err(Error::IoctlFailed(_nr, e)) => { 153 if e.errno() == EAGAIN { 154 // No more completed transfers right now. 155 break; 156 } 157 } 158 Err(e) => return Err(e), 159 Ok(_) => {} 160 } 161 162 if urb_ptr.is_null() { 163 break; 164 } 165 166 // Safe because the URB usercontext field is always set to the result of 167 // Arc::into_raw() in submit_transfer(). 168 let rc_transfer: Arc<Transfer> = 169 unsafe { Arc::from_raw((*urb_ptr).usercontext as *const Transfer) }; 170 171 // There should always be exactly one strong reference to rc_transfer, 172 // so try_unwrap() should never fail. 173 let mut transfer = Arc::try_unwrap(rc_transfer).map_err(|_| Error::RcUnwrapFailed)?; 174 175 if let Some(cb) = transfer.callback.take() { 176 cb(transfer); 177 } 178 } 179 180 Ok(()) 181 } 182 183 /// Perform a USB port reset to reinitialize a device. reset(&self) -> Result<()>184 pub fn reset(&self) -> Result<()> { 185 // TODO(dverkamp): re-enable reset once crbug.com/1058059 is resolved. 186 // Skip reset for all non-Edge TPU devices. 187 let vid = self.device_descriptor_tree.idVendor; 188 let pid = self.device_descriptor_tree.idProduct; 189 match (vid, pid) { 190 (0x1a6e, 0x089a) => (), 191 _ => return Ok(()), 192 } 193 194 // Safe because self.fd is a valid usbdevfs file descriptor. 195 let result = unsafe { self.ioctl(usb_sys::USBDEVFS_RESET()) }; 196 197 if let Err(Error::IoctlFailed(_nr, errno_err)) = result { 198 // The device may disappear after a reset if e.g. its firmware changed. 199 // Treat that as success. 200 if errno_err.errno() == libc::ENODEV { 201 return Ok(()); 202 } 203 } 204 205 result?; 206 Ok(()) 207 } 208 209 /// Claim an interface on this device. claim_interface(&self, interface_number: u8) -> Result<()>210 pub fn claim_interface(&self, interface_number: u8) -> Result<()> { 211 let disconnect_claim = usb_sys::usbdevfs_disconnect_claim { 212 interface: interface_number.into(), 213 flags: 0, 214 driver: [0u8; 256], 215 }; 216 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 217 // pointer to a usbdevs_disconnect_claim structure. 218 unsafe { 219 self.ioctl_with_ref(usb_sys::USBDEVFS_DISCONNECT_CLAIM(), &disconnect_claim)?; 220 } 221 222 Ok(()) 223 } 224 225 /// Release an interface previously claimed with `claim_interface()`. release_interface(&self, interface_number: u8) -> Result<()>226 pub fn release_interface(&self, interface_number: u8) -> Result<()> { 227 let ifnum: c_uint = interface_number.into(); 228 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 229 // pointer to unsigned int. 230 unsafe { 231 self.ioctl_with_ref(usb_sys::USBDEVFS_RELEASEINTERFACE(), &ifnum)?; 232 } 233 234 Ok(()) 235 } 236 237 /// Activate an alternate setting for an interface. set_interface_alt_setting( &self, interface_number: u8, alternative_setting: u8, ) -> Result<()>238 pub fn set_interface_alt_setting( 239 &self, 240 interface_number: u8, 241 alternative_setting: u8, 242 ) -> Result<()> { 243 let setinterface = usb_sys::usbdevfs_setinterface { 244 interface: interface_number.into(), 245 altsetting: alternative_setting.into(), 246 }; 247 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 248 // pointer to a usbdevfs_setinterface structure. 249 unsafe { 250 self.ioctl_with_ref(usb_sys::USBDEVFS_SETINTERFACE(), &setinterface)?; 251 } 252 Ok(()) 253 } 254 255 /// Set active configuration for this device. set_active_configuration(&mut self, config: u8) -> Result<()>256 pub fn set_active_configuration(&mut self, config: u8) -> Result<()> { 257 let config: c_int = config.into(); 258 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 259 // pointer to int. 260 unsafe { 261 self.ioctl_with_ref(usb_sys::USBDEVFS_SETCONFIGURATION(), &config)?; 262 } 263 264 Ok(()) 265 } 266 267 /// Get the device descriptor of this device. get_device_descriptor(&self) -> Result<DeviceDescriptor>268 pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> { 269 Ok(*self.device_descriptor_tree) 270 } 271 272 /// Get active config descriptor of this device. get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree>273 pub fn get_config_descriptor(&self, config: u8) -> Result<ConfigDescriptorTree> { 274 match self.device_descriptor_tree.get_config_descriptor(config) { 275 Some(config_descriptor) => Ok(config_descriptor.clone()), 276 None => Err(Error::NoSuchDescriptor), 277 } 278 } 279 280 /// Get bConfigurationValue of the currently active configuration. get_active_configuration(&self) -> Result<u8>281 pub fn get_active_configuration(&self) -> Result<u8> { 282 // Send a synchronous control transfer to get the active configuration. 283 let mut active_config: u8 = 0; 284 let ctrl_transfer = usb_sys::usbdevfs_ctrltransfer { 285 bRequestType: control_request_type( 286 ControlRequestType::Standard, 287 ControlRequestDataPhaseTransferDirection::DeviceToHost, 288 ControlRequestRecipient::Device, 289 ), 290 bRequest: StandardControlRequest::GetConfiguration as u8, 291 wValue: 0, 292 wIndex: 0, 293 wLength: size_of_val(&active_config) as u16, 294 timeout: 5000, // milliseconds 295 data: &mut active_config as *mut u8 as *mut c_void, 296 }; 297 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 298 // pointer to a usbdevfs_ctrltransfer structure. 299 unsafe { 300 self.ioctl_with_ref(usb_sys::USBDEVFS_CONTROL(), &ctrl_transfer)?; 301 } 302 Ok(active_config) 303 } 304 305 /// Get the total number of configurations for this device. get_num_configurations(&self) -> u8306 pub fn get_num_configurations(&self) -> u8 { 307 self.device_descriptor_tree.bNumConfigurations 308 } 309 310 /// Clear the halt/stall condition for an endpoint. clear_halt(&self, ep_addr: u8) -> Result<()>311 pub fn clear_halt(&self, ep_addr: u8) -> Result<()> { 312 let endpoint: c_uint = ep_addr.into(); 313 // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid 314 // pointer to unsigned int. 315 unsafe { 316 self.ioctl_with_ref(usb_sys::USBDEVFS_CLEAR_HALT(), &endpoint)?; 317 } 318 319 Ok(()) 320 } 321 } 322 323 impl AsRawDescriptor for Device { as_raw_descriptor(&self) -> RawDescriptor324 fn as_raw_descriptor(&self) -> RawDescriptor { 325 self.fd.as_raw_descriptor() 326 } 327 } 328 329 impl Transfer { urb(&self) -> &usb_sys::usbdevfs_urb330 fn urb(&self) -> &usb_sys::usbdevfs_urb { 331 // self.urb is a Vec created with `vec_with_array_field`; the first entry is 332 // the URB itself. 333 &self.urb[0] 334 } 335 urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb336 fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb { 337 &mut self.urb[0] 338 } 339 new( transfer_type: u8, endpoint: u8, buffer: Vec<u8>, iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], ) -> Result<Transfer>340 fn new( 341 transfer_type: u8, 342 endpoint: u8, 343 buffer: Vec<u8>, 344 iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], 345 ) -> Result<Transfer> { 346 let mut transfer = Transfer { 347 urb: vec_with_array_field::<usb_sys::usbdevfs_urb, usb_sys::usbdevfs_iso_packet_desc>( 348 iso_packets.len(), 349 ), 350 buffer, 351 callback: None, 352 }; 353 354 transfer.urb_mut().urb_type = transfer_type; 355 transfer.urb_mut().endpoint = endpoint; 356 transfer.urb_mut().buffer = transfer.buffer.as_mut_ptr() as *mut c_void; 357 transfer.urb_mut().buffer_length = transfer 358 .buffer 359 .len() 360 .try_into() 361 .map_err(Error::InvalidBufferLength)?; 362 363 // Safe because we ensured there is enough space in transfer.urb to hold the number of 364 // isochronous frames required. 365 let iso_frame_desc = unsafe { 366 transfer 367 .urb_mut() 368 .iso_frame_desc 369 .as_mut_slice(iso_packets.len()) 370 }; 371 iso_frame_desc.copy_from_slice(iso_packets); 372 373 Ok(transfer) 374 } 375 376 /// Create a control transfer. new_control(buffer: Vec<u8>) -> Result<Transfer>377 pub fn new_control(buffer: Vec<u8>) -> Result<Transfer> { 378 let endpoint = 0; 379 Self::new(usb_sys::USBDEVFS_URB_TYPE_CONTROL, endpoint, buffer, &[]) 380 } 381 382 /// Create an interrupt transfer. new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>383 pub fn new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { 384 Self::new(usb_sys::USBDEVFS_URB_TYPE_INTERRUPT, endpoint, buffer, &[]) 385 } 386 387 /// Create a bulk transfer. new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>388 pub fn new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { 389 Self::new(usb_sys::USBDEVFS_URB_TYPE_BULK, endpoint, buffer, &[]) 390 } 391 392 /// Create an isochronous transfer. new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer>393 pub fn new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { 394 // TODO(dverkamp): allow user to specify iso descriptors 395 Self::new(usb_sys::USBDEVFS_URB_TYPE_ISO, endpoint, buffer, &[]) 396 } 397 398 /// Get the status of a completed transfer. status(&self) -> TransferStatus399 pub fn status(&self) -> TransferStatus { 400 let status = self.urb().status; 401 if status == 0 { 402 TransferStatus::Completed 403 } else if status == -ENODEV { 404 TransferStatus::NoDevice 405 } else if status == -ENOENT { 406 TransferStatus::Cancelled 407 } else { 408 TransferStatus::Error 409 } 410 } 411 412 /// Get the actual amount of data transferred, which may be less than 413 /// the original length. actual_length(&self) -> usize414 pub fn actual_length(&self) -> usize { 415 self.urb().actual_length as usize 416 } 417 418 /// Set callback function for transfer completion. set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C)419 pub fn set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C) { 420 self.callback = Some(Box::new(cb)); 421 } 422 } 423 424 impl TransferHandle { 425 /// Attempt to cancel the transfer associated with this `TransferHandle`. 426 /// Safe to call even if the transfer has already completed; 427 /// `Error::TransferAlreadyCompleted` will be returned in this case. cancel(self) -> Result<()>428 pub fn cancel(self) -> Result<()> { 429 let rc_transfer = match self.weak_transfer.upgrade() { 430 None => return Err(Error::TransferAlreadyCompleted), 431 Some(rc_transfer) => rc_transfer, 432 }; 433 434 let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb; 435 let fd = match self.fd.upgrade() { 436 None => return Err(Error::NoDevice), 437 Some(fd) => fd, 438 }; 439 440 // Safe because fd is a valid usbdevfs file descriptor and we pass a valid 441 // pointer to a usbdevfs_urb structure. 442 if unsafe { 443 handle_eintr_errno!(base::ioctl_with_mut_ptr( 444 &*fd, 445 usb_sys::USBDEVFS_DISCARDURB(), 446 urb_ptr 447 )) 448 } < 0 449 { 450 return Err(Error::IoctlFailed( 451 usb_sys::USBDEVFS_DISCARDURB(), 452 base::Error::last(), 453 )); 454 } 455 456 Ok(()) 457 } 458 } 459