-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The function can wait for any event and detect the type of the event. It has in depth Rust-safe types for the fingerprint events.
- Loading branch information
1 parent
06efbf5
commit cb213aa
Showing
5 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use std::{ | ||
io::{self, Read}, | ||
mem::size_of, | ||
}; | ||
|
||
use bytemuck::{from_bytes, Pod, Zeroable}; | ||
use num_derive::FromPrimitive; | ||
use strum_macros::{EnumString, IntoStaticStr}; | ||
|
||
use crate::wait_event::fingerprint::EcMkbpEventFingerprint; | ||
|
||
#[derive(Debug, Clone, Copy, Pod, Zeroable)] | ||
#[repr(C, packed)] | ||
pub struct EcResponseMotionSenseFifoInfo { | ||
size: u16, | ||
count: u16, | ||
timestamp: u32, | ||
total_lost: u16, | ||
lost: [u16; 0], | ||
} | ||
|
||
#[derive(Debug)] | ||
#[repr(u8)] | ||
pub enum EcMkbpEvent { | ||
KeyMatrix([u8; 13]), | ||
HostEvent(u32), | ||
HostEvent64(u64), | ||
SensorFifo(EcResponseMotionSenseFifoInfo), | ||
Buttons(u32), | ||
Switches(u32), | ||
Fingerprint(EcMkbpEventFingerprint), | ||
Sysrq(u32), | ||
CecEvent(u32), | ||
} | ||
|
||
#[derive(Debug, IntoStaticStr, EnumString, FromPrimitive, Clone, Copy)] | ||
#[repr(u8)] | ||
pub enum EcMkbpEventType { | ||
KeyMatrix, | ||
HostEvent, | ||
SensorFifo, | ||
Buttons, | ||
Switches, | ||
Fingerprint, | ||
Sysrq, | ||
HostEvent64, | ||
CecEvent, | ||
CecMessage, | ||
DpAltModeEntered, | ||
OnlineCalibration, | ||
Pchg, | ||
} | ||
impl EcMkbpEventType { | ||
fn data_size(&self) -> usize { | ||
match self { | ||
Self::KeyMatrix => size_of::<[u8; 13]>(), | ||
Self::HostEvent => size_of::<u32>(), | ||
Self::SensorFifo => size_of::<EcResponseMotionSenseFifoInfo>(), | ||
Self::Buttons => size_of::<u32>(), | ||
Self::Switches => size_of::<u32>(), | ||
Self::Fingerprint => size_of::<u32>(), | ||
Self::Sysrq => size_of::<u32>(), | ||
Self::HostEvent64 => size_of::<u64>(), | ||
Self::CecEvent => size_of::<u32>(), | ||
_ => 0, | ||
} | ||
} | ||
|
||
pub(crate) fn read<T: Read>(&self, stream: &mut T) -> io::Result<EcMkbpEvent> { | ||
let mut event = vec![Default::default(); size_of::<Self>() + self.data_size()]; | ||
stream.read_exact(&mut event)?; | ||
debug_assert_eq!(event[0], *self as u8); | ||
event.remove(0); | ||
let data = event; | ||
Ok(match self { | ||
EcMkbpEventType::Fingerprint => { | ||
EcMkbpEvent::Fingerprint(from_bytes::<EcMkbpEventFingerprint>(&data).to_owned()) | ||
} | ||
event_type => panic!("{event_type:#?} from_bytes not implemented yet"), | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
use std::fmt::Debug; | ||
|
||
use bytemuck::{Pod, Zeroable}; | ||
|
||
#[derive(Debug)] | ||
pub enum EcMkbpEventFingerprintEnrollError { | ||
LowQuality, | ||
Immobile, | ||
LowCoverage, | ||
Internal, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct EcMkbpEventFingerprintEnroll { | ||
pub percentage: u8, | ||
pub error: Option<EcMkbpEventFingerprintEnrollError>, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct EcMkbpEventFingerprintMatch { | ||
pub index: usize, | ||
/// If `Some`, his means that the fingerprint matched an existing template and the existing template was updated to more accurately match future fingerprints. | ||
/// `None` if `EC_MKBP_FP_ERR_MATCH_YES`. | ||
/// `Some(Ok)` if `EC_MKBP_FP_ERR_MATCH_YES_UPDATED`. | ||
/// `Some(Err)` if `EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED`. | ||
// TODO: Find the CrOS EC documentation for this and add the link here | ||
pub update: Option<Result<(), ()>>, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum EcMkbpEventFingerprintNoMatchError { | ||
/// `EC_MKBP_FP_ERR_MATCH_NO_INTERNAL` - Probably means there was an internal error. | ||
Internal, | ||
/// `EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES` - This either means there are no templates, or something's wrong with the templates. Idk which one. | ||
Templates, | ||
/// `EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY` - My guess is this might happen if the sensor or finger is dirty | ||
LowQuality, | ||
/// `EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE` - My guess is this might happen if only a small part of a finger is sensed | ||
LowCoverage, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum EcMkbpEventFingerprintMatchResult { | ||
Match(EcMkbpEventFingerprintMatch), | ||
NoMatch(Result<(), EcMkbpEventFingerprintNoMatchError>), | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum EcMkbpEventFingerprintRust { | ||
/// Contains the enroll progress, as a percentage | ||
Enroll(EcMkbpEventFingerprintEnroll), | ||
Match(EcMkbpEventFingerprintMatchResult), | ||
FingerDown, | ||
FingerUp, | ||
ImageReady, | ||
} | ||
|
||
const EC_MKBP_EVENT_FINGERPRINT_ERROR_MASK: u32 = 0x0000000F; | ||
|
||
#[derive(Clone, Copy, Pod, Zeroable)] | ||
#[repr(C)] | ||
pub struct EcMkbpEventFingerprint { | ||
fp_events: u32, | ||
} | ||
impl EcMkbpEventFingerprint { | ||
/// Get a Rust-friendly format. Uses CPU to call and format uses more memory. | ||
pub fn rust(&self) -> EcMkbpEventFingerprintRust { | ||
match self.fp_events { | ||
fp_events if fp_events & (1 << 27) != 0 => { | ||
EcMkbpEventFingerprintRust::Enroll(EcMkbpEventFingerprintEnroll { | ||
percentage: ((self.fp_events & 0x00000FF0) >> 4).try_into().unwrap(), | ||
error: match self.fp_events & EC_MKBP_EVENT_FINGERPRINT_ERROR_MASK { | ||
0 => None, | ||
1 => Some(EcMkbpEventFingerprintEnrollError::LowQuality), | ||
2 => Some(EcMkbpEventFingerprintEnrollError::Immobile), | ||
3 => Some(EcMkbpEventFingerprintEnrollError::LowCoverage), | ||
5 => Some(EcMkbpEventFingerprintEnrollError::Internal), | ||
unknown_error => panic!("Unknown error: {unknown_error}"), | ||
}, | ||
}) | ||
} | ||
fp_events if fp_events & (1 << 28) != 0 => EcMkbpEventFingerprintRust::Match({ | ||
let code = self.fp_events & EC_MKBP_EVENT_FINGERPRINT_ERROR_MASK; | ||
let get_match_index = || ((self.fp_events & 0x0000F000) >> 12) as usize; | ||
match code { | ||
0 => EcMkbpEventFingerprintMatchResult::NoMatch(Ok(())), | ||
6 => EcMkbpEventFingerprintMatchResult::NoMatch(Err( | ||
EcMkbpEventFingerprintNoMatchError::Internal, | ||
)), | ||
7 => EcMkbpEventFingerprintMatchResult::NoMatch(Err( | ||
EcMkbpEventFingerprintNoMatchError::Templates, | ||
)), | ||
2 => EcMkbpEventFingerprintMatchResult::NoMatch(Err( | ||
EcMkbpEventFingerprintNoMatchError::LowQuality, | ||
)), | ||
4 => EcMkbpEventFingerprintMatchResult::NoMatch(Err( | ||
EcMkbpEventFingerprintNoMatchError::LowCoverage, | ||
)), | ||
1 => EcMkbpEventFingerprintMatchResult::Match(EcMkbpEventFingerprintMatch { | ||
index: get_match_index(), | ||
update: None, | ||
}), | ||
3 => EcMkbpEventFingerprintMatchResult::Match(EcMkbpEventFingerprintMatch { | ||
index: get_match_index(), | ||
update: Some(Ok(())), | ||
}), | ||
5 => EcMkbpEventFingerprintMatchResult::Match(EcMkbpEventFingerprintMatch { | ||
index: get_match_index(), | ||
update: Some(Err(())), | ||
}), | ||
code => panic!("Unknown error code: {code} ({code:#b})"), | ||
} | ||
}), | ||
fp_events if fp_events & (1 << 29) != 0 => EcMkbpEventFingerprintRust::FingerDown, | ||
fp_events if fp_events & (1 << 30) != 0 => EcMkbpEventFingerprintRust::FingerUp, | ||
fp_events if fp_events & (1 << 31) != 0 => EcMkbpEventFingerprintRust::ImageReady, | ||
fp_events => panic!("Unknown FP event: {fp_events} ({fp_events:#b})"), | ||
} | ||
} | ||
} | ||
impl Debug for EcMkbpEventFingerprint { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
self.rust().fmt(f) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
use std::{fs::File, os::fd::AsRawFd}; | ||
|
||
use event::{EcMkbpEvent, EcMkbpEventType}; | ||
use nix::{ | ||
libc::{ioctl, poll, pollfd}, | ||
request_code_none, | ||
}; | ||
|
||
use crate::CROS_EC_IOC_MAGIC; | ||
|
||
pub mod event; | ||
pub mod fingerprint; | ||
|
||
const POLL_IN: i16 = 0x001; | ||
|
||
#[derive(Debug)] | ||
pub enum PollData { | ||
EventHappened(EcMkbpEvent), | ||
Timeout, | ||
SomethingElseHappened(i16), | ||
} | ||
|
||
pub fn wait_event( | ||
file: &mut File, | ||
event_type: EcMkbpEventType, | ||
timeout: i32, | ||
) -> Result<PollData, i32> { | ||
let mask = 1 << event_type as u8; | ||
unsafe { | ||
ioctl( | ||
file.as_raw_fd(), | ||
request_code_none!(CROS_EC_IOC_MAGIC, 2), | ||
mask, | ||
) | ||
}; | ||
let mut fds = pollfd { | ||
fd: file.as_raw_fd(), | ||
events: POLL_IN, | ||
revents: Default::default(), | ||
}; | ||
let result = unsafe { poll(&mut fds, 1, timeout) }; | ||
match result { | ||
0 => Ok(PollData::Timeout), | ||
1 => match fds.revents { | ||
POLL_IN => Ok(PollData::EventHappened(event_type.read(file).unwrap())), | ||
events => Ok(PollData::SomethingElseHappened(events)), | ||
}, | ||
result => Err(result), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters