-
-
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.
Merge pull request #4 from ChocolateLoverRaj/more-commands
More commands
- Loading branch information
Showing
45 changed files
with
4,110 additions
and
323 deletions.
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.