diff options
author | Jingkui Wang <jkwang@google.com> | 2018-07-12 14:09:24 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-12-01 01:08:35 -0800 |
commit | 457ebc9d93253cc44d81baacda889ff604fb0319 (patch) | |
tree | 61e56132b13db470170766071eb34355b76d1436 /usb_util | |
parent | 33e08312f272c863f062fffe53ea4a4ce94e6e26 (diff) | |
download | crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar.gz crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar.bz2 crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar.lz crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar.xz crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.tar.zst crosvm-457ebc9d93253cc44d81baacda889ff604fb0319.zip |
usb_util: Add pollfd change handler.
Allow user to hander pollfd change events. BUG=chromium:831850 TEST=local build CQ-DEPEND=CL:1124870 Change-Id: I013104e7dfae8f9ae94803f99f435039cd53925c Reviewed-on: https://chromium-review.googlesource.com/1135783 Commit-Ready: Jingkui Wang <jkwang@google.com> Tested-by: Jingkui Wang <jkwang@google.com> Reviewed-by: Jingkui Wang <jkwang@google.com>
Diffstat (limited to 'usb_util')
-rw-r--r-- | usb_util/src/libusb_context.rs | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/usb_util/src/libusb_context.rs b/usb_util/src/libusb_context.rs index 821d2ad..016ea22 100644 --- a/usb_util/src/libusb_context.rs +++ b/usb_util/src/libusb_context.rs @@ -3,22 +3,37 @@ // found in the LICENSE file. use std; +use std::os::raw::{c_short, c_void}; +use std::os::unix::io::RawFd; use bindings; use error::{Error, Result}; use libusb_device::LibUsbDevice; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; pub struct LibUsbContextInner { context: *mut bindings::libusb_context, + pollfd_change_handler: Mutex<Option<Box<PollfdChangeHandlerHolder>>>, } // Safe because libusb_context could be accessed from multiple threads safely. unsafe impl Send for LibUsbContextInner {} unsafe impl Sync for LibUsbContextInner {} +impl LibUsbContextInner { + /// Remove the previous registered notifiers. + pub fn remove_pollfd_notifiers(&self) { + // Safe because 'self.context' is valid. + unsafe { + bindings::libusb_set_pollfd_notifiers(self.context, None, None, std::ptr::null_mut()); + } + } +} + impl Drop for LibUsbContextInner { fn drop(&mut self) { + // Avoid pollfd change handler call when libusb_exit is called. + self.remove_pollfd_notifiers(); // Safe beacuse 'self.context' points to a valid context allocated by libusb_init. unsafe { bindings::libusb_exit(self.context); @@ -41,7 +56,10 @@ impl LibUsbContext { // Safe because '&mut ctx' points to a valid memory (on stack). try_libusb!(unsafe { bindings::libusb_init(&mut ctx) }); Ok(LibUsbContext { - inner: Arc::new(LibUsbContextInner { context: ctx }), + inner: Arc::new(LibUsbContextInner { + context: ctx, + pollfd_change_handler: Mutex::new(None), + }), }) } @@ -74,7 +92,7 @@ impl LibUsbContext { } /// Handle libusb events in a non block way. - pub fn handle_event_nonblock(&self) { + pub fn handle_events_nonblock(&self) { static mut zero_time: bindings::timeval = bindings::timeval { tv_sec: 0, tv_usec: 0, @@ -88,6 +106,30 @@ impl LibUsbContext { ); } } + + /// Set a handler that could handle pollfd change events. + pub fn set_pollfd_notifiers(&self, handler: Box<LibUsbPollfdChangeHandler>) { + // LibUsbContext is alive when any libusb related function is called. It owns the handler, + // thus the handler memory is always valid when callback is invoked. + let holder = Box::new(PollfdChangeHandlerHolder { handler }); + let raw_holder = Box::into_raw(holder); + unsafe { + bindings::libusb_set_pollfd_notifiers( + self.inner.context, + Some(pollfd_added_cb), + Some(pollfd_removed_cb), + raw_holder as *mut c_void, + ); + } + // Safe because raw_holder is from Boxed pointer. + let holder = unsafe { Box::from_raw(raw_holder) }; + *self.inner.pollfd_change_handler.lock().unwrap() = Some(holder); + } + + /// Remove the previous registered notifiers. + pub fn remove_pollfd_notifiers(&self) { + self.inner.remove_pollfd_notifiers(); + } } /// Iterator for device list. @@ -154,3 +196,29 @@ impl Iterator for PollFdIter { } } } + +/// Trait for handler that handles Pollfd Change events. +pub trait LibUsbPollfdChangeHandler: Send + Sync + 'static { + fn add_poll_fd(&self, fd: RawFd, events: c_short); + fn remove_poll_fd(&self, fd: RawFd); +} + +// This struct owns LibUsbPollfdChangeHandler. We need it because it's not possible to cast void +// pointer to trait pointer. +struct PollfdChangeHandlerHolder { + handler: Box<LibUsbPollfdChangeHandler>, +} + +// This function is safe when user_data points to valid PollfdChangeHandlerHolder. +unsafe extern "C" fn pollfd_added_cb(fd: RawFd, events: c_short, user_data: *mut c_void) { + // Safe because user_data was casted from holder. + let keeper = &*(user_data as *mut PollfdChangeHandlerHolder); + keeper.handler.add_poll_fd(fd, events); +} + +// This function is safe when user_data points to valid PollfdChangeHandlerHolder. +unsafe extern "C" fn pollfd_removed_cb(fd: RawFd, user_data: *mut c_void) { + // Safe because user_data was casted from holder. + let keeper = &*(user_data as *mut PollfdChangeHandlerHolder); + keeper.handler.remove_poll_fd(fd); +} |