From 1c8d72892246d4cce0b031e0b596f2e08edf98b6 Mon Sep 17 00:00:00 2001 From: Rajas Paranjpe <52586855+ChocolateLoverRaj@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:21:51 -0700 Subject: [PATCH] Multiple event types when waiting for event --- Cargo.lock | 5 +-- crosec/src/wait_event/event.rs | 58 +++++++++++++++++++++------------- crosec/src/wait_event/mod.rs | 41 ++++++++++++++++-------- ectool/Cargo.toml | 1 + ectool/src/main.rs | 11 +++++-- 5 files changed, 75 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d41b9b..0d20f3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -554,6 +554,7 @@ dependencies = [ "crosec", "image", "num-traits", + "strum", ] [[package]] @@ -1561,9 +1562,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" diff --git a/crosec/src/wait_event/event.rs b/crosec/src/wait_event/event.rs index 3708273..7c2ecd2 100644 --- a/crosec/src/wait_event/event.rs +++ b/crosec/src/wait_event/event.rs @@ -1,6 +1,9 @@ use async_std::io::ReadExt; +use num::FromPrimitive; use std::io; use std::mem::size_of; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; use bytemuck::{from_bytes, Pod, Zeroable}; use num_derive::FromPrimitive; @@ -32,8 +35,37 @@ pub enum EcMkbpEvent { Sysrq(u32), CecEvent(u32), } +impl EcMkbpEvent { + fn max_event_size() -> usize { + EcMkbpEventType::iter() + .map(|e| e.data_size()) + .max() + .unwrap_or_default() + } + + fn from_bytes(bytes: &[u8]) -> Self { + let event_type = EcMkbpEventType::from_u8(bytes[0]).unwrap(); + event_type.event_from_bytes(&mut bytes[1..1 + event_type.data_size()].to_vec()) + } + + pub(crate) fn read_sync(stream: &mut T) -> io::Result { + let mut buf: Vec = + vec![Default::default(); size_of::() + Self::max_event_size()]; + stream.read(&mut buf)?; + Ok(Self::from_bytes(&buf)) + } + + pub(crate) async fn read_async( + stream: &mut T, + ) -> io::Result { + let mut buf: Vec = + vec![Default::default(); size_of::() + Self::max_event_size()]; + stream.read(&mut buf).await?; + Ok(Self::from_bytes(&buf)) + } +} -#[derive(Debug, FromPrimitive, Clone, Copy)] +#[derive(Debug, FromPrimitive, Clone, Copy, EnumIter, PartialEq)] #[cfg_attr(feature = "clap", derive(clap::ValueEnum))] #[repr(u8)] pub enum EcMkbpEventType { @@ -68,33 +100,15 @@ impl EcMkbpEventType { } } - fn parse_event(&self, event: &mut Vec) -> EcMkbpEvent { - debug_assert_eq!(event[0], *self as u8); - event.remove(0); - let data = event; + fn event_from_bytes(&self, event: &[u8]) -> EcMkbpEvent { match self { EcMkbpEventType::Fingerprint => { - EcMkbpEvent::Fingerprint(from_bytes::(&data).to_owned()) + EcMkbpEvent::Fingerprint(from_bytes::(&event).to_owned()) } EcMkbpEventType::HostEvent => { - EcMkbpEvent::HostEvent(from_bytes::(&data).to_owned()) + EcMkbpEvent::HostEvent(from_bytes::(&event).to_owned()) } event_type => panic!("{event_type:#?} from_bytes not implemented yet"), } } - - pub(crate) fn read_sync(&self, stream: &mut T) -> io::Result { - let mut event = vec![Default::default(); size_of::() + self.data_size()]; - stream.read_exact(&mut event)?; - Ok(self.parse_event(&mut event)) - } - - pub(crate) async fn read_async( - &self, - stream: &mut T, - ) -> io::Result { - let mut event = vec![Default::default(); size_of::() + self.data_size()]; - stream.read_exact(&mut event).await?; - Ok(self.parse_event(&mut event)) - } } diff --git a/crosec/src/wait_event/mod.rs b/crosec/src/wait_event/mod.rs index cf027d9..4d858cd 100644 --- a/crosec/src/wait_event/mod.rs +++ b/crosec/src/wait_event/mod.rs @@ -1,5 +1,4 @@ -use std::io; -use std::os::fd::AsRawFd; +use std::{io, os::fd::AsRawFd}; use nix::{ libc::{ioctl, poll, pollfd}, @@ -23,18 +22,26 @@ pub enum PollData { SomethingElseHappened(i16), } +fn get_mask>(event_types: I) -> i32 { + let mut mask = i32::default(); + for event_type in event_types { + mask |= 1 << event_type as u8; + } + assert_ne!(mask, 0, "Must specify at least one event type"); + mask +} + /// If no timeout is specified, this function will wait for an unlimited amount of time -pub fn wait_event_sync( +pub fn wait_event_sync>( file: &mut File, - event_type: EcMkbpEventType, + event_types: I, timeout: Option, ) -> Result { - let mask = 1 << event_type as u8; unsafe { ioctl( file.as_raw_fd(), request_code_none!(CROS_EC_IOC_MAGIC, 2), - mask, + get_mask(event_types), ) }; match timeout { @@ -48,27 +55,33 @@ pub fn wait_event_sync( match result { 0 => Ok(PollData::Timeout), 1 => match fds.revents { - POLL_IN => Ok(PollData::EventHappened(event_type.read_sync(file).unwrap())), + POLL_IN => Ok(PollData::EventHappened( + EcMkbpEvent::read_sync(file).unwrap(), + )), events => Ok(PollData::SomethingElseHappened(events)), }, result => Err(result), } } - None => Ok(PollData::EventHappened(event_type.read_sync(file).unwrap())), + None => Ok(PollData::EventHappened( + EcMkbpEvent::read_sync(file).unwrap(), + )), } } -pub async fn wait_event_async( +pub async fn wait_event_async< + File: AsRawFd + async_std::io::Read + Unpin, + I: IntoIterator, +>( file: &mut File, - event_type: EcMkbpEventType, + event_types: I, ) -> io::Result { - let mask = 1 << event_type as u8; unsafe { ioctl( file.as_raw_fd(), request_code_none!(CROS_EC_IOC_MAGIC, 2), - mask, + get_mask(event_types), ) }; - event_type.read_async(file).await -} \ No newline at end of file + EcMkbpEvent::read_async(file).await +} diff --git a/ectool/Cargo.toml b/ectool/Cargo.toml index 4089e54..9c2f404 100644 --- a/ectool/Cargo.toml +++ b/ectool/Cargo.toml @@ -12,3 +12,4 @@ color-eyre = "0.6.2" clap = { version = "4.5.4", features = ["derive"] } num-traits = "0.2.19" image = "0.25.1" +strum = "0.26.3" diff --git a/ectool/src/main.rs b/ectool/src/main.rs index 31978ef..c55c831 100644 --- a/ectool/src/main.rs +++ b/ectool/src/main.rs @@ -16,6 +16,7 @@ use fp_download_subcommand::{fp_download_subcommand, FpDownloadSubcommand}; use fp_upload_template_command::fp_upload_template_command; use get_uptime_info_command::get_uptime_info_commnad; use num_traits::cast::FromPrimitive; +use strum::IntoEnumIterator; use crate::fp_get_encryption_status_command::fp_get_encryption_status_command; use crosec::battery::battery; @@ -114,8 +115,9 @@ enum Commands { mode: Vec, }, WaitEvent { - event_type: EcMkbpEventType, + event_types: Vec, /// Timeout in milliseconds + #[arg(short, long)] timeout: Option, #[arg(short, long)] device: Option, @@ -268,13 +270,16 @@ fn main() -> Result<()> { println!("FP mode: {display}"); } Commands::WaitEvent { - event_type, + mut event_types, device, timeout, } => { + if event_types.len() == 0 { + event_types = EcMkbpEventType::iter().collect(); + } let mut file = File::open(device.unwrap_or_default().get_path())?; println!("Waiting for event..."); - let result = wait_event_sync(&mut file, event_type, timeout).unwrap(); + let result = wait_event_sync(&mut file, event_types, timeout).unwrap(); println!("{result:#?}"); } Commands::FpDownload { command } => fp_download_subcommand(command)?,