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