Skip to content

Commit

Permalink
Merge pull request #10 from ChocolateLoverRaj/get-charge-control
Browse files Browse the repository at this point in the history
Get charge control
  • Loading branch information
lleyton authored Dec 20, 2024
2 parents 6260a12 + e402e3f commit f820e09
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 32 deletions.
131 changes: 104 additions & 27 deletions crosec/src/commands/charge_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::ec_command::ec_command_bytemuck;
use crate::EcCmdResult;
use bytemuck::{Pod, Zeroable};
use std::os::fd::AsRawFd;
use strum_macros::FromRepr;

#[repr(C)]
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
Expand All @@ -13,7 +14,7 @@ pub struct Sustainer {
}

#[derive(Debug)]
pub enum ChargeControl {
pub enum SetChargeControl {
Normal(Option<Sustainer>),
Idle,
Discharge,
Expand All @@ -33,43 +34,119 @@ pub struct EcParamsChargeControl {
sustain: Sustainer,
}

const CHARGE_CONTROL_MODE_SET: u8 = 0;
// const CHARGE_CONTROL_MODE_GET: u8 = 1;
impl EcParamsChargeControl {
/// Get params to just get the charge control
fn get() -> Self {
let mut params = Self::zeroed();
params.command = ChargeControlCommand::Get as u8;
params
}
}

impl SetChargeControl {
fn to_set_params(&self) -> EcParamsChargeControl {
EcParamsChargeControl {
command: ChargeControlCommand::Set as u8,
mode: match self {
SetChargeControl::Normal(_) => ChargeControlMode::Normal,
SetChargeControl::Idle => ChargeControlMode::Idle,
SetChargeControl::Discharge => ChargeControlMode::Discharge,
} as u32,
reserved: Default::default(),
sustain: match self {
SetChargeControl::Normal(sustain) => sustain.unwrap_or(Sustainer {
min_percent: -1,
max_percent: -1,
}),
_ => Default::default(),
},
}
}
}

const CHARGE_CONTROL_COMMAND_NORMAL: u32 = 0;
const CHARGE_CONTROL_COMMAND_IDLE: u32 = 1;
const CHARGE_CONTROL_COMMAND_DISCHARGE: u32 = 2;
#[repr(C, align(4))]
#[derive(Pod, Zeroable, Clone, Copy)]
pub struct EcResponseChargeControl {
mode: u32,
sustainer: Sustainer,
reserved: u16,
}

#[repr(u8)]
#[derive(FromRepr)]
enum ChargeControlCommand {
Set,
Get,
}

#[repr(u32)]
#[derive(FromRepr, Debug, Clone, Copy)]
pub enum ChargeControlMode {
Normal,
Idle,
Discharge,
}

pub fn get_charge_control<File: AsRawFd>(_file: &mut File) -> EcCmdResult<ChargeControl> {
panic!("Not implemented yet");
#[derive(Debug, Clone, Copy)]
pub struct ChargeControlStatus {
pub mode: ChargeControlMode,
pub sustainer: Option<Sustainer>,
}

impl TryFrom<EcResponseChargeControl> for ChargeControlStatus {
type Error = String;

fn try_from(value: EcResponseChargeControl) -> Result<Self, Self::Error> {
Ok(Self {
mode: {
let charge_control_mode = value.mode;
ChargeControlMode::from_repr(charge_control_mode).ok_or(format!(
"Invalid charge control mode: {charge_control_mode}"
))?
},
sustainer: {
let sustainer = value.sustainer;
match sustainer {
Sustainer {
min_percent: -1,
max_percent: -1,
} => Ok(None),
Sustainer {
min_percent: 0..=100,
max_percent: 0..=100,
} => Ok(Some(sustainer)),
sustainer => Err(format!("Invalid sustainer value: {sustainer:?}")),
}
}?,
})
}
}

/// Not all Chromebooks support this. You can check if it's supported using [`supports_get_and_sustainer`]
pub fn get_charge_control<File: AsRawFd>(file: &mut File) -> EcCmdResult<ChargeControlStatus> {
let charge_control: EcResponseChargeControl = ec_command_bytemuck(
CrosEcCmd::ChargeControl,
2,
&EcParamsChargeControl::get(),
file.as_raw_fd(),
)?;
Ok(charge_control.try_into().unwrap())
}

pub fn set_charge_control<File: AsRawFd>(
file: &mut File,
charge_control: ChargeControl,
charge_control: SetChargeControl,
) -> EcCmdResult<()> {
ec_command_bytemuck(
CrosEcCmd::ChargeControl,
{
let version = ec_cmd_get_cmd_versions(file, CrosEcCmd::ChargeControl)?;
Ok(if version & V2 != 0 { 2 } else { 1 })
Ok(if supports_get_and_sustainer(file)? {
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(),
},
},
&charge_control.to_set_params(),
file.as_raw_fd(),
)?;
Ok(())
Expand Down
10 changes: 5 additions & 5 deletions ectool/src/charge_control_subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use clap::Subcommand;
use color_eyre::eyre::Result;
use crosec::{
commands::charge_control::{
get_charge_control, set_charge_control, supports_get_and_sustainer, ChargeControl,
get_charge_control, set_charge_control, supports_get_and_sustainer, SetChargeControl,
Sustainer,
},
CROS_EC_PATH,
Expand Down Expand Up @@ -46,25 +46,25 @@ pub fn charge_control_subcommand(command: Option<ChargeControlSubcommand>) -> Re
let max_percent = max_percent.unwrap_or(min_percent);
set_charge_control(
&mut file,
ChargeControl::Normal(Some(Sustainer {
SetChargeControl::Normal(Some(Sustainer {
min_percent: min_percent as i8,
max_percent: max_percent as i8,
})),
)?;
println!("Set charge control to normal with sustainer from {min_percent}% to {max_percent}%");
}
None => {
set_charge_control(&mut file, ChargeControl::Normal(None))?;
set_charge_control(&mut file, SetChargeControl::Normal(None))?;
println!("Set charge control to normal");
}
},
ChargeControlSubcommand::Idle => {
println!("Set charge control to idle");
set_charge_control(&mut file, ChargeControl::Idle)?;
set_charge_control(&mut file, SetChargeControl::Idle)?;
}
ChargeControlSubcommand::Discharge => {
println!("Set charge control to discharge");
set_charge_control(&mut file, ChargeControl::Discharge)?;
set_charge_control(&mut file, SetChargeControl::Discharge)?;
}
},
}
Expand Down

0 comments on commit f820e09

Please sign in to comment.