diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index 2a22b89..1ebfff6 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -246,6 +246,16 @@ impl EcRequest<()> for EcRequestPwmSetFanDutyV1 { pub const PWM_MAX_DUTY: u16 = 0xFFFF; +pub fn percent_to_duty(percent: u8) -> u16 { + let duty = percent as u32 * PWM_MAX_DUTY as u32; + (duty / 100) as u16 +} + +pub fn duty_to_percent(duty: u16) -> u8 { + let percent = duty as u32 * 100; + (percent / PWM_MAX_DUTY as u32) as u8 +} + #[repr(C, packed)] pub struct EcRequestPwmSetDuty { /// Duty cycle, min 0, max 0xFFFF diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index 055ee75..f8d675f 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -770,24 +770,53 @@ impl CrosEc { /// * `percent` - An integer from 0 to 100. 0 being off, 100 being full brightness pub fn set_keyboard_backlight(&self, percent: u8) { debug_assert!(percent <= 100); + let duty = percent_to_duty(percent); + let res = EcRequestPwmSetDuty { - duty: percent as u16 * (PWM_MAX_DUTY / 100), + duty, pwm_type: PwmType::KbLight as u8, index: 0, } .send_command(self); + + // Early systems (hx20/hx30) don't enable CONFIG_PWM_KBLIGHT in their EC firmware; + // keyboard backlight is at generic PWM channel index 1. + let res = match res { + Err(EcError::Response(EcResponseStatus::InvalidParameter)) => { + EcRequestPwmSetDuty { + duty, + pwm_type: PwmType::Generic as u8, + index: 1, + } + .send_command(self) + } + other => other, + }; debug_assert!(res.is_ok()); } /// Check the current brightness of the keyboard backlight pub fn get_keyboard_backlight(&self) -> EcResult { - let kblight = EcRequestPwmGetDuty { + let res = EcRequestPwmGetDuty { pwm_type: PwmType::KbLight as u8, index: 0, } - .send_command(self)?; + .send_command(self); + + // Early systems (hx20/hx30) don't enable CONFIG_PWM_KBLIGHT in their EC firmware; + // keyboard backlight is at generic PWM channel index 1. + let kblight = match res { + Err(EcError::Response(EcResponseStatus::InvalidParameter)) => { + EcRequestPwmGetDuty { + pwm_type: PwmType::Generic as u8, + index: 1, + } + .send_command(self)? + } + other => other?, + }; - Ok((kblight.duty / (PWM_MAX_DUTY / 100)) as u8) + Ok(duty_to_percent(kblight.duty)) } pub fn ps2_emulation_enable(&self, enable: bool) -> EcResult<()> {