-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More commands #4
Merged
Merged
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
b84a185
Use clap for an actual ectool CLI
ChocolateLoverRaj 1ba33c6
Board version command
ChocolateLoverRaj 227d7ad
Get command versions
ChocolateLoverRaj fded85b
Command version constants
ChocolateLoverRaj 1d61b72
Set fan target RPM
ChocolateLoverRaj a94d8ce
Get EC features
ChocolateLoverRaj ed15d21
Get number of fans
ChocolateLoverRaj 14f2a73
Get fan RPM
ChocolateLoverRaj 1120872
ectool console
ChocolateLoverRaj 5e1b846
Battery command
ChocolateLoverRaj 7f4d0aa
Charge control commands
ChocolateLoverRaj a33802e
Add hello and console commands for cros_fp
ChocolateLoverRaj 614d48d
remove unused EcInterface enum
ChocolateLoverRaj 4bfb52f
fp-info command
ChocolateLoverRaj 2808fdb
fp-stats command
ChocolateLoverRaj 1d1d30a
set fp seed command
ChocolateLoverRaj 06efbf5
fp mode command
ChocolateLoverRaj cb213aa
wait_event function
ChocolateLoverRaj 9625eb1
Use &mut File instead of raw fd for safe functions
ChocolateLoverRaj cc8858e
Download fp frame and templates
ChocolateLoverRaj 4a81f0c
Move charge control subcommand to new file
ChocolateLoverRaj c4b3560
Upload template command
ChocolateLoverRaj 6da00c5
Add clap feature to crosec for better fp-mode command
ChocolateLoverRaj 80f4101
Add no-timeout mode to wait_event
ChocolateLoverRaj 16e89ed
clap::ValueEnum for EcMkbpEventType
ChocolateLoverRaj b086358
Better fp-seed bad seed feedback
ChocolateLoverRaj 37a554e
Add version and about to ectool
ChocolateLoverRaj 22e0d43
Remove unused EcParamsReadMem
ChocolateLoverRaj 311b3b0
Nix flake
ChocolateLoverRaj a64baa9
Use trait for File in `fp_mode`
ChocolateLoverRaj a2d5504
Some improvements
ChocolateLoverRaj a8121a0
Add HostEvent enum
ChocolateLoverRaj 980e60e
No unused deps
ChocolateLoverRaj 94f055f
Get uptime info command
ChocolateLoverRaj 1c8d728
Multiple event types when waiting for event
ChocolateLoverRaj 05120f1
cargo fmt
ChocolateLoverRaj c64772c
Meet cargo clippy rules
ChocolateLoverRaj e497559
Charge current limit command
ChocolateLoverRaj 10417b1
fix: use lossy conversion
lleyton File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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,72 @@ | ||
use crate::commands::get_cmd_versions::{ec_cmd_get_cmd_versions, V1}; | ||
use crate::commands::CrosEcCmd; | ||
use crate::read_mem_any::read_mem_any; | ||
use crate::read_mem_string::read_mem_string; | ||
use crate::{ | ||
EcCmdResult, EC_MEM_MAP_BATTERY_CAPACITY, EC_MEM_MAP_BATTERY_CYCLE_COUNT, | ||
EC_MEM_MAP_BATTERY_DESIGN_CAPACITY, EC_MEM_MAP_BATTERY_DESIGN_VOLTAGE, | ||
EC_MEM_MAP_BATTERY_FLAGS, EC_MEM_MAP_BATTERY_LAST_FULL_CHARGE_CAPACITY, | ||
EC_MEM_MAP_BATTERY_MANUFACTURER, EC_MEM_MAP_BATTERY_MODEL, EC_MEM_MAP_BATTERY_RATE, | ||
EC_MEM_MAP_BATTERY_SERIAL, EC_MEM_MAP_BATTERY_TYPE, EC_MEM_MAP_BATTERY_VERSION, | ||
EC_MEM_MAP_BATTERY_VOLTAGE, | ||
}; | ||
use std::fs::File; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct BatteryInfo { | ||
pub oem_name: String, | ||
pub model_number: String, | ||
pub chemistry: String, | ||
pub serial_number: String, | ||
pub design_capacity: i32, | ||
pub last_full_charge: i32, | ||
pub design_output_voltage: i32, | ||
pub cycle_count: i32, | ||
pub present_voltage: i32, | ||
pub present_current: i32, | ||
pub remaining_capacity: i32, | ||
pub flags: u8, | ||
} | ||
|
||
pub fn battery(file: &mut File) -> EcCmdResult<BatteryInfo> { | ||
if ec_cmd_get_cmd_versions(file, CrosEcCmd::BatteryGetStatic)? & V1 != 0 { | ||
panic!( | ||
"Battery info needs to be gotten with the {:?} command", | ||
CrosEcCmd::BatteryGetStatic | ||
); | ||
} else { | ||
let battery_version = read_mem_any::<i8>(file, EC_MEM_MAP_BATTERY_VERSION).unwrap(); | ||
if battery_version < 1 { | ||
panic!("Battery version {battery_version} is not supported"); | ||
} | ||
let flags = read_mem_any::<u8>(file, EC_MEM_MAP_BATTERY_FLAGS).unwrap(); | ||
let oem_name = read_mem_string(file, EC_MEM_MAP_BATTERY_MANUFACTURER).unwrap(); | ||
let model_number = read_mem_string(file, EC_MEM_MAP_BATTERY_MODEL).unwrap(); | ||
let chemistry = read_mem_string(file, EC_MEM_MAP_BATTERY_TYPE).unwrap(); | ||
let serial_number = read_mem_string(file, EC_MEM_MAP_BATTERY_SERIAL).unwrap(); | ||
let design_capacity = | ||
read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_DESIGN_CAPACITY).unwrap(); | ||
let last_full_charge = | ||
read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_LAST_FULL_CHARGE_CAPACITY).unwrap(); | ||
let design_output_voltage = | ||
read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_DESIGN_VOLTAGE).unwrap(); | ||
let cycle_count = read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_CYCLE_COUNT).unwrap(); | ||
let present_voltage = read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_VOLTAGE).unwrap(); | ||
let present_current = read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_RATE).unwrap(); | ||
let remaining_capacity = read_mem_any::<i32>(file, EC_MEM_MAP_BATTERY_CAPACITY).unwrap(); | ||
Ok(BatteryInfo { | ||
flags, | ||
oem_name, | ||
model_number, | ||
chemistry, | ||
serial_number, | ||
design_capacity, | ||
last_full_charge, | ||
design_output_voltage, | ||
cycle_count, | ||
present_voltage, | ||
present_current, | ||
remaining_capacity, | ||
}) | ||
} | ||
} |
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,10 @@ | ||
use std::fs::File; | ||
use std::os::fd::AsRawFd; | ||
|
||
use crate::commands::CrosEcCmd; | ||
use crate::ec_command::ec_command_bytemuck; | ||
use crate::EcCmdResult; | ||
|
||
pub fn ec_cmd_board_version(file: &mut File) -> EcCmdResult<u32> { | ||
ec_command_bytemuck(CrosEcCmd::GetBoardVersion, 0, &(), file.as_raw_fd()) | ||
} |
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,76 @@ | ||
use crate::commands::get_cmd_versions::{ec_cmd_get_cmd_versions, V2}; | ||
use crate::commands::CrosEcCmd; | ||
use crate::ec_command::ec_command_bytemuck; | ||
use crate::EcCmdResult; | ||
use bytemuck::{Pod, Zeroable}; | ||
use std::os::fd::AsRawFd; | ||
|
||
#[repr(C)] | ||
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)] | ||
pub struct Sustainer { | ||
pub min_percent: i8, | ||
pub max_percent: i8, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum ChargeControl { | ||
Normal(Option<Sustainer>), | ||
Idle, | ||
Discharge, | ||
} | ||
|
||
pub fn supports_get_and_sustainer<File: AsRawFd>(file: &mut File) -> EcCmdResult<bool> { | ||
let versions = ec_cmd_get_cmd_versions(file, CrosEcCmd::ChargeControl)?; | ||
Ok(versions & V2 != 0) | ||
} | ||
|
||
#[repr(C)] | ||
#[derive(Pod, Zeroable, Copy, Clone)] | ||
pub struct EcParamsChargeControl { | ||
mode: u32, | ||
command: u8, | ||
reserved: u8, | ||
sustain: Sustainer, | ||
} | ||
|
||
const CHARGE_CONTROL_MODE_SET: u8 = 0; | ||
// const CHARGE_CONTROL_MODE_GET: u8 = 1; | ||
|
||
const CHARGE_CONTROL_COMMAND_NORMAL: u32 = 0; | ||
const CHARGE_CONTROL_COMMAND_IDLE: u32 = 1; | ||
const CHARGE_CONTROL_COMMAND_DISCHARGE: u32 = 2; | ||
|
||
pub fn get_charge_control<File: AsRawFd>(_file: &mut File) -> EcCmdResult<ChargeControl> { | ||
panic!("Not implemented yet"); | ||
} | ||
|
||
pub fn set_charge_control<File: AsRawFd>( | ||
file: &mut File, | ||
charge_control: ChargeControl, | ||
) -> EcCmdResult<()> { | ||
ec_command_bytemuck( | ||
CrosEcCmd::ChargeControl, | ||
{ | ||
let version = ec_cmd_get_cmd_versions(file, CrosEcCmd::ChargeControl)?; | ||
Ok(if version & V2 != 0 { 2 } else { 1 }) | ||
}?, | ||
&EcParamsChargeControl { | ||
command: CHARGE_CONTROL_MODE_SET, | ||
mode: match charge_control { | ||
ChargeControl::Normal(_) => CHARGE_CONTROL_COMMAND_NORMAL, | ||
ChargeControl::Idle => CHARGE_CONTROL_COMMAND_IDLE, | ||
ChargeControl::Discharge => CHARGE_CONTROL_COMMAND_DISCHARGE, | ||
}, | ||
reserved: Default::default(), | ||
sustain: match charge_control { | ||
ChargeControl::Normal(sustain) => sustain.unwrap_or(Sustainer { | ||
min_percent: -1, | ||
max_percent: -1, | ||
}), | ||
_ => Default::default(), | ||
}, | ||
}, | ||
file.as_raw_fd(), | ||
)?; | ||
Ok(()) | ||
} |
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,29 @@ | ||
use std::os::fd::AsRawFd; | ||
|
||
use bytemuck::{Pod, Zeroable}; | ||
use uom::si::{electric_current::milliampere, f32::ElectricCurrent}; | ||
|
||
use crate::{ec_command::ec_command_bytemuck, EcCmdResult}; | ||
|
||
use super::CrosEcCmd; | ||
|
||
#[repr(C)] | ||
#[derive(Pod, Zeroable, Copy, Clone)] | ||
pub struct EcParamsChargeCurrentLimit { | ||
limit: u32, // in mA | ||
} | ||
|
||
/// Limit the charging current. The EC command sends the charging current limit to the nearest mA. | ||
pub fn set_charge_current_limit<File: AsRawFd>( | ||
file: &mut File, | ||
limit: ElectricCurrent, | ||
) -> EcCmdResult<()> { | ||
ec_command_bytemuck( | ||
CrosEcCmd::ChargeCurrentLimit, | ||
0, | ||
&EcParamsChargeCurrentLimit { | ||
limit: limit.get::<milliampere>() as u32, | ||
}, | ||
file.as_raw_fd(), | ||
) | ||
} |
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,115 @@ | ||
use std::{os::fd::AsRawFd, thread::sleep, time::Duration}; | ||
|
||
use bytemuck::{bytes_of, Pod, Zeroable}; | ||
|
||
use crate::ec_command::ec_command_with_dynamic_output_size; | ||
|
||
use super::{fp_info::EcResponseFpInfo, get_protocol_info::EcResponseGetProtocolInfo, CrosEcCmd}; | ||
|
||
#[repr(C)] | ||
#[derive(Pod, Zeroable, Clone, Copy)] | ||
struct EcParamsFpFrame { | ||
/// The offset contains the template index or FP_FRAME_INDEX_RAW_IMAGE | ||
/// in the high nibble, and the real offset within the frame in | ||
/// FP_FRAME_OFFSET_MASK. | ||
offset: u32, | ||
size: u32, | ||
} | ||
|
||
const FP_FRAME_INDEX_RAW_IMAGE: u32 = 0; | ||
|
||
/// This can be changed. `3` is what the ChromiumOS ectool uses. | ||
const MAX_ATTEMPTS: usize = 3; | ||
|
||
pub enum DownloadType { | ||
/// (aka `FP_FRAME_INDEX_SIMPLE_IMAGE`) for the a single grayscale image | ||
SimpleImage, | ||
/// (aka `FP_FRAME_INDEX_RAW_IMAGE`) for the full vendor raw finger image. | ||
RawImage, | ||
Template(usize), | ||
} | ||
|
||
/// Downloads a frame buffer from the FPMCU. | ||
/// The downloaded data might be either the finger image or a finger template. | ||
pub fn fp_download<File: AsRawFd>( | ||
file: &mut File, | ||
fp_info: &EcResponseFpInfo, | ||
protocol_info: &EcResponseGetProtocolInfo, | ||
download_type: &DownloadType, | ||
) -> Vec<u8> { | ||
let (size, index) = match download_type { | ||
DownloadType::SimpleImage => (fp_info.get_simple_image_size(), FP_FRAME_INDEX_RAW_IMAGE), | ||
DownloadType::RawImage => (fp_info.frame_size as usize, FP_FRAME_INDEX_RAW_IMAGE), | ||
DownloadType::Template(template_index) => { | ||
(fp_info.template_size as usize, *template_index as u32 + 1) | ||
} | ||
}; | ||
// The template may be (and probably is) bigger than the max output size, so we need to download it in chunks | ||
let number_of_chunks = size.div_ceil(protocol_info.max_ec_output_size()); | ||
let mut chunks = Vec::<Vec<u8>>::with_capacity(number_of_chunks); | ||
for chunk_index in 0..number_of_chunks { | ||
let bytes_read = chunk_index * protocol_info.max_ec_output_size(); | ||
let remaining_bytes = size - bytes_read; | ||
let current_chunk_size = remaining_bytes.min(protocol_info.max_ec_output_size()); | ||
let mut attempt = 0; | ||
loop { | ||
let result = ec_command_with_dynamic_output_size( | ||
CrosEcCmd::FpFrame, | ||
0, | ||
bytes_of(&EcParamsFpFrame { | ||
offset: (index << 28) + (bytes_read as u32), | ||
size: current_chunk_size as u32, | ||
}), | ||
current_chunk_size, | ||
file.as_raw_fd(), | ||
); | ||
if let Ok(chunk) = result { | ||
chunks.push(chunk); | ||
break; | ||
} else { | ||
attempt += 1; | ||
if attempt == MAX_ATTEMPTS { | ||
panic!("Could not successfully get the fp frame in {MAX_ATTEMPTS} attempts"); | ||
} | ||
// Using micros and not millis to be more like original `usleep(100000)` from ChromiumOS's ectool | ||
sleep(Duration::from_micros(100_000)); | ||
} | ||
} | ||
} | ||
chunks.concat() | ||
} | ||
|
||
/// A safe wrapper around the actual template so you don't try to upload arbitrary data | ||
pub struct FpTemplate { | ||
vec: Vec<u8>, | ||
} | ||
|
||
impl From<FpTemplate> for Vec<u8> { | ||
fn from(value: FpTemplate) -> Self { | ||
value.vec | ||
} | ||
} | ||
|
||
impl FpTemplate { | ||
pub fn buffer(&self) -> &Vec<u8> { | ||
&self.vec | ||
} | ||
|
||
/// Make sure your buffer is actually a compatible fp template | ||
/// # Safety | ||
/// Make sure you're uploading a template from the same FPMCU with the same version and the same seed set. | ||
pub unsafe fn from_vec_unchecked(vec: Vec<u8>) -> Self { | ||
|
||
FpTemplate { vec } | ||
} | ||
} | ||
|
||
pub fn fp_download_template<File: AsRawFd>( | ||
file: &mut File, | ||
fp_info: &EcResponseFpInfo, | ||
protocol_info: &EcResponseGetProtocolInfo, | ||
index: usize, | ||
) -> FpTemplate { | ||
FpTemplate { | ||
vec: fp_download(file, fp_info, protocol_info, &DownloadType::Template(index)), | ||
} | ||
} |
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,23 @@ | ||
use crate::commands::CrosEcCmd; | ||
use crate::ec_command::ec_command_bytemuck; | ||
use crate::EcCmdResult; | ||
use bytemuck::{Pod, Zeroable}; | ||
use std::os::fd::AsRawFd; | ||
|
||
#[repr(u32)] | ||
pub enum FpEncryptionStatus { | ||
SeedSet = 0b1, | ||
} | ||
|
||
#[derive(Pod, Zeroable, Copy, Clone)] | ||
#[repr(C)] | ||
pub struct EcResponseFpGetEncryptionStatus { | ||
pub valid_flags: u32, | ||
pub status: u32, | ||
} | ||
|
||
pub fn fp_get_encryption_status<File: AsRawFd>( | ||
file: &mut File, | ||
) -> EcCmdResult<EcResponseFpGetEncryptionStatus> { | ||
ec_command_bytemuck(CrosEcCmd::FpGetEncryptionStatus, 0, &(), file.as_raw_fd()) | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check warning
Code scanning / clippy
this function depends on never type fallback being () Warning