Add MaybeFuture::map
This commit is contained in:
parent
8dfb3e5f1d
commit
5e866af4e4
5 changed files with 134 additions and 75 deletions
|
|
@ -46,13 +46,13 @@ impl Device {
|
|||
pub(crate) fn open(
|
||||
d: &DeviceInfo,
|
||||
) -> impl MaybeFuture<Output = Result<Device, std::io::Error>> {
|
||||
platform::Device::from_device_info(d)
|
||||
platform::Device::from_device_info(d).map(|d| d.map(Device::wrap))
|
||||
}
|
||||
|
||||
/// Wraps a device that is already open.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub fn from_fd(fd: std::os::fd::OwnedFd) -> impl MaybeFuture<Output = Result<Device, Error>> {
|
||||
platform::Device::from_fd(fd)
|
||||
platform::Device::from_fd(fd).map(|d| d.map(Device::wrap))
|
||||
}
|
||||
|
||||
/// Open an interface of the device and claim it for exclusive use.
|
||||
|
|
@ -60,7 +60,10 @@ impl Device {
|
|||
&self,
|
||||
interface: u8,
|
||||
) -> impl MaybeFuture<Output = Result<Interface, Error>> {
|
||||
self.backend.clone().claim_interface(interface)
|
||||
self.backend
|
||||
.clone()
|
||||
.claim_interface(interface)
|
||||
.map(|i| i.map(Interface::wrap))
|
||||
}
|
||||
|
||||
/// Detach kernel drivers and open an interface of the device and claim it for exclusive use.
|
||||
|
|
@ -72,7 +75,10 @@ impl Device {
|
|||
&self,
|
||||
interface: u8,
|
||||
) -> impl MaybeFuture<Output = Result<Interface, Error>> {
|
||||
self.backend.clone().detach_and_claim_interface(interface)
|
||||
self.backend
|
||||
.clone()
|
||||
.detach_and_claim_interface(interface)
|
||||
.map(|i| i.map(Interface::wrap))
|
||||
}
|
||||
|
||||
/// Detach kernel drivers for the specified interface.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
use std::future::IntoFuture;
|
||||
use std::{
|
||||
future::{Future, IntoFuture},
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// IO that may be performed synchronously or asynchronously.
|
||||
///
|
||||
|
|
@ -8,6 +12,17 @@ pub trait MaybeFuture: IntoFuture {
|
|||
/// Block waiting for the action to complete
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn wait(self) -> Self::Output;
|
||||
|
||||
/// Apply a function to the output.
|
||||
fn map<T: FnOnce(Self::Output) -> R + Unpin, R>(self, f: T) -> Map<Self, T>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Map {
|
||||
wrapped: self,
|
||||
func: f,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
|
|
@ -73,3 +88,47 @@ impl<T> MaybeFuture for Ready<T> {
|
|||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Map<F, T> {
|
||||
wrapped: F,
|
||||
func: T,
|
||||
}
|
||||
|
||||
impl<F: MaybeFuture, T: FnOnce(F::Output) -> R, R> IntoFuture for Map<F, T> {
|
||||
type Output = R;
|
||||
type IntoFuture = MapFut<F::IntoFuture, T>;
|
||||
|
||||
fn into_future(self) -> Self::IntoFuture {
|
||||
MapFut {
|
||||
wrapped: self.wrapped.into_future(),
|
||||
func: Some(self.func),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: MaybeFuture, T: FnOnce(F::Output) -> R, R> MaybeFuture for Map<F, T> {
|
||||
fn wait(self) -> Self::Output {
|
||||
(self.func)(self.wrapped.wait())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapFut<F, T> {
|
||||
wrapped: F,
|
||||
func: Option<T>,
|
||||
}
|
||||
|
||||
impl<F: Future, T: FnOnce(F::Output) -> R, R> Future for MapFut<F, T> {
|
||||
type Output = R;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// SAFETY: structural pin projection: `self.wrapped` is always pinned.
|
||||
let wrapped = unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.wrapped) };
|
||||
|
||||
Future::poll(wrapped, cx).map(|output| {
|
||||
// SAFETY: `self.func` is never pinned.
|
||||
let func = unsafe { &mut self.as_mut().get_unchecked_mut().func };
|
||||
|
||||
(func.take().expect("polled after completion"))(output)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ pub(crate) struct LinuxDevice {
|
|||
impl LinuxDevice {
|
||||
pub(crate) fn from_device_info(
|
||||
d: &DeviceInfo,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<LinuxDevice>, Error>> {
|
||||
let busnum = d.busnum();
|
||||
let devnum = d.device_address();
|
||||
let sysfs_path = d.path.clone();
|
||||
|
|
@ -68,7 +68,9 @@ impl LinuxDevice {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn from_fd(fd: OwnedFd) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
|
||||
pub(crate) fn from_fd(
|
||||
fd: OwnedFd,
|
||||
) -> impl MaybeFuture<Output = Result<Arc<LinuxDevice>, Error>> {
|
||||
Blocking::new(move || {
|
||||
debug!("Wrapping fd {} as usbfs device", fd.as_raw_fd());
|
||||
Self::create_inner(fd, None, None)
|
||||
|
|
@ -79,7 +81,7 @@ impl LinuxDevice {
|
|||
fd: OwnedFd,
|
||||
sysfs: Option<SysfsPath>,
|
||||
active_config: Option<u8>,
|
||||
) -> Result<crate::Device, Error> {
|
||||
) -> Result<Arc<LinuxDevice>, Error> {
|
||||
let descriptors = {
|
||||
let mut file = unsafe { ManuallyDrop::new(File::from_raw_fd(fd.as_raw_fd())) };
|
||||
// NOTE: Seek required on android
|
||||
|
|
@ -125,7 +127,7 @@ impl LinuxDevice {
|
|||
epoll::EventFlags::OUT,
|
||||
)?;
|
||||
|
||||
Ok(crate::Device::wrap(arc))
|
||||
Ok(arc)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_usb_epoll(id: usize) {
|
||||
|
|
@ -284,7 +286,7 @@ impl LinuxDevice {
|
|||
pub(crate) fn claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface_number: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<LinuxInterface>, Error>> {
|
||||
Blocking::new(move || {
|
||||
usbfs::claim_interface(&self.fd, interface_number).inspect_err(|e| {
|
||||
warn!(
|
||||
|
|
@ -296,31 +298,31 @@ impl LinuxDevice {
|
|||
"Claimed interface {interface_number} on device id {dev}",
|
||||
dev = self.events_id
|
||||
);
|
||||
Ok(crate::Interface::wrap(Arc::new(LinuxInterface {
|
||||
Ok(Arc::new(LinuxInterface {
|
||||
device: self,
|
||||
interface_number,
|
||||
reattach: false,
|
||||
state: Mutex::new(Default::default()),
|
||||
})))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn detach_and_claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface_number: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<LinuxInterface>, Error>> {
|
||||
Blocking::new(move || {
|
||||
usbfs::detach_and_claim_interface(&self.fd, interface_number)?;
|
||||
debug!(
|
||||
"Detached and claimed interface {interface_number} on device id {dev}",
|
||||
dev = self.events_id
|
||||
);
|
||||
Ok(crate::Interface::wrap(Arc::new(LinuxInterface {
|
||||
Ok(Arc::new(LinuxInterface {
|
||||
device: self,
|
||||
interface_number,
|
||||
reattach: true,
|
||||
state: Mutex::new(Default::default()),
|
||||
})))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ fn guess_active_config(dev: &IoKitDevice) -> Option<u8> {
|
|||
impl MacDevice {
|
||||
pub(crate) fn from_device_info(
|
||||
d: &DeviceInfo,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<MacDevice>, Error>> {
|
||||
let registry_id = d.registry_id;
|
||||
let speed = d.speed;
|
||||
Blocking::new(move || {
|
||||
|
|
@ -88,7 +88,7 @@ impl MacDevice {
|
|||
res.unwrap_or(0)
|
||||
};
|
||||
|
||||
Ok(crate::Device::wrap(Arc::new(MacDevice {
|
||||
Ok(Arc::new(MacDevice {
|
||||
_event_registration,
|
||||
device,
|
||||
device_descriptor,
|
||||
|
|
@ -96,7 +96,7 @@ impl MacDevice {
|
|||
active_config: AtomicU8::new(active_config),
|
||||
is_open_exclusive: Mutex::new(opened),
|
||||
claimed_interfaces: AtomicUsize::new(0),
|
||||
})))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ impl MacDevice {
|
|||
pub(crate) fn claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface_number: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<MacInterface>, Error>> {
|
||||
Blocking::new(move || {
|
||||
let intf_service = self
|
||||
.device
|
||||
|
|
@ -254,21 +254,21 @@ impl MacDevice {
|
|||
|
||||
self.claimed_interfaces.fetch_add(1, Ordering::Acquire);
|
||||
|
||||
Ok(crate::Interface::wrap(Arc::new(MacInterface {
|
||||
Ok(Arc::new(MacInterface {
|
||||
device: self.clone(),
|
||||
interface_number,
|
||||
interface,
|
||||
endpoints: Mutex::new(endpoints),
|
||||
state: Mutex::new(InterfaceState::default()),
|
||||
_event_registration,
|
||||
})))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn detach_and_claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<MacInterface>, Error>> {
|
||||
self.claim_interface(interface)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub(crate) struct WindowsDevice {
|
|||
impl WindowsDevice {
|
||||
pub(crate) fn from_device_info(
|
||||
d: &DeviceInfo,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<WindowsDevice>, Error>> {
|
||||
let instance_id = d.instance_id.clone();
|
||||
let devinst = d.devinst;
|
||||
Blocking::new(move || {
|
||||
|
|
@ -85,14 +85,14 @@ impl WindowsDevice {
|
|||
})
|
||||
.collect();
|
||||
|
||||
Ok(crate::Device::wrap(Arc::new(WindowsDevice {
|
||||
Ok(Arc::new(WindowsDevice {
|
||||
device_descriptor,
|
||||
config_descriptors,
|
||||
speed: connection_info.speed,
|
||||
active_config: connection_info.active_config,
|
||||
devinst: devinst,
|
||||
handles: Mutex::new(BTreeMap::new()),
|
||||
})))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -145,63 +145,55 @@ impl WindowsDevice {
|
|||
pub(crate) fn claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface_number: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<WindowsInterface>, Error>> {
|
||||
Blocking::new(move || {
|
||||
self.claim_interface_blocking(interface_number)
|
||||
.map(crate::Interface::wrap)
|
||||
let driver = get_driver_name(self.devinst);
|
||||
|
||||
let mut handles = self.handles.lock().unwrap();
|
||||
|
||||
if driver.eq_ignore_ascii_case("winusb") {
|
||||
match handles.entry(0) {
|
||||
Entry::Occupied(mut e) => e.get_mut().claim_interface(&self, interface_number),
|
||||
Entry::Vacant(e) => {
|
||||
let path = get_winusb_device_path(self.devinst)?;
|
||||
let mut handle = WinusbFileHandle::new(&path, 0)?;
|
||||
let intf = handle.claim_interface(&self, interface_number)?;
|
||||
e.insert(handle);
|
||||
Ok(intf)
|
||||
}
|
||||
}
|
||||
} else if driver.eq_ignore_ascii_case("usbccgp") {
|
||||
let (first_interface, child_dev) =
|
||||
find_usbccgp_child(self.devinst, interface_number)
|
||||
.ok_or_else(|| Error::new(ErrorKind::NotFound, "Interface not found"))?;
|
||||
|
||||
if first_interface != interface_number {
|
||||
debug!("Guessing that interface {interface_number} is an associated interface of {first_interface}");
|
||||
}
|
||||
|
||||
match handles.entry(first_interface) {
|
||||
Entry::Occupied(mut e) => e.get_mut().claim_interface(&self, interface_number),
|
||||
Entry::Vacant(e) => {
|
||||
let path = get_usbccgp_winusb_device_path(child_dev)?;
|
||||
let mut handle = WinusbFileHandle::new(&path, first_interface)?;
|
||||
let intf = handle.claim_interface(&self, interface_number)?;
|
||||
e.insert(handle);
|
||||
Ok(intf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(
|
||||
ErrorKind::Unsupported,
|
||||
format!("Device driver is {driver:?}, not WinUSB or USBCCGP"),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn claim_interface_blocking(
|
||||
self: &Arc<Self>,
|
||||
interface_number: u8,
|
||||
) -> Result<Arc<WindowsInterface>, Error> {
|
||||
let driver = get_driver_name(self.devinst);
|
||||
|
||||
let mut handles = self.handles.lock().unwrap();
|
||||
|
||||
if driver.eq_ignore_ascii_case("winusb") {
|
||||
match handles.entry(0) {
|
||||
Entry::Occupied(mut e) => e.get_mut().claim_interface(self, interface_number),
|
||||
Entry::Vacant(e) => {
|
||||
let path = get_winusb_device_path(self.devinst)?;
|
||||
let mut handle = WinusbFileHandle::new(&path, 0)?;
|
||||
let intf = handle.claim_interface(self, interface_number)?;
|
||||
e.insert(handle);
|
||||
Ok(intf)
|
||||
}
|
||||
}
|
||||
} else if driver.eq_ignore_ascii_case("usbccgp") {
|
||||
let (first_interface, child_dev) =
|
||||
find_usbccgp_child(self.devinst, interface_number)
|
||||
.ok_or_else(|| Error::new(ErrorKind::NotFound, "Interface not found"))?;
|
||||
|
||||
if first_interface != interface_number {
|
||||
debug!("Guessing that interface {interface_number} is an associated interface of {first_interface}");
|
||||
}
|
||||
|
||||
match handles.entry(first_interface) {
|
||||
Entry::Occupied(mut e) => e.get_mut().claim_interface(self, interface_number),
|
||||
Entry::Vacant(e) => {
|
||||
let path = get_usbccgp_winusb_device_path(child_dev)?;
|
||||
let mut handle = WinusbFileHandle::new(&path, first_interface)?;
|
||||
let intf = handle.claim_interface(self, interface_number)?;
|
||||
e.insert(handle);
|
||||
Ok(intf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(
|
||||
ErrorKind::Unsupported,
|
||||
format!("Device driver is {driver:?}, not WinUSB or USBCCGP"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn detach_and_claim_interface(
|
||||
self: Arc<Self>,
|
||||
interface: u8,
|
||||
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
|
||||
) -> impl MaybeFuture<Output = Result<Arc<WindowsInterface>, Error>> {
|
||||
self.claim_interface(interface)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue