1 use std::{ 2 fmt::{self, Debug}, 3 mem, 4 ptr::NonNull, 5 sync::Mutex, 6 time::Duration, 7 }; 8 9 use libc::{c_int, c_uchar, c_uint}; 10 use libusb1_sys::{constants::*, *}; 11 12 use crate::{ 13 config_descriptor::ConfigDescriptor, 14 device::{self, Device}, 15 device_descriptor::DeviceDescriptor, 16 error::{self, Error}, 17 fields::{request_type, Direction, Recipient, RequestType}, 18 interface_descriptor::InterfaceDescriptor, 19 language::Language, 20 UsbContext, 21 }; 22 23 /// Bit set representing claimed USB interfaces. 24 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 25 struct ClaimedInterfaces { 26 inner: [u128; 2], 27 } 28 29 impl ClaimedInterfaces { 30 /// Create a new bit set. new() -> Self31 fn new() -> Self { 32 Self { inner: [0, 0] } 33 } 34 get_index_and_mask(interface: u8) -> (usize, u128)35 fn get_index_and_mask(interface: u8) -> (usize, u128) { 36 ((interface / 128) as usize, 1 << (interface % 128)) 37 } 38 39 /// Mark `interface` as claimed. insert(&mut self, interface: u8)40 fn insert(&mut self, interface: u8) { 41 let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface); 42 self.inner[index] |= mask; 43 } 44 45 /// Mark `interface` as not claimed. remove(&mut self, interface: u8)46 fn remove(&mut self, interface: u8) { 47 let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface); 48 self.inner[index] &= !mask; 49 } 50 51 /// Returns true if this set contains `interface`. contains(&self, interface: u8) -> bool52 fn contains(&self, interface: u8) -> bool { 53 let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface); 54 self.inner[index] & mask != 0 55 } 56 57 /// Returns a count of the interfaces contained in this set. size(&self) -> usize58 fn size(&self) -> usize { 59 self.inner.iter().map(|v| v.count_ones()).sum::<u32>() as usize 60 } 61 62 /// Returns an iterator over the interfaces in this set. iter(&self) -> ClaimedInterfacesIter63 fn iter(&self) -> ClaimedInterfacesIter { 64 ClaimedInterfacesIter::new(self) 65 } 66 } 67 68 /// Iterator over interfaces. 69 struct ClaimedInterfacesIter<'a> { 70 // Next interface to check as a possible value to return from the interator. 71 index: u16, 72 73 // Number of elements remaining in this iterator. 74 remaining: usize, 75 76 // The ClaimedInterfaces object that we're iterating over. 77 source: &'a ClaimedInterfaces, 78 } 79 80 impl ClaimedInterfacesIter<'_> { 81 /// Create a new iterator over the interfaces in `source`. new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter82 fn new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter { 83 ClaimedInterfacesIter { 84 index: 0, 85 remaining: source.size(), 86 source, 87 } 88 } 89 } 90 91 impl<'a> Iterator for ClaimedInterfacesIter<'a> { 92 type Item = u8; 93 next(&mut self) -> Option<u8>94 fn next(&mut self) -> Option<u8> { 95 while self.index <= u8::MAX as u16 { 96 let index = self.index as u8; 97 let contains = self.source.contains(index); 98 self.index += 1; 99 if contains { 100 self.remaining -= 1; 101 return Some(index); 102 } 103 } 104 None 105 } 106 size_hint(&self) -> (usize, Option<usize>)107 fn size_hint(&self) -> (usize, Option<usize>) { 108 (self.remaining, Some(self.remaining)) 109 } 110 } 111 112 /// A handle to an open USB device. 113 pub struct DeviceHandle<T: UsbContext> { 114 context: T, 115 handle: Option<NonNull<libusb_device_handle>>, 116 interfaces: Mutex<ClaimedInterfaces>, 117 } 118 119 impl<T: UsbContext> Drop for DeviceHandle<T> { 120 /// Closes the device. drop(&mut self)121 fn drop(&mut self) { 122 unsafe { 123 let interfaces = self.interfaces.lock().unwrap(); 124 for iface in interfaces.iter() { 125 libusb_release_interface(self.as_raw(), iface as c_int); 126 } 127 128 if let Some(handle) = self.handle { 129 libusb_close(handle.as_ptr()); 130 } 131 } 132 } 133 } 134 135 unsafe impl<T: UsbContext> Send for DeviceHandle<T> {} 136 unsafe impl<T: UsbContext> Sync for DeviceHandle<T> {} 137 138 impl<T: UsbContext> Debug for DeviceHandle<T> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 140 f.debug_struct("DeviceHandle") 141 .field("device", &self.device()) 142 .field("handle", &self.handle) 143 .field("interfaces", &*self.interfaces.lock().unwrap()) 144 .finish() 145 } 146 } 147 148 impl<T: UsbContext + PartialEq> PartialEq for DeviceHandle<T> { eq(&self, other: &Self) -> bool149 fn eq(&self, other: &Self) -> bool { 150 self.context == other.context 151 && self.handle == other.handle 152 && *self.interfaces.lock().unwrap() == *other.interfaces.lock().unwrap() 153 } 154 } 155 156 impl<T: UsbContext + PartialEq> Eq for DeviceHandle<T> {} 157 158 impl<T: UsbContext> DeviceHandle<T> { 159 /// Get the raw libusb_device_handle pointer, for advanced use in unsafe code. 160 /// 161 /// This structure tracks claimed interfaces, and will get out if sync if interfaces are 162 /// manipulated externally. Use only libusb endpoint IO functions. as_raw(&self) -> *mut libusb_device_handle163 pub fn as_raw(&self) -> *mut libusb_device_handle { 164 // Safety: handle is Some() after initialization 165 match self.handle { 166 Some(it) => it.as_ptr(), 167 _ => unreachable!(), 168 } 169 } 170 171 /// Consumes the `DeviceHandle`, returning the raw libusb_device_handle 172 /// pointer, for advanced use in unsafe code. 173 /// 174 /// # Safety 175 /// 176 /// Panics if you have any claimed interfaces on this handle. into_raw(mut self) -> *mut libusb_device_handle177 pub fn into_raw(mut self) -> *mut libusb_device_handle { 178 assert_eq!(self.interfaces.lock().unwrap().size(), 0); 179 match self.handle.take() { 180 Some(it) => it.as_ptr(), 181 _ => unreachable!(), 182 } 183 } 184 185 /// Get the context associated with this device context(&self) -> &T186 pub fn context(&self) -> &T { 187 &self.context 188 } 189 190 /// Get the device associated to this handle device(&self) -> Device<T>191 pub fn device(&self) -> Device<T> { 192 unsafe { 193 device::Device::from_libusb( 194 self.context.clone(), 195 std::ptr::NonNull::new_unchecked(libusb_get_device(self.as_raw())), 196 ) 197 } 198 } 199 200 /// # Safety 201 /// 202 /// Converts an existing `libusb_device_handle` pointer into a `DeviceHandle<T>`. 203 /// `handle` must be a pointer to a valid `libusb_device_handle`. Rusb assumes ownership of the handle, and will close it on `drop`. from_libusb( context: T, handle: NonNull<libusb_device_handle>, ) -> DeviceHandle<T>204 pub unsafe fn from_libusb( 205 context: T, 206 handle: NonNull<libusb_device_handle>, 207 ) -> DeviceHandle<T> { 208 DeviceHandle { 209 context, 210 handle: Some(handle), 211 interfaces: Mutex::new(ClaimedInterfaces::new()), 212 } 213 } 214 215 /// Returns the active configuration number. active_configuration(&self) -> crate::Result<u8>216 pub fn active_configuration(&self) -> crate::Result<u8> { 217 let mut config = mem::MaybeUninit::<c_int>::uninit(); 218 219 try_unsafe!(libusb_get_configuration(self.as_raw(), config.as_mut_ptr())); 220 Ok(unsafe { config.assume_init() } as u8) 221 } 222 223 /// Sets the device's active configuration. set_active_configuration(&self, config: u8) -> crate::Result<()>224 pub fn set_active_configuration(&self, config: u8) -> crate::Result<()> { 225 try_unsafe!(libusb_set_configuration(self.as_raw(), c_int::from(config))); 226 Ok(()) 227 } 228 229 /// Puts the device in an unconfigured state. unconfigure(&self) -> crate::Result<()>230 pub fn unconfigure(&self) -> crate::Result<()> { 231 try_unsafe!(libusb_set_configuration(self.as_raw(), -1)); 232 Ok(()) 233 } 234 235 /// Resets the device. reset(&self) -> crate::Result<()>236 pub fn reset(&self) -> crate::Result<()> { 237 try_unsafe!(libusb_reset_device(self.as_raw())); 238 Ok(()) 239 } 240 241 /// Clear the halt/stall condition for an endpoint. clear_halt(&self, endpoint: u8) -> crate::Result<()>242 pub fn clear_halt(&self, endpoint: u8) -> crate::Result<()> { 243 try_unsafe!(libusb_clear_halt(self.as_raw(), endpoint)); 244 Ok(()) 245 } 246 247 /// Indicates whether the device has an attached kernel driver. 248 /// 249 /// This method is not supported on all platforms. kernel_driver_active(&self, iface: u8) -> crate::Result<bool>250 pub fn kernel_driver_active(&self, iface: u8) -> crate::Result<bool> { 251 match unsafe { libusb_kernel_driver_active(self.as_raw(), c_int::from(iface)) } { 252 0 => Ok(false), 253 1 => Ok(true), 254 err => Err(error::from_libusb(err)), 255 } 256 } 257 258 /// Detaches an attached kernel driver from the device. 259 /// 260 /// This method is not supported on all platforms. detach_kernel_driver(&self, iface: u8) -> crate::Result<()>261 pub fn detach_kernel_driver(&self, iface: u8) -> crate::Result<()> { 262 try_unsafe!(libusb_detach_kernel_driver( 263 self.as_raw(), 264 c_int::from(iface) 265 )); 266 Ok(()) 267 } 268 269 /// Attaches a kernel driver to the device. 270 /// 271 /// This method is not supported on all platforms. attach_kernel_driver(&self, iface: u8) -> crate::Result<()>272 pub fn attach_kernel_driver(&self, iface: u8) -> crate::Result<()> { 273 try_unsafe!(libusb_attach_kernel_driver( 274 self.as_raw(), 275 c_int::from(iface) 276 )); 277 Ok(()) 278 } 279 280 /// Enable/disable automatic kernel driver detachment. 281 /// 282 /// When this is enabled rusb will automatically detach the 283 /// kernel driver on an interface when claiming the interface, and 284 /// attach it when releasing the interface. 285 /// 286 /// On platforms which do not have support, this function will 287 /// return `Error::NotSupported`, and rusb will continue as if 288 /// this function was never called. set_auto_detach_kernel_driver(&self, auto_detach: bool) -> crate::Result<()>289 pub fn set_auto_detach_kernel_driver(&self, auto_detach: bool) -> crate::Result<()> { 290 try_unsafe!(libusb_set_auto_detach_kernel_driver( 291 self.as_raw(), 292 auto_detach.into() 293 )); 294 Ok(()) 295 } 296 297 /// Claims one of the device's interfaces. 298 /// 299 /// An interface must be claimed before operating on it. All claimed interfaces are released 300 /// when the device handle goes out of scope. claim_interface(&self, iface: u8) -> crate::Result<()>301 pub fn claim_interface(&self, iface: u8) -> crate::Result<()> { 302 try_unsafe!(libusb_claim_interface(self.as_raw(), c_int::from(iface))); 303 self.interfaces.lock().unwrap().insert(iface); 304 Ok(()) 305 } 306 307 /// Releases a claimed interface. release_interface(&self, iface: u8) -> crate::Result<()>308 pub fn release_interface(&self, iface: u8) -> crate::Result<()> { 309 try_unsafe!(libusb_release_interface(self.as_raw(), c_int::from(iface))); 310 self.interfaces.lock().unwrap().remove(iface); 311 Ok(()) 312 } 313 314 /// Sets an interface's active setting. set_alternate_setting(&self, iface: u8, setting: u8) -> crate::Result<()>315 pub fn set_alternate_setting(&self, iface: u8, setting: u8) -> crate::Result<()> { 316 try_unsafe!(libusb_set_interface_alt_setting( 317 self.as_raw(), 318 c_int::from(iface), 319 c_int::from(setting) 320 )); 321 Ok(()) 322 } 323 324 /// Reads from an interrupt endpoint. 325 /// 326 /// This function attempts to read from the interrupt endpoint with the address given by the 327 /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function 328 /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds, 329 /// anything smaller will result in an infinite block. 330 /// 331 /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received 332 /// from the endpoint. 333 /// 334 /// ## Errors 335 /// 336 /// If this function encounters any form of error while fulfilling the transfer request, an 337 /// error variant will be returned. If an error variant is returned, no bytes were read. 338 /// 339 /// The errors returned by this function include: 340 /// 341 /// * `InvalidParam` if the endpoint is not an input endpoint. 342 /// * `Timeout` if the transfer timed out. 343 /// * `Pipe` if the endpoint halted. 344 /// * `Overflow` if the device offered more data. 345 /// * `NoDevice` if the device has been disconnected. 346 /// * `Io` if the transfer encountered an I/O error. read_interrupt( &self, endpoint: u8, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>347 pub fn read_interrupt( 348 &self, 349 endpoint: u8, 350 buf: &mut [u8], 351 timeout: Duration, 352 ) -> crate::Result<usize> { 353 if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN { 354 return Err(Error::InvalidParam); 355 } 356 let mut transferred = mem::MaybeUninit::<c_int>::uninit(); 357 unsafe { 358 match libusb_interrupt_transfer( 359 self.as_raw(), 360 endpoint, 361 buf.as_mut_ptr() as *mut c_uchar, 362 buf.len() as c_int, 363 transferred.as_mut_ptr(), 364 timeout.as_millis() as c_uint, 365 ) { 366 0 => Ok(transferred.assume_init() as usize), 367 err if err == LIBUSB_ERROR_INTERRUPTED => { 368 let transferred = transferred.assume_init(); 369 if transferred > 0 { 370 Ok(transferred as usize) 371 } else { 372 Err(error::from_libusb(err)) 373 } 374 } 375 err => Err(error::from_libusb(err)), 376 } 377 } 378 } 379 380 /// Writes to an interrupt endpoint. 381 /// 382 /// This function attempts to write the contents of `buf` to the interrupt endpoint with the 383 /// address given by the `endpoint` parameter. The function blocks up to the amount of time 384 /// specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will 385 /// result in an infinite block. 386 /// 387 /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint. 388 /// 389 /// ## Errors 390 /// 391 /// If this function encounters any form of error while fulfilling the transfer request, an 392 /// error variant will be returned. If an error variant is returned, no bytes were written. 393 /// 394 /// The errors returned by this function include: 395 /// 396 /// * `InvalidParam` if the endpoint is not an output endpoint. 397 /// * `Timeout` if the transfer timed out. 398 /// * `Pipe` if the endpoint halted. 399 /// * `NoDevice` if the device has been disconnected. 400 /// * `Io` if the transfer encountered an I/O error. write_interrupt( &self, endpoint: u8, buf: &[u8], timeout: Duration, ) -> crate::Result<usize>401 pub fn write_interrupt( 402 &self, 403 endpoint: u8, 404 buf: &[u8], 405 timeout: Duration, 406 ) -> crate::Result<usize> { 407 if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT { 408 return Err(Error::InvalidParam); 409 } 410 let mut transferred = mem::MaybeUninit::<c_int>::uninit(); 411 unsafe { 412 match libusb_interrupt_transfer( 413 self.as_raw(), 414 endpoint, 415 buf.as_ptr() as *mut c_uchar, 416 buf.len() as c_int, 417 transferred.as_mut_ptr(), 418 timeout.as_millis() as c_uint, 419 ) { 420 0 => Ok(transferred.assume_init() as usize), 421 err if err == LIBUSB_ERROR_INTERRUPTED => { 422 let transferred = transferred.assume_init(); 423 if transferred > 0 { 424 Ok(transferred as usize) 425 } else { 426 Err(error::from_libusb(err)) 427 } 428 } 429 err => Err(error::from_libusb(err)), 430 } 431 } 432 } 433 434 /// Reads from a bulk endpoint. 435 /// 436 /// This function attempts to read from the bulk endpoint with the address given by the 437 /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function 438 /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds, 439 /// anything smaller will result in an infinite block. 440 /// 441 /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received 442 /// from the endpoint. 443 /// 444 /// ## Errors 445 /// 446 /// If this function encounters any form of error while fulfilling the transfer request, an 447 /// error variant will be returned. If an error variant is returned, no bytes were read. 448 /// 449 /// The errors returned by this function include: 450 /// 451 /// * `InvalidParam` if the endpoint is not an input endpoint. 452 /// * `Timeout` if the transfer timed out. 453 /// * `Pipe` if the endpoint halted. 454 /// * `Overflow` if the device offered more data. 455 /// * `NoDevice` if the device has been disconnected. 456 /// * `Io` if the transfer encountered an I/O error. read_bulk( &self, endpoint: u8, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>457 pub fn read_bulk( 458 &self, 459 endpoint: u8, 460 buf: &mut [u8], 461 timeout: Duration, 462 ) -> crate::Result<usize> { 463 if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN { 464 return Err(Error::InvalidParam); 465 } 466 let mut transferred = mem::MaybeUninit::<c_int>::uninit(); 467 unsafe { 468 match libusb_bulk_transfer( 469 self.as_raw(), 470 endpoint, 471 buf.as_mut_ptr() as *mut c_uchar, 472 buf.len() as c_int, 473 transferred.as_mut_ptr(), 474 timeout.as_millis() as c_uint, 475 ) { 476 0 => Ok(transferred.assume_init() as usize), 477 err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => { 478 let transferred = transferred.assume_init(); 479 if transferred > 0 { 480 Ok(transferred as usize) 481 } else { 482 Err(error::from_libusb(err)) 483 } 484 } 485 err => Err(error::from_libusb(err)), 486 } 487 } 488 } 489 490 /// Writes to a bulk endpoint. 491 /// 492 /// This function attempts to write the contents of `buf` to the bulk endpoint with the address 493 /// given by the `endpoint` parameter. The function blocks up to the amount of time specified 494 /// by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will result in an 495 /// infinite block. 496 /// 497 /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint. 498 /// 499 /// ## Errors 500 /// 501 /// If this function encounters any form of error while fulfilling the transfer request, an 502 /// error variant will be returned. If an error variant is returned, no bytes were written. 503 /// 504 /// The errors returned by this function include: 505 /// 506 /// * `InvalidParam` if the endpoint is not an output endpoint. 507 /// * `Timeout` if the transfer timed out. 508 /// * `Pipe` if the endpoint halted. 509 /// * `NoDevice` if the device has been disconnected. 510 /// * `Io` if the transfer encountered an I/O error. write_bulk(&self, endpoint: u8, buf: &[u8], timeout: Duration) -> crate::Result<usize>511 pub fn write_bulk(&self, endpoint: u8, buf: &[u8], timeout: Duration) -> crate::Result<usize> { 512 if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT { 513 return Err(Error::InvalidParam); 514 } 515 let mut transferred = mem::MaybeUninit::<c_int>::uninit(); 516 unsafe { 517 match libusb_bulk_transfer( 518 self.as_raw(), 519 endpoint, 520 buf.as_ptr() as *mut c_uchar, 521 buf.len() as c_int, 522 transferred.as_mut_ptr(), 523 timeout.as_millis() as c_uint, 524 ) { 525 0 => Ok(transferred.assume_init() as usize), 526 err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => { 527 let transferred = transferred.assume_init(); 528 if transferred > 0 { 529 Ok(transferred as usize) 530 } else { 531 Err(error::from_libusb(err)) 532 } 533 } 534 err => Err(error::from_libusb(err)), 535 } 536 } 537 } 538 539 /// Reads data using a control transfer. 540 /// 541 /// This function attempts to read data from the device using a control transfer and fills 542 /// `buf` with any data received during the transfer. The function blocks up to the amount of 543 /// time specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will 544 /// result in an infinite block. 545 /// 546 /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the 547 /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex` 548 /// respectively). The values for each of these parameters shall be given in host-endian byte 549 /// order. The value for the `request_type` parameter can be built with the helper function, 550 /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the 551 /// type of control request. 552 /// 553 /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data. 554 /// 555 /// ## Errors 556 /// 557 /// If this function encounters any form of error while fulfilling the transfer request, an 558 /// error variant will be returned. If an error variant is returned, no bytes were read. 559 /// 560 /// The errors returned by this function include: 561 /// 562 /// * `InvalidParam` if `request_type` does not specify a read transfer. 563 /// * `Timeout` if the transfer timed out. 564 /// * `Pipe` if the control request was not supported by the device. 565 /// * `NoDevice` if the device has been disconnected. 566 /// * `Io` if the transfer encountered an I/O error. read_control( &self, request_type: u8, request: u8, value: u16, index: u16, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>567 pub fn read_control( 568 &self, 569 request_type: u8, 570 request: u8, 571 value: u16, 572 index: u16, 573 buf: &mut [u8], 574 timeout: Duration, 575 ) -> crate::Result<usize> { 576 if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN { 577 return Err(Error::InvalidParam); 578 } 579 let res = unsafe { 580 libusb_control_transfer( 581 self.as_raw(), 582 request_type, 583 request, 584 value, 585 index, 586 buf.as_mut_ptr() as *mut c_uchar, 587 buf.len() as u16, 588 timeout.as_millis() as c_uint, 589 ) 590 }; 591 592 if res < 0 { 593 Err(error::from_libusb(res)) 594 } else { 595 Ok(res as usize) 596 } 597 } 598 599 /// Writes data using a control transfer. 600 /// 601 /// This function attempts to write the contents of `buf` to the device using a control 602 /// transfer. The function blocks up to the amount of time specified by `timeout`. 603 /// Minimal `timeout` is 1 milliseconds, anything smaller will result in an infinite block. 604 /// 605 /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the 606 /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex` 607 /// respectively). The values for each of these parameters shall be given in host-endian byte 608 /// order. The value for the `request_type` parameter can be built with the helper function, 609 /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the 610 /// type of control request. 611 /// 612 /// If the return value is `Ok(n)`, then `n` bytes of `buf` were transfered. 613 /// 614 /// ## Errors 615 /// 616 /// If this function encounters any form of error while fulfilling the transfer request, an 617 /// error variant will be returned. If an error variant is returned, no bytes were read. 618 /// 619 /// The errors returned by this function include: 620 /// 621 /// * `InvalidParam` if `request_type` does not specify a write transfer. 622 /// * `Timeout` if the transfer timed out. 623 /// * `Pipe` if the control request was not supported by the device. 624 /// * `NoDevice` if the device has been disconnected. 625 /// * `Io` if the transfer encountered an I/O error. write_control( &self, request_type: u8, request: u8, value: u16, index: u16, buf: &[u8], timeout: Duration, ) -> crate::Result<usize>626 pub fn write_control( 627 &self, 628 request_type: u8, 629 request: u8, 630 value: u16, 631 index: u16, 632 buf: &[u8], 633 timeout: Duration, 634 ) -> crate::Result<usize> { 635 if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT { 636 return Err(Error::InvalidParam); 637 } 638 let res = unsafe { 639 libusb_control_transfer( 640 self.as_raw(), 641 request_type, 642 request, 643 value, 644 index, 645 buf.as_ptr() as *mut c_uchar, 646 buf.len() as u16, 647 timeout.as_millis() as c_uint, 648 ) 649 }; 650 651 if res < 0 { 652 Err(error::from_libusb(res)) 653 } else { 654 Ok(res as usize) 655 } 656 } 657 658 /// Reads the languages supported by the device's string descriptors. 659 /// 660 /// This function returns a list of languages that can be used to read the device's string 661 /// descriptors. read_languages(&self, timeout: Duration) -> crate::Result<Vec<Language>>662 pub fn read_languages(&self, timeout: Duration) -> crate::Result<Vec<Language>> { 663 let mut buf = [0u8; 255]; 664 665 let len = self.read_control( 666 request_type(Direction::In, RequestType::Standard, Recipient::Device), 667 LIBUSB_REQUEST_GET_DESCRIPTOR, 668 u16::from(LIBUSB_DT_STRING) << 8, 669 0, 670 &mut buf, 671 timeout, 672 )?; 673 674 if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 { 675 return Err(Error::BadDescriptor); 676 } 677 678 if len == 2 { 679 return Ok(Vec::new()); 680 } 681 682 Ok(buf[0..len] 683 .chunks(2) 684 .skip(1) 685 .map(|chunk| { 686 let lang_id = u16::from(chunk[0]) | u16::from(chunk[1]) << 8; 687 crate::language::from_lang_id(lang_id) 688 }) 689 .collect()) 690 } 691 692 /// Reads a ascii string descriptor from the device. 693 /// read_string_descriptor_ascii(&self, index: u8) -> crate::Result<String>694 pub fn read_string_descriptor_ascii(&self, index: u8) -> crate::Result<String> { 695 let mut buf = Vec::<u8>::with_capacity(255); 696 697 let ptr = buf.as_mut_ptr() as *mut c_uchar; 698 let capacity = buf.capacity() as i32; 699 700 let res = 701 unsafe { libusb_get_string_descriptor_ascii(self.as_raw(), index, ptr, capacity) }; 702 703 if res < 0 { 704 return Err(error::from_libusb(res)); 705 } 706 707 unsafe { 708 buf.set_len(res as usize); 709 } 710 711 String::from_utf8(buf).map_err(|_| Error::Other) 712 } 713 714 /// Reads a string descriptor from the device. 715 /// 716 /// `language` should be one of the languages returned from [`read_languages`](#method.read_languages). read_string_descriptor( &self, language: Language, index: u8, timeout: Duration, ) -> crate::Result<String>717 pub fn read_string_descriptor( 718 &self, 719 language: Language, 720 index: u8, 721 timeout: Duration, 722 ) -> crate::Result<String> { 723 let mut buf = [0u16; 128]; 724 725 let len = { 726 // SAFETY: since we create slice from existing slice pointer valid 727 // alignment of [u8] less or equal to the [u16] 728 // size is less then allocated buffer (128 * 2 = 256 => 256 < 255) 729 let buf = unsafe { 730 std::slice::from_raw_parts_mut( 731 buf.as_mut_ptr().cast::<u8>(), 732 255, // Some devices choke on size > 255 733 ) 734 }; 735 736 let len = self.read_control( 737 request_type(Direction::In, RequestType::Standard, Recipient::Device), 738 LIBUSB_REQUEST_GET_DESCRIPTOR, 739 u16::from(LIBUSB_DT_STRING) << 8 | u16::from(index), 740 language.lang_id(), 741 buf, 742 timeout, 743 )?; 744 745 if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 { 746 return Err(Error::BadDescriptor); 747 } 748 749 len 750 }; 751 752 if len == 2 { 753 return Ok(String::new()); 754 } 755 756 // len in bytes, skip first element(it's contain descriptor type and len) 757 String::from_utf16(&buf[1..(len / 2)]).map_err(|_| Error::Other) 758 } 759 760 /// Reads the device's manufacturer string descriptor (ascii). read_manufacturer_string_ascii( &self, device: &DeviceDescriptor, ) -> crate::Result<String>761 pub fn read_manufacturer_string_ascii( 762 &self, 763 device: &DeviceDescriptor, 764 ) -> crate::Result<String> { 765 match device.manufacturer_string_index() { 766 None => Err(Error::InvalidParam), 767 Some(n) => self.read_string_descriptor_ascii(n), 768 } 769 } 770 771 /// Reads the device's manufacturer string descriptor. read_manufacturer_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>772 pub fn read_manufacturer_string( 773 &self, 774 language: Language, 775 device: &DeviceDescriptor, 776 timeout: Duration, 777 ) -> crate::Result<String> { 778 match device.manufacturer_string_index() { 779 None => Err(Error::InvalidParam), 780 Some(n) => self.read_string_descriptor(language, n, timeout), 781 } 782 } 783 784 /// Reads the device's product string descriptor (ascii). read_product_string_ascii(&self, device: &DeviceDescriptor) -> crate::Result<String>785 pub fn read_product_string_ascii(&self, device: &DeviceDescriptor) -> crate::Result<String> { 786 match device.product_string_index() { 787 None => Err(Error::InvalidParam), 788 Some(n) => self.read_string_descriptor_ascii(n), 789 } 790 } 791 792 /// Reads the device's product string descriptor. read_product_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>793 pub fn read_product_string( 794 &self, 795 language: Language, 796 device: &DeviceDescriptor, 797 timeout: Duration, 798 ) -> crate::Result<String> { 799 match device.product_string_index() { 800 None => Err(Error::InvalidParam), 801 Some(n) => self.read_string_descriptor(language, n, timeout), 802 } 803 } 804 805 /// Reads the device's serial number string descriptor (ascii). read_serial_number_string_ascii( &self, device: &DeviceDescriptor, ) -> crate::Result<String>806 pub fn read_serial_number_string_ascii( 807 &self, 808 device: &DeviceDescriptor, 809 ) -> crate::Result<String> { 810 match device.serial_number_string_index() { 811 None => Err(Error::InvalidParam), 812 Some(n) => self.read_string_descriptor_ascii(n), 813 } 814 } 815 816 /// Reads the device's serial number string descriptor. read_serial_number_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>817 pub fn read_serial_number_string( 818 &self, 819 language: Language, 820 device: &DeviceDescriptor, 821 timeout: Duration, 822 ) -> crate::Result<String> { 823 match device.serial_number_string_index() { 824 None => Err(Error::InvalidParam), 825 Some(n) => self.read_string_descriptor(language, n, timeout), 826 } 827 } 828 829 /// Reads the string descriptor for a configuration's description. read_configuration_string( &self, language: Language, configuration: &ConfigDescriptor, timeout: Duration, ) -> crate::Result<String>830 pub fn read_configuration_string( 831 &self, 832 language: Language, 833 configuration: &ConfigDescriptor, 834 timeout: Duration, 835 ) -> crate::Result<String> { 836 match configuration.description_string_index() { 837 None => Err(Error::InvalidParam), 838 Some(n) => self.read_string_descriptor(language, n, timeout), 839 } 840 } 841 842 /// Reads the string descriptor for a interface's description. read_interface_string( &self, language: Language, interface: &InterfaceDescriptor, timeout: Duration, ) -> crate::Result<String>843 pub fn read_interface_string( 844 &self, 845 language: Language, 846 interface: &InterfaceDescriptor, 847 timeout: Duration, 848 ) -> crate::Result<String> { 849 match interface.description_string_index() { 850 None => Err(Error::InvalidParam), 851 Some(n) => self.read_string_descriptor(language, n, timeout), 852 } 853 } 854 } 855 856 #[cfg(test)] 857 mod tests { 858 use super::ClaimedInterfaces; 859 use std::u8; 860 861 #[test] claimed_interfaces_empty()862 fn claimed_interfaces_empty() { 863 let empty = ClaimedInterfaces::new(); 864 assert_eq!(empty.size(), 0); 865 for i in 0..=u8::MAX { 866 assert!(!empty.contains(i), "empty set should not contain {}", i); 867 } 868 869 let mut iter = empty.iter(); 870 assert_eq!(iter.size_hint(), (0, Some(0))); 871 assert_eq!(iter.next(), None); 872 } 873 874 #[test] claimed_interfaces_one_element()875 fn claimed_interfaces_one_element() { 876 let mut interfaces = ClaimedInterfaces::new(); 877 interfaces.insert(94); 878 assert_eq!(interfaces.size(), 1); 879 assert!(interfaces.contains(94)); 880 for i in 0..=u8::MAX { 881 if i == 94 { 882 continue; 883 } 884 assert!( 885 !interfaces.contains(i), 886 "interfaces should not contain {}", 887 i 888 ); 889 } 890 891 let mut iter = interfaces.iter(); 892 assert_eq!(iter.size_hint(), (1, Some(1))); 893 assert_eq!(iter.next(), Some(94)); 894 assert_eq!(iter.size_hint(), (0, Some(0))); 895 assert_eq!(iter.next(), None); 896 } 897 898 #[test] claimed_interfaces_many_elements()899 fn claimed_interfaces_many_elements() { 900 let mut interfaces = ClaimedInterfaces::new(); 901 let elements = vec![94, 0, 255, 17, 183, 6]; 902 903 for (index, &interface) in elements.iter().enumerate() { 904 interfaces.insert(interface); 905 assert_eq!(interfaces.size(), index + 1); 906 } 907 908 // Validate contains(). 909 for &interface in elements.iter() { 910 assert!( 911 interfaces.contains(interface), 912 "interfaces should contain {}", 913 interface 914 ); 915 } 916 917 // Validate iter(). 918 let contents = interfaces.iter().collect::<Vec<_>>().sort(); 919 assert_eq!(contents, elements.clone().sort()); 920 921 // Validate size_hint(). 922 let mut iter = interfaces.iter(); 923 let mut read = 0; 924 loop { 925 assert!( 926 read <= elements.len(), 927 "read elements {} should not exceed elements size {}", 928 read, 929 elements.len() 930 ); 931 let remaining = elements.len() - read; 932 assert_eq!(iter.size_hint(), (remaining, Some(remaining))); 933 match iter.next() { 934 Some(_) => read += 1, 935 None => break, 936 } 937 } 938 } 939 } 940