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